diff --git a/.gitignore b/.gitignore index 91faeca..9fd1df3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ mar.log.lck plugins/*.jar save.json Server/Server.iml +target/* +Server/Server.iml +Server/src/main/java/META-INF/MANIFEST.MF 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 c2d871f..0eb1a47 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java @@ -8,16 +8,16 @@ import org.json.simple.JSONObject; import java.util.ArrayList; -public class Cubot extends GameObject implements Updatable, ControllableUnit { +public class Cubot extends GameObject implements Updatable, ControllableUnit, Programmable { private static final char MAP_INFO = 0x0080; public static final int ID = 1; - private char hologram = 0; + private int hologram = 0; private String hologramString = ""; private HologramMode hologramMode = HologramMode.CLEARED; - - private char lastHologram = 0; + private HologramMode lastHologramMode = HologramMode.CLEARED; + private int hologramColor = 0; /** * Hit points @@ -30,7 +30,10 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { private ArrayList keyboardBuffer = new ArrayList<>(); - private FloppyDisk floppyDisk; + private ArrayList consoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE); + private ArrayList lastConsoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE); + private ConsoleMode consoleMode = ConsoleMode.NORMAL; + private ConsoleMode lastConsoleMode = ConsoleMode.NORMAL; private User parent; @@ -38,6 +41,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { private int maxEnergy; private static final float SOLAR_PANEL_MULTIPLIER = 1; + private static final int CONSOLE_BUFFER_MAX_SIZE = 40; public Cubot() { @@ -73,8 +77,15 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { currentAction = Action.IDLE; //Same principle for hologram - lastHologram = hologram; - hologram = 0; + lastHologramMode = hologramMode; + hologramMode = HologramMode.CLEARED; + + //And the console + lastConsoleMode = consoleMode; + consoleMode = ConsoleMode.NORMAL; + + lastConsoleMessagesBuffer = new ArrayList<>(consoleMessagesBuffer); + consoleMessagesBuffer.clear(); } @Override @@ -88,9 +99,10 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { json.put("heldItem", heldItem); json.put("hp", hp); json.put("action", lastAction.ordinal()); - json.put("holo", (int) lastHologram); + json.put("holo", hologram); json.put("holoStr", hologramString); - json.put("holoMode", hologramMode.ordinal()); + json.put("holoMode", lastHologramMode.ordinal()); + json.put("holoC", hologramColor); json.put("energy", energy); if (parent != null) { @@ -158,13 +170,10 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { return currentAction; } - public void setHologram(char hologram) { + public void setHologram(int hologram) { this.hologram = hologram; } - public char getHologram() { - return lastHologram; - } public void setHologramString(String hologramString) { this.hologramString = hologramString; @@ -226,6 +235,42 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { public enum HologramMode { CLEARED, HEX, - STRING + STRING, + DEC + } + + public enum ConsoleMode { + CLEAR, + NORMAL + } + + @Override + public void setAction(Action action) { + currentAction = action; + } + + @Override + public void sendMessage(char[] message) { + + if (consoleMessagesBuffer.size() < CONSOLE_BUFFER_MAX_SIZE) { + consoleMessagesBuffer.add(message); + } + } + + public ArrayList getConsoleMessagesBuffer() { + return lastConsoleMessagesBuffer; + } + + + public int getConsoleMode() { + return lastConsoleMode.ordinal(); + } + + public void setConsoleMode(ConsoleMode consoleMode) { + this.consoleMode = consoleMode; + } + + public void setHologramColor(int hologramColor) { + this.hologramColor = hologramColor; } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotComPort.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotComPort.java new file mode 100644 index 0000000..506c1b5 --- /dev/null +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotComPort.java @@ -0,0 +1,132 @@ +package net.simon987.cubotplugin; + +import net.simon987.server.GameServer; +import net.simon987.server.assembly.CpuHardware; +import net.simon987.server.assembly.Status; +import net.simon987.server.game.GameObject; +import net.simon987.server.game.Programmable; +import org.json.simple.JSONObject; + +import java.awt.*; +import java.util.ArrayList; + +public class CubotComPort extends CpuHardware { + + public static final char HWID = 0xD; + public static final int DEFAULT_ADDRESS = 0xD; + + private Cubot cubot; + + private static final int SELF_CLEAR = 0; + private static final int POLL = 1; + private static final int FRONT_PORT_OUT = 2; + private static final int SELF_OUT = 3; + + public CubotComPort(Cubot cubot) { + this.cubot = cubot; + } + + private static final int MESSAGE_LENGTH = 8; + + @Override + public void handleInterrupt(Status status) { + + int a = getCpu().getRegisterSet().getRegister("A").getValue(); + + if (a == SELF_CLEAR) { + + cubot.getConsoleMessagesBuffer().clear(); + cubot.setConsoleMode(Cubot.ConsoleMode.CLEAR); + + } else if (a == POLL) { + + if (cubot.spendEnergy(4)) { + + int x = getCpu().getRegisterSet().getRegister("X").getValue(); + + //Read all messages in the console buffer to memory at X + + for (char[] message : cubot.getConsoleMessagesBuffer()) { + if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) { + //todo set interrupt ? + getCpu().getStatus().setErrorFlag(true); + } else { + System.arraycopy(message, 0, getCpu().getMemory().getWords(), x, MESSAGE_LENGTH); + } + } + + //Set B = number of messages + getCpu().getRegisterSet().getRegister("B").setValue(cubot.getConsoleMessagesBuffer().size()); + + } + + } else if (a == FRONT_PORT_OUT) { + + if (cubot.spendEnergy(20)) { + //Get object directly in front of the Cubot + Point frontTile = cubot.getFrontTile(); + //Todo will have to add getGameObjectsBlockingAt to enable Factory + ArrayList objects = cubot.getWorld().getGameObjectsAt(frontTile.x, frontTile.y); + + if (objects.size() > 0 && objects.get(0) instanceof Programmable) { + + int x = getCpu().getRegisterSet().getRegister("X").getValue(); + + if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) { + //todo set interrupt ? + getCpu().getStatus().setErrorFlag(true); + } else { + + //Get MESSAGE_LENGTH-word message pointed by X + char[] message = new char[MESSAGE_LENGTH]; + System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH); + + //Send it to the Programmable object + ((Programmable) objects.get(0)).sendMessage(message); + + System.out.println("Sent message to " + ((Cubot) objects.get(0)).getParent().getUsername()); + } + } + } + + } else if (a == SELF_OUT) { + + if (cubot.spendEnergy(1)) { + + int x = getCpu().getRegisterSet().getRegister("X").getValue(); + + //Write a single message to console buffer + if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) { + //todo set interrupt ? + getCpu().getStatus().setErrorFlag(true); + } else { + + //Get MESSAGE_LENGTH-word message pointed by X + char[] message = new char[MESSAGE_LENGTH]; + System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH); + cubot.sendMessage(message); + } + } + } + + + } + + @Override + public char getId() { + return HWID; + } + + @Override + public JSONObject serialise() { + JSONObject json = new JSONObject(); + json.put("hwid", (int) HWID); + json.put("cubot", cubot.getObjectId()); + + return json; + } + + public static CubotComPort deserialize(JSONObject json) { + return new CubotComPort((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((int) (long) json.get("cubot"))); + } +} diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHologram.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHologram.java index 7e07839..28cdfcf 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHologram.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHologram.java @@ -20,6 +20,8 @@ public class CubotHologram extends CpuHardware { private static final int CLEAR = 0; private static final int DISPLAY_HEX = 1; private static final int DISPLAY_STRING = 2; + private static final int DISPLAY_DEC = 3; + private static final int DISPLAY_COLOR = 4; private static final int STR_MAX_LEN = 8; @@ -57,6 +59,20 @@ public class CubotHologram extends CpuHardware { cubot.setHologramString(holoString.toString()); cubot.setHologramMode(Cubot.HologramMode.STRING); + } else if (a == DISPLAY_DEC) { + //Display decimal number + char b = getCpu().getRegisterSet().getRegister("B").getValue(); + cubot.setHologram(b); + cubot.setHologramMode(Cubot.HologramMode.DEC); + + } else if (a == DISPLAY_COLOR) { + + if (cubot.spendEnergy(4)) { + int b = getCpu().getRegisterSet().getRegister("B").getValue(); + int c = getCpu().getRegisterSet().getRegister("C").getValue(); + + cubot.setHologramColor((c | (b << 16))); //B:C + } } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotInventory.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotInventory.java index 1dd2f5b..bf44d46 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotInventory.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotInventory.java @@ -16,8 +16,8 @@ public class CubotInventory extends CpuHardware { private Cubot cubot; + private static final int CLEAR = 0; private static final int POLL = 1; - private static final int CLEAR = 2; public CubotInventory(Cubot cubot) { this.cubot = cubot; diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Keyboard.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotKeyboard.java similarity index 82% rename from Plugin Cubot/src/main/java/net/simon987/cubotplugin/Keyboard.java rename to Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotKeyboard.java index ec05d59..902a226 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Keyboard.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotKeyboard.java @@ -5,7 +5,7 @@ import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.Status; import org.json.simple.JSONObject; -public class Keyboard extends CpuHardware { +public class CubotKeyboard extends CpuHardware { public static final int DEFAULT_ADDRESS = 4; @@ -19,7 +19,7 @@ public class Keyboard extends CpuHardware { private Cubot cubot; - public Keyboard(Cubot cubot) { + public CubotKeyboard(Cubot cubot) { this.cubot = cubot; } @@ -61,7 +61,7 @@ public class Keyboard extends CpuHardware { return json; } - public static Keyboard deserialize(JSONObject hwJSON) { - return new Keyboard((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((int) (long) hwJSON.get("cubot"))); + public static CubotKeyboard deserialize(JSONObject hwJSON) { + return new CubotKeyboard((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((int) (long) hwJSON.get("cubot"))); } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLaser.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLaser.java index 341f59b..41688e2 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLaser.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLaser.java @@ -46,7 +46,7 @@ public class CubotLaser extends CpuHardware { Point frontTile = cubot.getFrontTile(); - ArrayList objects = cubot.getWorld().getGameObjectsAt(frontTile.x, frontTile.y); + ArrayList objects = cubot.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y); if (cubot.getCurrentAction() == Action.IDLE && objects.size() > 0) { @@ -62,8 +62,6 @@ public class CubotLaser extends CpuHardware { } } } - } else { - System.out.println("\n\n\n\n\n It did it"); } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLeg.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLeg.java index f3b0d81..b10a456 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLeg.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLeg.java @@ -55,16 +55,18 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable { } else if (a == SET_DIR_AND_WALK) { - Direction dir = Direction.getDirection(b); + if (cubot.getMaxEnergy() >= 100) { + Direction dir = Direction.getDirection(b); - if (dir != null) { - cubot.setDirection(Direction.getDirection(b)); - status.setErrorFlag(false); - } else { - status.setErrorFlag(true); + if (dir != null) { + cubot.setDirection(Direction.getDirection(b)); + status.setErrorFlag(false); + } else { + status.setErrorFlag(true); + } + + cubot.setCurrentAction(Action.WALKING); } - - cubot.setCurrentAction(Action.WALKING); } } 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 8060d11..dce0961 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java @@ -50,14 +50,16 @@ public class CubotPlugin extends ServerPlugin implements GameObjectDeserializer, return CubotDrill.deserialize(hwJson); case CubotInventory.HWID: return CubotInventory.deserialize(hwJson); - case Keyboard.HWID: - return Keyboard.deserialize(hwJson); + case CubotKeyboard.HWID: + return CubotKeyboard.deserialize(hwJson); case CubotHologram.HWID: return CubotHologram.deserialize(hwJson); case CubotBattery.HWID: return CubotBattery.deserialize(hwJson); case CubotFloppyDrive.HWID: return CubotFloppyDrive.deserialize(hwJson); + case CubotComPort.HWID: + return CubotComPort.deserialize(hwJson); } return null; diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/CpuInitialisationListener.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/CpuInitialisationListener.java index 0bf3106..622aa6e 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/CpuInitialisationListener.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/CpuInitialisationListener.java @@ -5,7 +5,6 @@ import net.simon987.server.assembly.CPU; import net.simon987.server.event.CpuInitialisationEvent; import net.simon987.server.event.GameEvent; import net.simon987.server.event.GameEventListener; -import net.simon987.server.logging.LogManager; import net.simon987.server.user.User; public class CpuInitialisationListener implements GameEventListener { @@ -16,7 +15,7 @@ public class CpuInitialisationListener implements GameEventListener { @Override public void handle(GameEvent event) { - LogManager.LOGGER.fine("(Plugin) Handled CPU Initialisation event (Cubot Plugin)"); + //LogManager.LOGGER.fine("(Plugin) Handled CPU Initialisation event (Cubot Plugin)"); CPU cpu = (CPU) event.getSource(); User user = ((CpuInitialisationEvent) event).getUser(); @@ -27,7 +26,7 @@ public class CpuInitialisationListener implements GameEventListener { laserHw.setCpu(cpu); CubotLidar radarHw = new CubotLidar((Cubot) user.getControlledUnit()); radarHw.setCpu(cpu); - Keyboard keyboard = new Keyboard((Cubot) user.getControlledUnit()); + CubotKeyboard keyboard = new CubotKeyboard((Cubot) user.getControlledUnit()); keyboard.setCpu(cpu); CubotDrill drillHw = new CubotDrill((Cubot) user.getControlledUnit()); drillHw.setCpu(cpu); @@ -39,16 +38,19 @@ public class CpuInitialisationListener implements GameEventListener { batteryHw.setCpu(cpu); CubotFloppyDrive floppyHw = new CubotFloppyDrive((Cubot) user.getControlledUnit()); floppyHw.setCpu(cpu); + CubotComPort comPortHw = new CubotComPort((Cubot) user.getControlledUnit()); + comPortHw.setCpu(cpu); cpu.attachHardware(legHw, CubotLeg.DEFAULT_ADDRESS); cpu.attachHardware(laserHw, CubotLaser.DEFAULT_ADDRESS); cpu.attachHardware(radarHw, CubotLidar.DEFAULT_ADDRESS); - cpu.attachHardware(keyboard, Keyboard.DEFAULT_ADDRESS); + cpu.attachHardware(keyboard, CubotKeyboard.DEFAULT_ADDRESS); cpu.attachHardware(drillHw, CubotDrill.DEFAULT_ADDRESS); cpu.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS); cpu.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS); cpu.attachHardware(emoteHw, CubotHologram.DEFAULT_ADDRESS); cpu.attachHardware(batteryHw, CubotBattery.DEFAULT_ADDRESS); cpu.attachHardware(floppyHw, CubotFloppyDrive.DEFAULT_ADDRESS); + cpu.attachHardware(comPortHw, CubotComPort.DEFAULT_ADDRESS); } } diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java index 85deb75..da8b5fd 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java @@ -124,7 +124,7 @@ public class Factory extends GameObject implements Updatable { factory.setX((int) (long) json.get("x")); factory.setY((int) (long) json.get("y")); - factory.tmpNpcArray = (Object[]) ((JSONArray) json.get("n")).toArray(); + factory.tmpNpcArray = ((JSONArray) json.get("n")).toArray(); return factory; } diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java index 36e7da6..a2d80d1 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java @@ -1,35 +1,65 @@ package net.simon987.npcplugin; +import net.simon987.npcplugin.event.CpuInitialisationListener; import net.simon987.npcplugin.event.WorldCreationListener; import net.simon987.server.ServerConfiguration; +import net.simon987.server.assembly.CpuHardware; import net.simon987.server.game.GameObject; +import net.simon987.server.io.CpuHardwareDeserializer; import net.simon987.server.io.GameObjectDeserializer; import net.simon987.server.logging.LogManager; import net.simon987.server.plugin.ServerPlugin; import org.json.simple.JSONObject; -public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer { +import java.util.ArrayList; +public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer, CpuHardwareDeserializer { + + /** + * Radio tower cache + */ + private static ArrayList radioTowers; @Override public void init(ServerConfiguration configuration) { listeners.add(new WorldCreationListener()); + listeners.add(new CpuInitialisationListener()); + + radioTowers = new ArrayList<>(32); LogManager.LOGGER.info("Initialised NPC plugin"); } @Override - public GameObject deserializeObject(JSONObject object) { + public GameObject deserializeObject(JSONObject json) { - int objType = (int) (long) object.get("t"); + int objType = (int) (long) json.get("t"); if (objType == HarvesterNPC.ID) { - return HarvesterNPC.deserialize(object); + return HarvesterNPC.deserialize(json); } else if (objType == Factory.ID) { - return Factory.deserialise(object); + return Factory.deserialise(json); + } else if (objType == RadioTower.ID) { + return RadioTower.deserialize(json); } return null; } + + @Override + public CpuHardware deserializeHardware(JSONObject hwJson) { + int hwid = (int) (long) hwJson.get("hwid"); + + switch (hwid) { + case RadioReceiverHardware.HWID: + return RadioReceiverHardware.deserialize(hwJson); + } + + return null; + } + + public static ArrayList getRadioTowers() { + return radioTowers; + } } diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/RadioReceiverHardware.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/RadioReceiverHardware.java new file mode 100644 index 0000000..2a04f77 --- /dev/null +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/RadioReceiverHardware.java @@ -0,0 +1,79 @@ +package net.simon987.npcplugin; + +import net.simon987.server.GameServer; +import net.simon987.server.assembly.CpuHardware; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Util; +import net.simon987.server.game.Action; +import net.simon987.server.game.ControllableUnit; +import org.json.simple.JSONObject; + +import java.util.ArrayList; + +public class RadioReceiverHardware extends CpuHardware { + + public static final char HWID = 0xC; //12 + + private static final int LISTEN = 1; + + public static final int DEFAULT_ADDRESS = 0xC; + + private ControllableUnit cubot; + + public RadioReceiverHardware(ControllableUnit cubot) { + this.cubot = cubot; + } + + @Override + public void handleInterrupt(Status status) { + int x = getCpu().getRegisterSet().getRegister("X").getValue(); + int a = getCpu().getRegisterSet().getRegister("A").getValue(); + + if (a == LISTEN) { + + //Find the nearest Radio Tower and query it + cubot.setAction(Action.LISTENING); + + ArrayList messages = new ArrayList<>(6); + + ArrayList towers = new ArrayList<>(NpcPlugin.getRadioTowers()); //Avoid ConcurrentModificationException + for (RadioTower tower : towers) { + if (Util.manhattanDist(tower.getWorld().getX(), tower.getWorld().getY(), cubot.getWorld().getX(), + cubot.getWorld().getY()) <= RadioTower.MAX_RANGE) { + //Tower is in range + messages.addAll(tower.getMessages()); + } + } + + //Write messages to memory + int offset = 0; + + for (char[] message : messages) { + + getCpu().getMemory().write(x + offset, message, 0, message.length); + offset += message.length; + } + + //Write the amount of messages received to B + getCpu().getRegisterSet().getRegister("B").setValue(messages.size()); + } + } + + @Override + public char getId() { + return HWID; + } + + @Override + public JSONObject serialise() { + JSONObject json = new JSONObject(); + json.put("hwid", (int) HWID); + json.put("cubot", cubot.getObjectId()); + + return json; + } + + public static RadioReceiverHardware deserialize(JSONObject json) { + return new RadioReceiverHardware((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((int) (long) json.get("cubot"))); + } +} diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/RadioTower.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/RadioTower.java index b225e96..54ee1d1 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/RadioTower.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/RadioTower.java @@ -1,4 +1,103 @@ package net.simon987.npcplugin; -public class RadioTower { +import net.simon987.server.game.GameObject; +import net.simon987.server.game.Programmable; +import net.simon987.server.game.Updatable; +import org.json.simple.JSONObject; + +import java.awt.*; +import java.util.ArrayList; + +public class RadioTower extends GameObject implements Programmable, Updatable { + + private static final int MAP_INFO = 0x1000; + + public static final int ID = 4; + + public static final int MAX_RANGE = 3; //todo load from config + + private static final int MAX_MESSAGES = 16; + + @Override + public char getMapInfo() { + return MAP_INFO; + } + + + /** + * Messages from the current tick + */ + private ArrayList messages = new ArrayList<>(4); + + /** + * Messages from the last tick + */ + private ArrayList lastMessages = new ArrayList<>(4); + + @Override + public void update() { + lastMessages = new ArrayList<>(messages); + messages.clear(); + } + + @Override + public void sendMessage(char[] message) { + + if (message.length < MAX_MESSAGES) { + messages.add(message); + } + } + + @Override + public JSONObject serialise() { + + JSONObject json = new JSONObject(); + + json.put("i", getObjectId()); + json.put("x", getX()); + json.put("y", getY()); + json.put("t", ID); + + return json; + + } + + public static RadioTower deserialize(JSONObject json) { + + RadioTower tower = new RadioTower(); + tower.setObjectId((long) json.get("i")); + tower.setX((int) (long) json.get("x")); + tower.setY((int) (long) json.get("y")); + + NpcPlugin.getRadioTowers().add(tower); + + return tower; + } + + + public ArrayList getMessages() { + return lastMessages; + } + + /** + * Get the first directly adjacent tile (starting east, going clockwise) + */ + public Point getAdjacentTile() { + + if (!getWorld().isTileBlocked(getX() + 1, getY())) { + return new Point(getX() + 1, getY()); + + } else if (!getWorld().isTileBlocked(getX(), getY() + 1)) { + return new Point(getX(), getY() + 1); + + } else if (!getWorld().isTileBlocked(getX() - 1, getY())) { + return new Point(getX() - 1, getY()); + + } else if (!getWorld().isTileBlocked(getX(), getY() - 1)) { + return new Point(getX(), getY() - 1); + } else { + return null; + } + + } } diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/event/CpuInitialisationListener.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/event/CpuInitialisationListener.java new file mode 100644 index 0000000..f6bf356 --- /dev/null +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/event/CpuInitialisationListener.java @@ -0,0 +1,27 @@ +package net.simon987.npcplugin.event; + +import net.simon987.npcplugin.RadioReceiverHardware; +import net.simon987.server.assembly.CPU; +import net.simon987.server.event.CpuInitialisationEvent; +import net.simon987.server.event.GameEvent; +import net.simon987.server.event.GameEventListener; +import net.simon987.server.user.User; + +public class CpuInitialisationListener implements GameEventListener { + @Override + public Class getListenedEventType() { + return CpuInitialisationEvent.class; + } + + + @Override + public void handle(GameEvent event) { + CPU cpu = (CPU) event.getSource(); + User user = ((CpuInitialisationEvent) event).getUser(); + + RadioReceiverHardware radioHw = new RadioReceiverHardware(user.getControlledUnit()); + radioHw.setCpu(cpu); + + cpu.attachHardware(radioHw, RadioReceiverHardware.DEFAULT_ADDRESS); + } +} diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/event/WorldCreationListener.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/event/WorldCreationListener.java index 6601bbf..608a40d 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/event/WorldCreationListener.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/event/WorldCreationListener.java @@ -1,6 +1,8 @@ package net.simon987.npcplugin.event; import net.simon987.npcplugin.Factory; +import net.simon987.npcplugin.NpcPlugin; +import net.simon987.npcplugin.RadioTower; import net.simon987.server.GameServer; import net.simon987.server.event.GameEvent; import net.simon987.server.event.GameEventListener; @@ -8,6 +10,7 @@ import net.simon987.server.event.WorldGenerationEvent; import net.simon987.server.game.World; import net.simon987.server.logging.LogManager; +import java.awt.*; import java.util.Random; public class WorldCreationListener implements GameEventListener { @@ -31,6 +34,7 @@ public class WorldCreationListener implements GameEventListener { World world = ((WorldGenerationEvent) event).getWorld(); + outerLoopFactory: for (int x = 2; x < 12; x++) { for (int y = 2; y < 12; y++) { @@ -54,10 +58,40 @@ public class WorldCreationListener implements GameEventListener { LogManager.LOGGER.info("Spawned Factory at (" + world.getX() + ", " + world.getY() + ") (" + x + ", " + y + ")"); + break outerLoopFactory; + } + } + } + //Also spawn a radio tower in the same World + Point p = world.getRandomPassableTile(); + if (p != null) { + while (p.x == 0 || p.x == World.WORLD_SIZE - 1 || p.y == World.WORLD_SIZE - 1 || p.y == 0) { + p = world.getRandomPassableTile(); + + if (p == null) { + //World is full return; } } + + RadioTower radioTower = new RadioTower(); + + radioTower.setWorld(world); + radioTower.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId()); + radioTower.setX(p.x); + radioTower.setY(p.y); + + if (radioTower.getAdjacentTile() != null) { + //Radio Tower has adjacent tiles + world.getGameObjects().add(radioTower); + world.incUpdatable(); //In case the Factory couldn't be spawned. + + NpcPlugin.getRadioTowers().add(radioTower); + + LogManager.LOGGER.info("Spawned RadioTower at (" + world.getX() + ", " + world.getY() + + ") (" + p.x + ", " + p.y + ")"); + } } } } diff --git a/Plugin Plant/src/main/java/net/simon987/biomassplugin/WorldUtils.java b/Plugin Plant/src/main/java/net/simon987/biomassplugin/WorldUtils.java index fda2516..e4b98bb 100644 --- a/Plugin Plant/src/main/java/net/simon987/biomassplugin/WorldUtils.java +++ b/Plugin Plant/src/main/java/net/simon987/biomassplugin/WorldUtils.java @@ -17,7 +17,7 @@ public class WorldUtils { Random random = new Random(); int blobCount = random.nextInt(maxCount - minCount) + minCount; - ArrayList biomassBlobs = new ArrayList<>(maxCount); + ArrayList biomassBlobs = new ArrayList<>(blobCount); //Count number of plain tiles. If there is less plain tiles than desired amount of blobs, //set the desired amount of blobs to the plain tile count @@ -45,7 +45,7 @@ public class WorldUtils { //Don't block worlds int counter = 0; while (p.x == 0 || p.y == 0 || p.x == World.WORLD_SIZE - 1 || p.y == World.WORLD_SIZE - 1 || - world.isTileBlocked(p.x, p.y)) { + world.getGameObjectsAt(p.x, p.y).size() != 0) { p = world.getTileMap().getRandomPlainTile(); counter++; diff --git a/Server/Server.iml b/Server/Server.iml index b341a74..9c5747d 100644 --- a/Server/Server.iml +++ b/Server/Server.iml @@ -7,8 +7,6 @@ - - @@ -18,5 +16,7 @@ + + \ No newline at end of file diff --git a/Server/pom.xml b/Server/pom.xml index 03a5739..473197b 100644 --- a/Server/pom.xml +++ b/Server/pom.xml @@ -3,15 +3,37 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - - net.simon987.server - server_root - 1.2a - + + + + maven-resources-plugin + 3.0.2 + + + default-resources + + prepare-package + + resources + + + ../target/ + + + ../Server/src/main/resources + true + + config.properties + + + + + + + 3.6.2 org.apache.maven.plugins @@ -21,11 +43,36 @@ 1.8 + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ../target/libs + + + + + org.apache.maven.plugins maven-jar-plugin + 3.0.2 ../target + + + net.simon987.server.Main + true + libs/ + + @@ -57,7 +104,17 @@ json-simple 1.1.1 + + org.apache.commons + commons-text + 1.2 + + + + UTF-8 + + \ No newline at end of file diff --git a/Server/src/main/java/net/simon987/server/GameServer.java b/Server/src/main/java/net/simon987/server/GameServer.java index 2042cc6..46c85d3 100644 --- a/Server/src/main/java/net/simon987/server/GameServer.java +++ b/Server/src/main/java/net/simon987/server/GameServer.java @@ -40,7 +40,7 @@ public class GameServer implements Runnable { public GameServer() { - this.config = new ServerConfiguration(new File("config.properties")); + this.config = new ServerConfiguration("config.properties"); gameUniverse = new GameUniverse(config); pluginManager = new PluginManager(); diff --git a/Server/src/main/java/net/simon987/server/Main.java b/Server/src/main/java/net/simon987/server/Main.java index 02542be..2bb4b98 100644 --- a/Server/src/main/java/net/simon987/server/Main.java +++ b/Server/src/main/java/net/simon987/server/Main.java @@ -12,8 +12,7 @@ public class Main { LogManager.initialize(); - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); - + ServerConfiguration config = new ServerConfiguration("config.properties"); //Load GameServer.INSTANCE.getGameUniverse().load(new File("save.json")); @@ -23,6 +22,7 @@ public class Main { GameServer.INSTANCE.setSocketServer(socketServer); + System.out.println(GameServer.INSTANCE.getGameUniverse().getWorld(0x7fff, 0x7fff)); (new Thread(socketServer)).start(); (new Thread(GameServer.INSTANCE)).start(); diff --git a/Server/src/main/java/net/simon987/server/ServerConfiguration.java b/Server/src/main/java/net/simon987/server/ServerConfiguration.java index 84d715a..b5d2f8a 100644 --- a/Server/src/main/java/net/simon987/server/ServerConfiguration.java +++ b/Server/src/main/java/net/simon987/server/ServerConfiguration.java @@ -6,6 +6,7 @@ import net.simon987.server.logging.LogManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.Properties; /** @@ -18,11 +19,11 @@ public class ServerConfiguration { */ private Properties properties; - public ServerConfiguration(File file) { + public ServerConfiguration(String file) { try { properties = new Properties(); - - properties.load(new FileInputStream(file)); + InputStream is = new FileInputStream("config.properties"); + properties.load(is); } catch (IOException e) { LogManager.LOGGER.severe("Problem loading server configuration: " + e.getMessage()); diff --git a/Server/src/main/java/net/simon987/server/assembly/Assembler.java b/Server/src/main/java/net/simon987/server/assembly/Assembler.java index 5b151b3..b6f5f8b 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Assembler.java +++ b/Server/src/main/java/net/simon987/server/assembly/Assembler.java @@ -3,12 +3,15 @@ package net.simon987.server.assembly; import net.simon987.server.ServerConfiguration; import net.simon987.server.assembly.exception.*; import net.simon987.server.logging.LogManager; +import org.apache.commons.text.StringEscapeUtils; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Top-level class for assembly operations. @@ -48,11 +51,9 @@ public class Assembler { * @return The line without its label part */ private static String removeLabel(String line) { - if (line.indexOf(':') != -1) { - return line.substring(line.indexOf(':') + 1); - } else { - return line; - } + + return line.replaceAll("\\b\\w*\\b:", ""); + } /** @@ -94,10 +95,11 @@ public class Assembler { line = removeComment(line); //Check for labels - if (line.indexOf(':') != -1) { + Pattern pattern = Pattern.compile("\\b\\w*\\b:"); + Matcher matcher = pattern.matcher(line); - line = line.substring(0, line.indexOf(':')); - String label = line.trim(); + if (matcher.find()) { + String label = matcher.group(0).substring(0, matcher.group(0).length() - 1); LogManager.LOGGER.fine("DEBUG: Label " + label + " @ " + (result.origin + currentOffset)); result.labels.put(label, (char) (result.origin + currentOffset)); @@ -134,7 +136,8 @@ public class Assembler { try { - String[] values = line.substring(2, line.length()).split(","); + //Special thanks to https://stackoverflow.com/questions/1757065/ + String[] values = line.substring(2, line.length()).split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1); for (String value : values) { @@ -147,7 +150,12 @@ public class Assembler { out.write(parseDUPOperator16(valueTokens, labels, currentLine)); } else if (value.startsWith("\"") && value.endsWith("\"")) { //Handle string - out.write(value.substring(1, value.length() - 1).getBytes(StandardCharsets.UTF_16)); + + //Unescape the string + String string = value.substring(1, value.length() - 1); + string = StringEscapeUtils.unescapeJava(string); + + out.write(string.getBytes(StandardCharsets.UTF_16BE)); } else if (labels != null && labels.containsKey(value)) { //Handle label out.writeChar(labels.get(value)); 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 52cc0be..c1404a1 100755 --- a/Server/src/main/java/net/simon987/server/assembly/CPU.java +++ b/Server/src/main/java/net/simon987/server/assembly/CPU.java @@ -245,7 +245,7 @@ public class CPU implements JSONSerialisable { } else if (destination <= registerSetSize * 2) { //Destination is [reg] ip++; - instruction.execute(memory, registerSet.get(destination - registerSetSize), memory, sourceValue, status); + instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status); } else { //Assuming that destination is [reg + x] ip += 2; diff --git a/Server/src/main/java/net/simon987/server/assembly/Instruction.java b/Server/src/main/java/net/simon987/server/assembly/Instruction.java index e791987..65f78e1 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Instruction.java +++ b/Server/src/main/java/net/simon987/server/assembly/Instruction.java @@ -120,8 +120,8 @@ public abstract class Instruction { * Whether or not the instruction is valid without any * operands */ - private static boolean noOperandsValid() { - return true; + public boolean noOperandsValid() { + return false; } String getMnemonic() { diff --git a/Server/src/main/java/net/simon987/server/assembly/Util.java b/Server/src/main/java/net/simon987/server/assembly/Util.java index cffafa2..437033a 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Util.java +++ b/Server/src/main/java/net/simon987/server/assembly/Util.java @@ -42,7 +42,7 @@ public class Util { } public static String toHex(int a) { - return String.format("%04X ", uShort(a)); + return String.format("%04X ", a); } public static String toHex(byte[] byteArray) { diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/BrkInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/BrkInstruction.java index ba713c5..cf2e92f 100755 --- a/Server/src/main/java/net/simon987/server/assembly/instruction/BrkInstruction.java +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/BrkInstruction.java @@ -20,4 +20,8 @@ public class BrkInstruction extends Instruction { return status; } + + public boolean noOperandsValid() { + return true; + } } diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/DivInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/DivInstruction.java index 77a6912..4290230 100644 --- a/Server/src/main/java/net/simon987/server/assembly/instruction/DivInstruction.java +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/DivInstruction.java @@ -28,8 +28,8 @@ public class DivInstruction extends Instruction { public Status execute(Target src, int srcIndex, Status status) { //Source = Y:A - int source = ((((char) cpu.getRegisterSet().getRegister("Y").getValue() & 0xFFFF) << 16)) | - ((char) cpu.getRegisterSet().getRegister("A").getValue() & 0xFFFF); + int source = (((cpu.getRegisterSet().getRegister("Y").getValue() & 0xFFFF) << 16)) | + (cpu.getRegisterSet().getRegister("A").getValue() & 0xFFFF); if (src.get(srcIndex) == 0) { //Division by 0 @@ -48,8 +48,8 @@ public class DivInstruction extends Instruction { //Source = Y:A - int source = ((((char) cpu.getRegisterSet().getRegister("Y").getValue() & 0xFFFF) << 16)) | - ((char) cpu.getRegisterSet().getRegister("A").getValue() & 0xFFFF); + int source = (((cpu.getRegisterSet().getRegister("Y").getValue() & 0xFFFF) << 16)) | + (cpu.getRegisterSet().getRegister("A").getValue() & 0xFFFF); if (src == 0) { //Division by 0 diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/MulInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/MulInstruction.java index 774ab66..62747e1 100644 --- a/Server/src/main/java/net/simon987/server/assembly/instruction/MulInstruction.java +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/MulInstruction.java @@ -25,9 +25,11 @@ public class MulInstruction extends Instruction { status.setOverflowFlag(true); status.setCarryFlag(true); cpu.getRegisterSet().getRegister("Y").setValue(hWord);//Don't overwrite Y register if it's blank + } else { + status.setOverflowFlag(false); + status.setCarryFlag(false); } - status.setOverflowFlag(false); - status.setCarryFlag(false); + cpu.getRegisterSet().set(1, Util.getLowerWord(result)); return status; @@ -44,9 +46,11 @@ public class MulInstruction extends Instruction { status.setOverflowFlag(true); status.setCarryFlag(true); cpu.getRegisterSet().getRegister("Y").setValue(hWord);//Don't overwrite Y register if it's blank + } else { + status.setOverflowFlag(false); + status.setCarryFlag(false); } - status.setOverflowFlag(false); - status.setCarryFlag(false); + cpu.getRegisterSet().getRegister("A").setValue(Util.getLowerWord(result)); return status; diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/NegInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/NegInstruction.java index 14b6316..c9638b0 100644 --- a/Server/src/main/java/net/simon987/server/assembly/instruction/NegInstruction.java +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/NegInstruction.java @@ -14,7 +14,23 @@ public class NegInstruction extends Instruction { @Override public Status execute(Target dst, int dstIndex, Status status) { - dst.set(dstIndex, -dst.get(dstIndex)); + //If the operand is zero, the carry flag is cleared; in all other cases, the carry flag is set. + + char destination = (char) dst.get(dstIndex); + + if (destination == 0) { + status.setCarryFlag(false); + status.setZeroFlag(true); + } else { + status.setCarryFlag(true); + } + + //Attempting to negate a word containing -32,768 causes no change to the operand and sets the Overflow Flag. + if (destination == 0x8000) { + status.setOverflowFlag(true); + } else { + dst.set(dstIndex, -destination); + } return status; } diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/RetInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/RetInstruction.java index cf2b371..ea8d972 100644 --- a/Server/src/main/java/net/simon987/server/assembly/instruction/RetInstruction.java +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/RetInstruction.java @@ -37,4 +37,9 @@ public class RetInstruction extends Instruction { return status; } + + @Override + public boolean noOperandsValid() { + return true; + } } \ No newline at end of file diff --git a/Server/src/main/java/net/simon987/server/game/Action.java b/Server/src/main/java/net/simon987/server/game/Action.java index 2b35c92..f9f037f 100644 --- a/Server/src/main/java/net/simon987/server/game/Action.java +++ b/Server/src/main/java/net/simon987/server/game/Action.java @@ -5,6 +5,7 @@ public enum Action { DIGGING, WALKING, WITHDRAWING, - DEPOSITING + DEPOSITING, + LISTENING } diff --git a/Server/src/main/java/net/simon987/server/game/ControllableUnit.java b/Server/src/main/java/net/simon987/server/game/ControllableUnit.java index 51a97f1..31b279d 100644 --- a/Server/src/main/java/net/simon987/server/game/ControllableUnit.java +++ b/Server/src/main/java/net/simon987/server/game/ControllableUnit.java @@ -21,4 +21,15 @@ public interface ControllableUnit { int getEnergy(); + int getX(); + + int getY(); + + void setAction(Action listening); + + World getWorld(); + + ArrayList getConsoleMessagesBuffer(); + + int getConsoleMode(); } diff --git a/Server/src/main/java/net/simon987/server/game/Programmable.java b/Server/src/main/java/net/simon987/server/game/Programmable.java new file mode 100644 index 0000000..3508480 --- /dev/null +++ b/Server/src/main/java/net/simon987/server/game/Programmable.java @@ -0,0 +1,7 @@ +package net.simon987.server.game; + +public interface Programmable { + + void sendMessage(char[] message); + +} 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 60b939a..990de2d 100644 --- a/Server/src/main/java/net/simon987/server/game/World.java +++ b/Server/src/main/java/net/simon987/server/game/World.java @@ -54,7 +54,7 @@ public class World implements JSONSerialisable { */ public boolean isTileBlocked(int x, int y) { - return getGameObjectsAt(x, y).size() > 0 || tileMap.getTileAt(x, y) == TileMap.WALL_TILE; + return getGameObjectsBlockingAt(x, y).size() > 0 || tileMap.getTileAt(x, y) == TileMap.WALL_TILE; } @@ -245,13 +245,13 @@ public class World implements JSONSerialisable { } /** - * Get the list of game objects at a location + * Get the list of game objects that are blocking a tile at a set of coordinates * * @param x X coordinate on the World * @param y Y coordinate on the World - * @return the list of game objects at a location + * @return the list of game objects blocking a location */ - public ArrayList getGameObjectsAt(int x, int y) { + public ArrayList getGameObjectsBlockingAt(int x, int y) { ArrayList gameObjects = new ArrayList<>(2); @@ -266,6 +266,30 @@ public class World implements JSONSerialisable { return gameObjects; } + /** + * Get the list of game objects that are exactly at a given location + *
+ * Note: Objects like the Factory that are more than 1x1 tiles wide will only be returned + * when their exact coordinates are specified + * + * @param x X coordinate on the World + * @param y Y coordinate on the World + * @return the list of game objects at a location + */ + public ArrayList getGameObjectsAt(int x, int y) { + ArrayList gameObjects = new ArrayList<>(2); + + for (GameObject obj : this.gameObjects) { + + if (obj.getX() == x && obj.getY() == y) { + gameObjects.add(obj); + } + + } + + return gameObjects; + } + public void incUpdatable() { updatable++; } diff --git a/Server/src/main/java/net/simon987/server/io/FileUtils.java b/Server/src/main/java/net/simon987/server/io/FileUtils.java index 8e9ba15..28c5a59 100644 --- a/Server/src/main/java/net/simon987/server/io/FileUtils.java +++ b/Server/src/main/java/net/simon987/server/io/FileUtils.java @@ -1,5 +1,7 @@ package net.simon987.server.io; +import net.simon987.server.logging.LogManager; + import java.io.*; import java.nio.file.Files; import java.nio.file.Path; @@ -11,176 +13,172 @@ import java.util.zip.ZipOutputStream; public class FileUtils { - private static final int BUFFER_SIZE = 1024; - private static final String STR_ENCODING = "UTF-8"; - private static final String DATE_FORMAT = "yyyyMMddHHmmss"; - private static final String FILE_TYPE = ".zip"; - private static final Path ROOT_DIR; - private static final String DIR_NAME = "history"; - public static final Path DIR_PATH; - - static { - ROOT_DIR = Paths.get(".").normalize(); - DIR_PATH = ROOT_DIR.resolve(DIR_NAME); - } - - //Private constructor - private FileUtils() { - - } - - /** - * Creates a new stamp containing the current date and time - * - * @return date and time stamp - */ - private static String getDateTimeStamp() { - Date millisToDate = new Date(System.currentTimeMillis()); - SimpleDateFormat f = new SimpleDateFormat(DATE_FORMAT); - return f.format(millisToDate); - } + private static final int BUFFER_SIZE = 1024; + private static final String STR_ENCODING = "UTF-8"; + private static final String DATE_FORMAT = "yyyyMMddHHmmss"; + private static final String FILE_TYPE = ".zip"; + private static final Path ROOT_DIR; + private static final String DIR_NAME = "history"; + public static final Path DIR_PATH; - /** - * Created a directory if none exists with the specified name - * + static { + ROOT_DIR = Paths.get(".").normalize(); + DIR_PATH = ROOT_DIR.resolve(DIR_NAME); + } + + //Private constructor + private FileUtils() { + + } + + /** + * Creates a new stamp containing the current date and time + * + * @return date and time stamp + */ + private static String getDateTimeStamp() { + Date millisToDate = new Date(System.currentTimeMillis()); + SimpleDateFormat f = new SimpleDateFormat(DATE_FORMAT); + return f.format(millisToDate); + } + + /** + * Created a directory if none exists with the specified name + * * @param directory folder to create * @return true is the file exists or create operation is successful - */ - public static boolean prepDirectory(Path directory) { - File file = directory.toFile(); - - //If the directory exists or the directory created successfully return true - if(file.exists() || file.mkdir()) { - return true; - - } else { - System.out.println("Error creating directory: " + file.toString()); - return false; - } - } - - /** - * Converts a file into an array of bytes - * + */ + public static boolean prepDirectory(Path directory) { + File file = directory.toFile(); + + //If the directory exists or the directory created successfully return true + if (file.exists() || file.mkdir()) { + return true; + + } else { + System.out.println("Error creating directory: " + file.toString()); + return false; + } + } + + /** + * Converts a file into an array of bytes + * * @param path the file to be converted into bytes * @return the byte array of the given file - */ - public static byte[] bytifyFile(Path path) { - byte[] bytes = null; + */ + public static byte[] bytifyFile(Path path) { + byte[] bytes = null; - try { - bytes = Files.readAllBytes(path); + try { + bytes = Files.readAllBytes(path); - } catch (IOException e) { - System.out.println("Failed to extract bytes from: " + path); - e.printStackTrace(); - } + } catch (IOException e) { + System.out.println("Failed to extract bytes from: " + path); + e.printStackTrace(); + } - return bytes; - } + return bytes; + } - /** - * Takes in a file that had been converted to a byte[] to be written to a new - * zip file - * + /** + * Takes in a file that had been converted to a byte[] to be written to a new + * zip file + * * @param data * contains data in byte array form to be written, typically a file - * that has been converted with bytifyFile() - * @throws IOException - * if an error occurs during the write process - */ - public static void writeSaveToZip(String name, byte[] data) throws IOException { + * that has been converted with bytifyFile() + * @throws IOException + * if an error occurs during the write process + */ + public static void writeSaveToZip(String name, byte[] data) throws IOException { - String newFile = DIR_PATH.resolve(getDateTimeStamp() + FILE_TYPE).toString(); - FileOutputStream output = new FileOutputStream(newFile); - ZipOutputStream stream = new ZipOutputStream(output); - byte[] buffer = new byte[BUFFER_SIZE]; - ByteArrayInputStream bais = new ByteArrayInputStream(buffer); + String newFile = DIR_PATH.resolve(getDateTimeStamp() + FILE_TYPE).toString(); + FileOutputStream output = new FileOutputStream(newFile); + ZipOutputStream stream = new ZipOutputStream(output); + byte[] buffer = new byte[BUFFER_SIZE]; + ByteArrayInputStream bais = new ByteArrayInputStream(buffer); - while ((bais.read(buffer)) > -1) { - // File name - ZipEntry entry = new ZipEntry(name); - // Set to start of next entry in the stream. - stream.putNextEntry(entry); - // Data to write. - stream.write(data); - // Close the current entry. - stream.closeEntry(); - } + while ((bais.read(buffer)) > -1) { + // File name + ZipEntry entry = new ZipEntry(name); + // Set to start of next entry in the stream. + stream.putNextEntry(entry); + // Data to write. + stream.write(data); + // Close the current entry. + stream.closeEntry(); + } - stream.close(); - output.close(); - } - - public static void cleanHistory(int size) { - - - File[] files = new File(DIR_PATH.toString()).listFiles(); - File[] sorted = new File[size]; - - File nextSortedFile = null; - File currentFile = null; - boolean changed = false; - - for(int i = 0; i < files.length / 2; i++) { - currentFile = files[i]; - files[i] = files[files.length - i - 1]; - files[files.length - i - 1] = currentFile; - } - - currentFile = null; - - for(int f = 0; f < files.length; f++) { - changed = false; - long dirFile = Long.parseLong(files[f].getName().substring(0, (files[f].getName().length() -4))); - - if(f < size && sorted[f] == null) { - sorted[f] = files[f]; - - } else { - - for(int s = 0; s < sorted.length; s++) { - - long sortedFile = Long.parseLong(sorted[s].getName().substring(0, (sorted[s].getName().length() -4))); - - if(dirFile > sortedFile) { - - if(s == sorted.length - 1) { - sorted[s] = files[f]; - - } else if(nextSortedFile == null) { - nextSortedFile = sorted[s]; - sorted[s] = files[f]; - - } else { - currentFile = sorted[s]; - sorted[s] = nextSortedFile; - nextSortedFile = currentFile; - } - - nextSortedFile = null; - currentFile = null; - changed = true; - } - } - - if(changed == false) { - files[f].delete(); - } - - } - } + stream.close(); + output.close(); + } - } - - /** - * Converts a byte array into human readable format using the provided encoding - * - * @param bytes - * data to be encoded to String - * @return a String containing the encoded bytes - */ - public static String byteArrAsString(byte[] bytes) throws UnsupportedEncodingException { - return new String(bytes, STR_ENCODING); - } + public static void cleanHistory(int size) { + + + File[] files = new File(DIR_PATH.toString()).listFiles(); + File[] sorted = new File[size]; + + File currentFile; + boolean changed; + + if (files != null) { + for (int i = 0; i < files.length / 2; i++) { + currentFile = files[i]; + files[i] = files[files.length - i - 1]; + files[files.length - i - 1] = currentFile; + } + + for (int f = 0; f < files.length; f++) { + changed = false; + + try { + long dirFile = Long.parseLong(files[f].getName().substring(0, (files[f].getName().length() - 4))); + + if (f < size && sorted[f] == null) { + sorted[f] = files[f]; + + } else { + + for (int s = 0; s < sorted.length; s++) { + + long sortedFile = Long.parseLong(sorted[s].getName().substring(0, (sorted[s].getName().length() - 4))); + + if (dirFile > sortedFile) { + + if (s == sorted.length - 1) { + sorted[s] = files[f]; + + } else { + sorted[s] = files[f]; + } + + changed = true; + } + } + + if (!changed) { + files[f].delete(); + } + + } + } catch (NumberFormatException e) { + LogManager.LOGGER.info("Non-save file in history directory: " + files[f].getName()); + } + } + } + + + } + + /** + * Converts a byte array into human readable format using the provided encoding + * + * @param bytes data to be encoded to String + * @return a String containing the encoded bytes + */ + public static String byteArrAsString(byte[] bytes) throws UnsupportedEncodingException { + return new String(bytes, STR_ENCODING); + } } diff --git a/Server/src/main/java/net/simon987/server/webserver/CodeRequestHandler.java b/Server/src/main/java/net/simon987/server/webserver/CodeRequestHandler.java index 273a3bb..dfa4272 100644 --- a/Server/src/main/java/net/simon987/server/webserver/CodeRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/CodeRequestHandler.java @@ -9,7 +9,7 @@ public class CodeRequestHandler implements MessageHandler { if (json.get("t").equals("codeRequest")) { - LogManager.LOGGER.info("(WS) Code request from " + user.getUser().getUsername()); + LogManager.LOGGER.fine("(WS) Code request from " + user.getUser().getUsername()); if (user.isGuest()) { diff --git a/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java b/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java index 520f6cd..1518241 100644 --- a/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java @@ -12,7 +12,7 @@ public class CodeUploadHandler implements MessageHandler { public void handle(OnlineUser user, JSONObject json) { if (json.get("t").equals("uploadCode")) { - LogManager.LOGGER.info("(WS) Code upload from " + user.getUser().getUsername()); + LogManager.LOGGER.fine("(WS) Code upload from " + user.getUser().getUsername()); if (user.isGuest()) { //Ignore @@ -33,6 +33,13 @@ public class CodeUploadHandler implements MessageHandler { user.getUser().getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length); user.getUser().getCpu().setCodeSegmentOffset(ar.getCodeSegmentOffset()); + //Clear keyboard buffer + if (user.getUser().getControlledUnit() != null && + user.getUser().getControlledUnit().getKeyboardBuffer() != null) { + user.getUser().getControlledUnit().getKeyboardBuffer().clear(); + } + + JSONObject response = new JSONObject(); response.put("t", "codeResponse"); response.put("bytes", ar.bytes.length); diff --git a/Server/src/main/java/net/simon987/server/webserver/FloppyHandler.java b/Server/src/main/java/net/simon987/server/webserver/FloppyHandler.java index 115d929..a66f418 100644 --- a/Server/src/main/java/net/simon987/server/webserver/FloppyHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/FloppyHandler.java @@ -13,7 +13,7 @@ public class FloppyHandler implements MessageHandler { if (json.get("t").equals("floppyDown")) { - LogManager.LOGGER.info("(WS) Floppy download request from " + user.getUser().getUsername()); + LogManager.LOGGER.fine("(WS) Floppy download request from " + user.getUser().getUsername()); if (user.isGuest()) { return; @@ -27,7 +27,7 @@ public class FloppyHandler implements MessageHandler { } else if (json.get("t").equals("floppyUp")) { - LogManager.LOGGER.info("(WS) Floppy upload request from " + user.getUser().getUsername()); + LogManager.LOGGER.fine("(WS) Floppy upload request from " + user.getUser().getUsername()); //Check newly uploaded file on the database byte[] bytes = db.getFloppy(user.getUser().getUsername()); diff --git a/Server/src/main/java/net/simon987/server/webserver/KeypressHandler.java b/Server/src/main/java/net/simon987/server/webserver/KeypressHandler.java index 4b99783..a0cbd95 100644 --- a/Server/src/main/java/net/simon987/server/webserver/KeypressHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/KeypressHandler.java @@ -1,6 +1,5 @@ package net.simon987.server.webserver; -import net.simon987.server.logging.LogManager; import org.json.simple.JSONObject; import java.util.ArrayList; @@ -14,7 +13,7 @@ public class KeypressHandler implements MessageHandler { if (!user.isGuest()) { if (json.get("t").equals("k")) { - LogManager.LOGGER.info("(WS) Received keypress"); + //LogManager.LOGGER.fine("(WS) Received keypress"); int key = (int) (long) json.get("k"); diff --git a/Server/src/main/java/net/simon987/server/webserver/MessageEventDispatcher.java b/Server/src/main/java/net/simon987/server/webserver/MessageEventDispatcher.java index 7fe2bc2..c766c9f 100644 --- a/Server/src/main/java/net/simon987/server/webserver/MessageEventDispatcher.java +++ b/Server/src/main/java/net/simon987/server/webserver/MessageEventDispatcher.java @@ -33,11 +33,11 @@ public class MessageEventDispatcher { handler.handle(user, json); } } else { - LogManager.LOGGER.info("Malformed JSON sent by " + user.getUser().getUsername()); + LogManager.LOGGER.severe("Malformed JSON sent by " + user.getUser().getUsername()); } } catch (ParseException e) { - LogManager.LOGGER.info("Malformed JSON sent by " + user.getUser().getUsername()); + LogManager.LOGGER.severe("Malformed JSON sent by " + user.getUser().getUsername()); } } } diff --git a/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java b/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java index 767a45a..d023ca4 100644 --- a/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java @@ -15,14 +15,14 @@ public class ObjectsRequestHandler implements MessageHandler { @Override public void handle(OnlineUser user, JSONObject json) { if (json.get("t").equals("object")) { - LogManager.LOGGER.info("(WS) Objects request from " + user.getUser().getUsername()); + LogManager.LOGGER.fine("(WS) Objects request from " + user.getUser().getUsername()); int x, y; try { x = Long.valueOf((long) json.get("x")).intValue(); y = Long.valueOf((long) json.get("y")).intValue(); } catch (Exception e) { - LogManager.LOGGER.info("(WS) Malformed Objects request from " + user.getUser().getUsername()); + LogManager.LOGGER.severe("(WS) Malformed Objects request from " + user.getUser().getUsername()); return; } diff --git a/Server/src/main/java/net/simon987/server/webserver/SocketServer.java b/Server/src/main/java/net/simon987/server/webserver/SocketServer.java index 3a1c713..56bc81d 100644 --- a/Server/src/main/java/net/simon987/server/webserver/SocketServer.java +++ b/Server/src/main/java/net/simon987/server/webserver/SocketServer.java @@ -2,6 +2,7 @@ package net.simon987.server.webserver; import net.simon987.server.GameServer; import net.simon987.server.ServerConfiguration; +import net.simon987.server.game.ControllableUnit; import net.simon987.server.logging.LogManager; import net.simon987.server.user.User; import org.java_websocket.WebSocket; @@ -172,20 +173,42 @@ public class SocketServer extends WebSocketServer { if (user.isGuest()) { + json.remove("c"); user.getWebSocket().send(json.toJSONString()); } else { - //Send keyboard updated buffer try { - ArrayList kbBuffer = user.getUser().getControlledUnit().getKeyboardBuffer(); + ControllableUnit unit = user.getUser().getControlledUnit(); + + //Send keyboard updated buffer + ArrayList kbBuffer = unit.getKeyboardBuffer(); JSONArray keys = new JSONArray(); keys.addAll(kbBuffer); json.put("keys", keys); + + //Send console buffer + if (unit.getConsoleMessagesBuffer().size() > 0) { + + JSONArray buff = new JSONArray(); + + for (char[] message : unit.getConsoleMessagesBuffer()) { + buff.add(new String(message)); + } + + json.put("c", buff); + } else { + json.remove("c"); + } + + json.put("cm", unit.getConsoleMode()); + + //Send tick message user.getWebSocket().send(json.toJSONString()); } catch (NullPointerException e) { //User is online but not completely initialised } + } diff --git a/Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java b/Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java index 6ae4dac..d47aa22 100644 --- a/Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java @@ -12,7 +12,7 @@ public class TerrainRequestHandler implements MessageHandler { public void handle(OnlineUser user, JSONObject json) { if (json.get("t").equals("terrain") && json.containsKey("x") && json.containsKey("y")) { - LogManager.LOGGER.info("Terrain request from " + user.getUser().getUsername()); + LogManager.LOGGER.fine("Terrain request from " + user.getUser().getUsername()); World world; try { world = GameServer.INSTANCE.getGameUniverse().getWorld( diff --git a/Server/src/main/java/net/simon987/server/webserver/UserInfoRequestHandler.java b/Server/src/main/java/net/simon987/server/webserver/UserInfoRequestHandler.java index 8c84268..ff370af 100644 --- a/Server/src/main/java/net/simon987/server/webserver/UserInfoRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/UserInfoRequestHandler.java @@ -13,7 +13,7 @@ public class UserInfoRequestHandler implements MessageHandler { if (message.get("t").equals("userInfo")) { - LogManager.LOGGER.info("(WS) User info request from " + user.getUser().getUsername()); + LogManager.LOGGER.fine("(WS) User info request from " + user.getUser().getUsername()); JSONObject json = new JSONObject(); if (user.isGuest()) { diff --git a/config.properties b/Server/src/main/resources/config.properties similarity index 97% rename from config.properties rename to Server/src/main/resources/config.properties index 78209cf..ffd7a8b 100644 --- a/config.properties +++ b/Server/src/main/resources/config.properties @@ -65,9 +65,9 @@ wg_centerPointCountMin=5 wg_centerPointCountMax=15 # Wall/Plain tile ratio for the WorldGenerator wg_wallPlainRatio=4 -# Minimum iron tiles count for the WorldGenerator -wg_minIronCount=0 # Minimum iron tile count for the WorldGenerator +wg_minIronCount=0 +# Maximum iron tile count for the WorldGenerator wg_maxIronCount=2 # Minimum copper tile count for the WorldGenerator wg_minCopperCount=0 @@ -77,4 +77,4 @@ wg_maxCopperCount=2 # ---------------------------------------------- # Maximum execution time of user code in ms -user_timeout=100 \ No newline at end of file +user_timeout=100 diff --git a/pom.xml b/pom.xml index 0ff00c0..91054b1 100644 --- a/pom.xml +++ b/pom.xml @@ -13,28 +13,26 @@ - 3.6.2 org.apache.maven.plugins + 3.6.2 maven-compiler-plugin 1.8 1.8 - - 3.6.2 - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - - - + org.apache.maven.plugins maven-jar-plugin + 3.0.2 ../target/plugins + + + false + net.simon987.server.Main + + diff --git a/target/plugins/plugin-biomassBlob-1.2a.jar b/target/plugins/plugin-biomassBlob-1.2a.jar deleted file mode 100644 index a5486be..0000000 Binary files a/target/plugins/plugin-biomassBlob-1.2a.jar and /dev/null differ diff --git a/target/plugins/plugin-cubot-1.2a.jar b/target/plugins/plugin-cubot-1.2a.jar deleted file mode 100644 index de09684..0000000 Binary files a/target/plugins/plugin-cubot-1.2a.jar and /dev/null differ diff --git a/target/plugins/plugin-misc-hw-1.2a.jar b/target/plugins/plugin-misc-hw-1.2a.jar deleted file mode 100644 index a85e7ba..0000000 Binary files a/target/plugins/plugin-misc-hw-1.2a.jar and /dev/null differ diff --git a/target/plugins/plugin-npc-1.2a.jar b/target/plugins/plugin-npc-1.2a.jar deleted file mode 100644 index c5e62cb..0000000 Binary files a/target/plugins/plugin-npc-1.2a.jar and /dev/null differ diff --git a/target/server-1.2a.jar b/target/server-1.2a.jar deleted file mode 100644 index 8a4a432..0000000 Binary files a/target/server-1.2a.jar and /dev/null differ