diff --git a/.gitignore b/.gitignore index 9fd1df3..b534ce4 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ Server/Server.iml target/* Server/Server.iml Server/src/main/java/META-INF/MANIFEST.MF +.settings +.project +.classpath \ No newline at end of file diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java index 8693776..9d573f9 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java @@ -10,13 +10,11 @@ import org.json.simple.JSONObject; import java.util.ArrayList; -public class Cubot extends GameObject implements Updatable, ControllableUnit, Programmable { +public class Cubot extends GameObject implements Updatable, ControllableUnit, Programmable, Attackable { private static final char MAP_INFO = 0x0080; public static final int ID = 1; - public static int TYPE_ID = 2; - private int hologram = 0; private String hologramString = ""; private HologramMode hologramMode = HologramMode.CLEARED; @@ -27,11 +25,16 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr * Hit points */ private int hp; + private int shield; + private int maxShield; private int heldItem; private Action currentAction = Action.IDLE; private Action lastAction = Action.IDLE; + private char currentStatus; + private char lastStatus; + private ArrayList keyboardBuffer = new ArrayList<>(); private ArrayList consoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE); @@ -90,6 +93,10 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr lastConsoleMessagesBuffer = new ArrayList<>(consoleMessagesBuffer); consoleMessagesBuffer.clear(); + + //And the status.. + lastStatus = currentStatus; + currentStatus = 0; } @Override @@ -102,6 +109,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr json.put("direction", getDirection().ordinal()); json.put("heldItem", heldItem); json.put("hp", hp); + json.put("shield", shield); json.put("action", lastAction.ordinal()); json.put("holo", hologram); json.put("holoStr", hologramString); @@ -127,6 +135,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr dbObject.put("direction", getDirection().ordinal()); dbObject.put("heldItem", heldItem); dbObject.put("hp", hp); + dbObject.put("shield", shield); dbObject.put("action", lastAction.ordinal()); dbObject.put("holo", hologram); dbObject.put("holoStr", hologramString); @@ -148,6 +157,8 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr cubot.setX((int) obj.get("x")); cubot.setY((int) obj.get("y")); cubot.hp = (int) obj.get("hp"); +// cubot.shield = (int) obj.get("shield"); +// cubot.maxShield = GameServer.INSTANCE.getConfig().getInt("max_shield"); cubot.setDirection(Direction.getDirection((int) obj.get("direction"))); cubot.heldItem = (int) obj.get("heldItem"); cubot.energy = (int) obj.get("energy"); @@ -240,6 +251,41 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr return maxEnergy; } + public int getShield() { + return shield; + } + + public void setShield(int shield) { + this.shield = shield; + } + + public boolean chargeShield(int qty) { + qty = Math.min(qty, maxShield - shield); + int cost = GameServer.INSTANCE.getConfig().getInt("shield_energy_cost"); + int energySpent = qty * cost; + if(spendEnergy(energySpent)) { + shield += qty; + return true; + } else { + return false; + } + } + + /** + * Damages shield by qty. + * + * Return damage that broke through the shield. + */ + public int damageShield(int qty) { + int after = shield - qty; + if(after < 0) { + shield = 0; + return -after; + } + shield = after; + return 0; + } + @Override public Memory getFloppyData() { @@ -305,4 +351,58 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr public void setHologramColor(int hologramColor) { this.hologramColor = hologramColor; } + + public void addStatus(CubotStatus status) { + + currentStatus |= status.val; + } + + public void removeStatus(CubotStatus status) { + + currentStatus &= (~status.val); + } + + public char getStatus() { + return lastStatus; + } + + @Override + public void setHealRate(int hp) { + + } + + @Override + public int getHp() { + return 0; + } + + @Override + public void setHp(int hp) { + + } + + @Override + public int getMaxHp() { + return 0; + } + + @Override + public void setMaxHp(int hp) { + + } + + @Override + public void heal(int amount) { + + } + + @Override + public void damage(int amount) { + + } + + @Override + public boolean onDeadCallback() { + return true; //always cancelled + } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotCore.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotCore.java new file mode 100644 index 0000000..021dc62 --- /dev/null +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotCore.java @@ -0,0 +1,59 @@ +package net.simon987.cubotplugin; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; +import net.simon987.server.GameServer; +import net.simon987.server.assembly.CpuHardware; +import net.simon987.server.assembly.Status; + +public class CubotCore extends CpuHardware { + + public static final int DEFAULT_ADDRESS = 0x000E; + + /** + * Hardware ID (Should be unique) + */ + public static final char HWID = 0x000E; + + private static final int CORE_STATUS_POLL = 1; + private static final int CORE_HULL_POLL = 2; + + private Cubot cubot; + + public CubotCore(Cubot cubot) { + this.cubot = cubot; + } + + @Override + public void handleInterrupt(Status status) { + + int a = getCpu().getRegisterSet().getRegister("A").getValue(); + + if (a == CORE_STATUS_POLL) { + getCpu().getRegisterSet().getRegister("B").setValue(cubot.getStatus()); + } else if (a == CORE_HULL_POLL) { + getCpu().getRegisterSet().getRegister("B").setValue(cubot.getHp()); + } + } + + @Override + public char getId() { + return HWID; + } + + @Override + public BasicDBObject mongoSerialise() { + + BasicDBObject dbObject = new BasicDBObject(); + + dbObject.put("hwid", (int) HWID); + dbObject.put("cubot", cubot.getObjectId()); + + return dbObject; + } + + + public static CubotCore deserialize(DBObject obj) { + return new CubotCore((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); + } +} diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java index abbe674..c4ac143 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java @@ -60,6 +60,8 @@ public class CubotPlugin extends ServerPlugin implements GameObjectDeserializer, return CubotFloppyDrive.deserialize(obj); case CubotComPort.HWID: return CubotComPort.deserialize(obj); + case CubotShield.HWID: + return CubotShield.deserialize(obj); } return null; diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotShield.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotShield.java new file mode 100644 index 0000000..0491b35 --- /dev/null +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotShield.java @@ -0,0 +1,51 @@ +package net.simon987.cubotplugin; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; +import net.simon987.server.GameServer; +import net.simon987.server.assembly.CpuHardware; +import net.simon987.server.assembly.Status; + +public class CubotShield extends CpuHardware { + static final char HWID = 0x000F; + + private static final int SHIELD_CHARGE = 1; + private static final int SHIELD_POLL = 2; + private Cubot cubot; + + public CubotShield(Cubot cubot) { + this.cubot = cubot; + } + + @Override + public char getId() { + return HWID; + } + + @Override + public BasicDBObject mongoSerialise() { + BasicDBObject dbObject = new BasicDBObject(); + + dbObject.put("hwid", HWID); + dbObject.put("cubot", cubot.getObjectId()); + + return dbObject; + } + + @Override + public void handleInterrupt(Status status) { + int a = getCpu().getRegisterSet().getRegister("A").getValue(); + // b = amount to charge + if(a == SHIELD_CHARGE) { + int b = getCpu().getRegisterSet().getRegister("B").getValue(); + cubot.chargeShield(b); + } else if (a == SHIELD_POLL) { + int shield = cubot.getShield(); + getCpu().getRegisterSet().getRegister("B").setValue(shield); + } + } + + public static CubotShield deserialize(DBObject obj) { + return new CubotShield((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); + } +} \ No newline at end of file diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotStatus.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotStatus.java new file mode 100644 index 0000000..bb16666 --- /dev/null +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotStatus.java @@ -0,0 +1,18 @@ +package net.simon987.cubotplugin; + +/** + * Status of a Cubot (Special buff or debuff) + */ +public enum CubotStatus { + + DEFAULT(0), + RADIATED(1), + DAMAGED(2); + + public char val; + + CubotStatus(int val) { + this.val = (char) val; + } + +} diff --git a/Server/src/main/java/net/simon987/server/Main.java b/Server/src/main/java/net/simon987/server/Main.java index 2b93634..cab15d0 100644 --- a/Server/src/main/java/net/simon987/server/Main.java +++ b/Server/src/main/java/net/simon987/server/Main.java @@ -9,9 +9,9 @@ import java.net.InetSocketAddress; public class Main { public static void main(String[] args) { - - LogManager.initialize(); ServerConfiguration config = new ServerConfiguration("config.properties"); + LogManager.initialize(config); + //Load GameServer.INSTANCE.load(); diff --git a/Server/src/main/java/net/simon987/server/assembly/CPU.java b/Server/src/main/java/net/simon987/server/assembly/CPU.java index 873907f..1643ed6 100755 --- a/Server/src/main/java/net/simon987/server/assembly/CPU.java +++ b/Server/src/main/java/net/simon987/server/assembly/CPU.java @@ -99,6 +99,8 @@ public class CPU implements MongoSerialisable { instructionSet.add(new JoInstruction(this)); instructionSet.add(new PushfInstruction(this)); instructionSet.add(new PopfInstruction(this)); + instructionSet.add(new JnaInstruction(this)); + instructionSet.add(new JaInstruction(this)); status = new Status(); memory = new Memory(config.getInt("memory_size")); diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/JaInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/JaInstruction.java new file mode 100644 index 0000000..20dca0f --- /dev/null +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/JaInstruction.java @@ -0,0 +1,38 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.CPU; +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; + +/** + * Jump if above + */ +public class JaInstruction extends Instruction { + + public static final int OPCODE = 46; + + private CPU cpu; + + public JaInstruction(CPU cpu) { + super("ja", OPCODE); + + this.cpu = cpu; + } + + @Override + public Status execute(Target src, int srcIndex, Status status) { + if (!status.isCarryFlag() && !status.isZeroFlag()) { + cpu.setIp((char) src.get(srcIndex)); + } + return status; + } + + @Override + public Status execute(int src, Status status) { + if (!status.isCarryFlag() && !status.isZeroFlag()) { + cpu.setIp((char) src); + } + return status; + } +} diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/JnaInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/JnaInstruction.java new file mode 100644 index 0000000..e143f7e --- /dev/null +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/JnaInstruction.java @@ -0,0 +1,38 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.CPU; +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; + +/** + * Jump if not above + */ +public class JnaInstruction extends Instruction { + + public static final int OPCODE = 47; + + private CPU cpu; + + public JnaInstruction(CPU cpu) { + super("jna", OPCODE); + + this.cpu = cpu; + } + + @Override + public Status execute(Target src, int srcIndex, Status status) { + if (status.isCarryFlag() || status.isZeroFlag()) { + cpu.setIp((char) src.get(srcIndex)); + } + return status; + } + + @Override + public Status execute(int src, Status status) { + if (status.isCarryFlag() || status.isZeroFlag()) { + cpu.setIp((char) src); + } + return status; + } +} \ No newline at end of file diff --git a/Server/src/main/java/net/simon987/server/game/GameObject.java b/Server/src/main/java/net/simon987/server/game/GameObject.java index 51426d7..e0530a8 100755 --- a/Server/src/main/java/net/simon987/server/game/GameObject.java +++ b/Server/src/main/java/net/simon987/server/game/GameObject.java @@ -254,7 +254,7 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable /** * Called before this GameObject is removed from the world - defaults to doing nothing - * @return cancelled + * @return true if cancelled */ public boolean onDeadCallback() { return false; diff --git a/Server/src/main/java/net/simon987/server/game/World.java b/Server/src/main/java/net/simon987/server/game/World.java index 0ec02e9..893e688 100644 --- a/Server/src/main/java/net/simon987/server/game/World.java +++ b/Server/src/main/java/net/simon987/server/game/World.java @@ -159,6 +159,7 @@ public class World implements MongoSerialisable { if (object.isDead()) { if (!object.onDeadCallback()) { removeObject(object); + //LogManager.LOGGER.fine("Removed object " + object + " id: " + object.getObjectId()); } } else if (object instanceof Updatable) { diff --git a/Server/src/main/java/net/simon987/server/logging/LogManager.java b/Server/src/main/java/net/simon987/server/logging/LogManager.java index 47b11e3..33cc974 100755 --- a/Server/src/main/java/net/simon987/server/logging/LogManager.java +++ b/Server/src/main/java/net/simon987/server/logging/LogManager.java @@ -1,5 +1,7 @@ package net.simon987.server.logging; +import net.simon987.server.ServerConfiguration; + import java.io.IOException; import java.util.logging.*; @@ -16,7 +18,7 @@ public class LogManager { /** * Initialises the logger */ - public static void initialize() { + public static void initialize(ServerConfiguration config) { LOGGER.setUseParentHandlers(false); /* @@ -45,15 +47,18 @@ public class LogManager { handler.setLevel(Level.ALL); try { - Handler fileHandler = new FileHandler("mar.log"); + Handler fileHandler = new FileHandler("mar-%g.log", config.getInt("log_limit"), + config.getInt("log_count")); fileHandler.setLevel(Level.ALL); fileHandler.setFormatter(new GenericFormatter()); + LOGGER.addHandler(handler); LOGGER.addHandler(errHandler); LOGGER.addHandler(fileHandler); LOGGER.setLevel(Level.ALL); + } catch (IOException e) { e.printStackTrace(); } diff --git a/Server/src/main/resources/config.properties b/Server/src/main/resources/config.properties index ed7e637..5032170 100644 --- a/Server/src/main/resources/config.properties +++ b/Server/src/main/resources/config.properties @@ -6,8 +6,8 @@ mysql_pass=mar mysql_url=jdbc:mysql://localhost:3306/mar?useSSL=false # File management save_interval=5 -clean_interval=10 -history_size=10 +log_limit=2000000 +log_count=10 # Web server port webSocket_port=8887 webSocket_host=0.0.0.0 @@ -49,6 +49,10 @@ maxBiomassRespawnCount=6 biomassEnergyValue=4000 # Maximum energy of the battery hardware in kJ battery_max_energy=60000 +# Maximum shield power +max_shield=100 +# Energy cost per unit to charge shield +shield_energy_cost=50 # Time for biomass respawn in ticks biomassRespawnTime=64 # Respawn timer will start when biomass count is below this number