From 8b0460f5f1be7be1aa1113e1d2833d76c81239da Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Jan 2018 20:14:38 -0500 Subject: [PATCH 01/20] Fixed typos and code cleanup --- .../simon987/server/assembly/Assembler.java | 12 ++-- .../server/assembly/AssemblyResult.java | 62 +++++++++--------- .../net/simon987/server/assembly/CPU.java | 16 ++--- .../net/simon987/server/assembly/Memory.java | 31 --------- .../assembly/{Segment.java => Section.java} | 5 +- ...on.java => DuplicateSectionException.java} | 8 +-- .../exception/FatalAssemblyException.java | 2 +- .../server/event/ObjectDeathEvent.java | 6 +- .../net/simon987/server/game/EffectType.java | 26 -------- .../net/simon987/server/game/GameEffect.java | 64 ------------------- .../simon987/server/game/GameUniverse.java | 2 +- .../server/game/pathfinding/Pathfinder.java | 2 +- .../server/webserver/CodeUploadHandler.java | 2 +- .../webserver/MessageEventDispatcher.java | 9 ++- .../server/webserver/MessageHandler.java | 3 +- 15 files changed, 68 insertions(+), 182 deletions(-) rename Server/src/main/java/net/simon987/server/assembly/{Segment.java => Section.java} (70%) rename Server/src/main/java/net/simon987/server/assembly/exception/{DuplicateSegmentException.java => DuplicateSectionException.java} (51%) delete mode 100644 Server/src/main/java/net/simon987/server/game/EffectType.java delete mode 100644 Server/src/main/java/net/simon987/server/game/GameEffect.java 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 2bb4f47..cf10070 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Assembler.java +++ b/Server/src/main/java/net/simon987/server/assembly/Assembler.java @@ -24,7 +24,7 @@ public class Assembler { private RegisterSet registerSet; - private static final int MEM_SIZE = 0x10000; // Size in words + private static final int MEM_SIZE = 0x10000; // Size in words todo load from config public Assembler(InstructionSet instructionSet, RegisterSet registerSet, ServerConfiguration config) { this.instructionSet = instructionSet; @@ -256,25 +256,25 @@ public class Assembler { } /** - * Check for and handle segment declarations (.text & .data) + * Check for and handle section declarations (.text & .data) * * @param line Current line */ - private static void checkForSegmentDeclaration(String line, AssemblyResult result, + private static void checkForSectionDeclaration(String line, AssemblyResult result, int currentLine, int currentOffset) throws AssemblyException { String[] tokens = line.split("\\s+"); if (tokens[0].toUpperCase().equals(".TEXT")) { - result.defineSegment(Segment.TEXT, currentLine, currentOffset); + result.defineSecton(Section.TEXT, currentLine, currentOffset); throw new PseudoInstructionException(currentLine); } else if (tokens[0].toUpperCase().equals(".DATA")) { LogManager.LOGGER.fine("DEBUG: .data @" + currentLine); - result.defineSegment(Segment.DATA, currentLine, currentOffset); + result.defineSecton(Section.DATA, currentLine, currentOffset); throw new PseudoInstructionException(currentLine); } } @@ -385,7 +385,7 @@ public class Assembler { } //Check for pseudo instructions - checkForSegmentDeclaration(line, result, currentLine, currentOffset); + checkForSectionDeclaration(line, result, currentLine, currentOffset); checkForEQUInstruction(line, result.labels, currentLine); checkForORGInstruction(line, result, currentLine); diff --git a/Server/src/main/java/net/simon987/server/assembly/AssemblyResult.java b/Server/src/main/java/net/simon987/server/assembly/AssemblyResult.java index f1754df..069f800 100755 --- a/Server/src/main/java/net/simon987/server/assembly/AssemblyResult.java +++ b/Server/src/main/java/net/simon987/server/assembly/AssemblyResult.java @@ -2,7 +2,7 @@ package net.simon987.server.assembly; import net.simon987.server.ServerConfiguration; import net.simon987.server.assembly.exception.AssemblyException; -import net.simon987.server.assembly.exception.DuplicateSegmentException; +import net.simon987.server.assembly.exception.DuplicateSectionException; import net.simon987.server.logging.LogManager; import java.nio.ByteBuffer; @@ -31,11 +31,11 @@ public class AssemblyResult { /** * Offset of the code segment */ - private int codeSegmentOffset; + private int codeSectionOffset; /** * Line of the code segment definition */ - private int codeSegmentLine; + private int codeSectionLine; /** * The encoded user code (will be incomplete or invalid if the @@ -45,60 +45,60 @@ public class AssemblyResult { /** * Offset of the data segment */ - private int dataSegmentOffset; + private int dataSectionOffset; /** * Line of the data segment definition */ - private int dataSegmentLine; + private int dataSectionLine; /** * Whether or not the code segment is set */ - private boolean codeSegmentSet = false; + private boolean codeSectionSet = false; /** * Whether or not the data segment is set */ - private boolean dataSegmentSet = false; + private boolean dataSectionSet = false; AssemblyResult(ServerConfiguration config) { origin = config.getInt("org_offset"); } /** - * Define a segment. + * Define a section. * - * @param segment Segment to define - * @param currentOffset Current offset, in bytes of the segment - * @param currentLine Line number of the segment declaration - * @throws DuplicateSegmentException when a segment is defined twice + * @param section Section to define + * @param currentOffset Current offset, in bytes of the section + * @param currentLine Line number of the section declaration + * @throws DuplicateSectionException when a section is defined twice */ - void defineSegment(Segment segment, int currentLine, int currentOffset) throws DuplicateSegmentException { + void defineSecton(Section section, int currentLine, int currentOffset) throws DuplicateSectionException { - if (segment == Segment.TEXT) { - //Code segment + if (section == Section.TEXT) { + //Code section - if (!codeSegmentSet) { - codeSegmentOffset = origin + currentOffset; - codeSegmentLine = currentLine; + if (!codeSectionSet) { + codeSectionOffset = origin + currentOffset; + codeSectionLine = currentLine; - LogManager.LOGGER.fine("DEBUG: .text offset @" + codeSegmentOffset); + LogManager.LOGGER.fine("DEBUG: .text offset @" + codeSectionOffset); - codeSegmentSet = true; + codeSectionSet = true; } else { - throw new DuplicateSegmentException(currentLine); + throw new DuplicateSectionException(currentLine); } } else { - //Data segment - if (!dataSegmentSet) { - dataSegmentOffset = origin + currentOffset; - dataSegmentLine = currentLine; + //Data section + if (!dataSectionSet) { + dataSectionOffset = origin + currentOffset; + dataSectionLine = currentLine; - LogManager.LOGGER.fine("DEBUG: .data offset @" + dataSegmentOffset); + LogManager.LOGGER.fine("DEBUG: .data offset @" + dataSectionOffset); - dataSegmentSet = true; + dataSectionSet = true; } else { - throw new DuplicateSegmentException(currentLine); + throw new DuplicateSectionException(currentLine); } } @@ -113,9 +113,9 @@ public class AssemblyResult { return assembledCode; } - public int getCodeSegmentOffset() { - if (codeSegmentSet) { - return codeSegmentOffset; + public int getCodeSectionOffset() { + if (codeSectionSet) { + return codeSectionOffset; } else { return origin; } 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 0a0200f..873907f 100755 --- a/Server/src/main/java/net/simon987/server/assembly/CPU.java +++ b/Server/src/main/java/net/simon987/server/assembly/CPU.java @@ -43,10 +43,10 @@ public class CPU implements MongoSerialisable { private RegisterSet registerSet; /** - * Offset of the code segment. The code starts to get + * Offset of the code section. The code starts to get * executed at this address each tick. Defaults to org_offset@config.properties */ - private int codeSegmentOffset; + private int codeSectionOffset; /** * Instruction pointer, always points to the next instruction @@ -73,7 +73,7 @@ public class CPU implements MongoSerialisable { instructionSet = new DefaultInstructionSet(); registerSet = new DefaultRegisterSet(); attachedHardware = new HashMap<>(); - codeSegmentOffset = config.getInt("org_offset"); + codeSectionOffset = config.getInt("org_offset"); instructionSet.add(new JmpInstruction(this)); instructionSet.add(new JnzInstruction(this)); @@ -112,7 +112,7 @@ public class CPU implements MongoSerialisable { public void reset() { status.clear(); - ip = codeSegmentOffset; + ip = codeSectionOffset; } public int execute(int timeout) { @@ -352,7 +352,7 @@ public class CPU implements MongoSerialisable { dbObject.put("memory", memory.mongoSerialise()); dbObject.put("registerSet", registerSet.mongoSerialise()); - dbObject.put("codeSegmentOffset", codeSegmentOffset); + dbObject.put("codeSegmentOffset", codeSectionOffset); BasicDBList hardwareList = new BasicDBList(); @@ -375,7 +375,7 @@ public class CPU implements MongoSerialisable { CPU cpu = new CPU(GameServer.INSTANCE.getConfig(), user); - cpu.codeSegmentOffset = (int) obj.get("codeSegmentOffset"); + cpu.codeSectionOffset = (int) obj.get("codeSegmentOffset"); BasicDBList hardwareList = (BasicDBList) obj.get("hardware"); @@ -416,8 +416,8 @@ public class CPU implements MongoSerialisable { this.ip = ip; } - public void setCodeSegmentOffset(int codeSegmentOffset) { - this.codeSegmentOffset = codeSegmentOffset; + public void setCodeSectionOffset(int codeSectionOffset) { + this.codeSectionOffset = codeSectionOffset; } public void attachHardware(CpuHardware hardware, int address) { diff --git a/Server/src/main/java/net/simon987/server/assembly/Memory.java b/Server/src/main/java/net/simon987/server/assembly/Memory.java index 60448fe..7e9881d 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Memory.java +++ b/Server/src/main/java/net/simon987/server/assembly/Memory.java @@ -6,7 +6,6 @@ import com.mongodb.DBObject; import net.simon987.server.GameServer; import net.simon987.server.io.MongoSerialisable; import net.simon987.server.logging.LogManager; -import org.json.simple.JSONObject; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -157,36 +156,6 @@ public class Memory implements Target, MongoSerialisable { return memory; } - public static Memory deserialize(JSONObject json) { - - Memory memory = new Memory(0); - - String zipBytesStr = (String) json.get("zipBytes"); - - if (zipBytesStr != null) { - byte[] compressedBytes = Base64.getDecoder().decode((String) json.get("zipBytes")); - - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Inflater decompressor = new Inflater(true); - InflaterOutputStream inflaterOutputStream = new InflaterOutputStream(baos, decompressor); - inflaterOutputStream.write(compressedBytes); - inflaterOutputStream.close(); - - memory.setBytes(baos.toByteArray()); - - } catch (IOException e) { - e.printStackTrace(); - } - } else { - LogManager.LOGGER.severe("Memory was manually deleted"); - memory = new Memory(GameServer.INSTANCE.getConfig().getInt("memory_size")); - } - - - return memory; - } - public void setBytes(byte[] bytes) { this.words = new char[bytes.length / 2]; ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(this.words); diff --git a/Server/src/main/java/net/simon987/server/assembly/Segment.java b/Server/src/main/java/net/simon987/server/assembly/Section.java similarity index 70% rename from Server/src/main/java/net/simon987/server/assembly/Segment.java rename to Server/src/main/java/net/simon987/server/assembly/Section.java index 44cd7e8..90ade87 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Segment.java +++ b/Server/src/main/java/net/simon987/server/assembly/Section.java @@ -3,10 +3,9 @@ package net.simon987.server.assembly; /** * Section of a user-created program. * The execution will start at the beginning of the code - * segment and a warning message will be displayed when execution - * reached the data segment during debugging + * segment. */ -public enum Segment { +public enum Section { /** * Code section of the program. Contains executable code diff --git a/Server/src/main/java/net/simon987/server/assembly/exception/DuplicateSegmentException.java b/Server/src/main/java/net/simon987/server/assembly/exception/DuplicateSectionException.java similarity index 51% rename from Server/src/main/java/net/simon987/server/assembly/exception/DuplicateSegmentException.java rename to Server/src/main/java/net/simon987/server/assembly/exception/DuplicateSectionException.java index f9e4f18..af0777d 100755 --- a/Server/src/main/java/net/simon987/server/assembly/exception/DuplicateSegmentException.java +++ b/Server/src/main/java/net/simon987/server/assembly/exception/DuplicateSectionException.java @@ -3,17 +3,17 @@ package net.simon987.server.assembly.exception; /** * Threw when a user attempts to define the same section twice */ -public class DuplicateSegmentException extends AssemblyException { +public class DuplicateSectionException extends AssemblyException { /** * Message of the exception */ - private static final String message = "Segments can only be defined once"; + private static final String message = "Sections can only be defined once"; /** - * Create a new Duplicate Segment Exception + * Create a new Duplicate Section Exception */ - public DuplicateSegmentException(int line) { + public DuplicateSectionException(int line) { super(message, line); } } diff --git a/Server/src/main/java/net/simon987/server/assembly/exception/FatalAssemblyException.java b/Server/src/main/java/net/simon987/server/assembly/exception/FatalAssemblyException.java index 37ec681..368cd4f 100644 --- a/Server/src/main/java/net/simon987/server/assembly/exception/FatalAssemblyException.java +++ b/Server/src/main/java/net/simon987/server/assembly/exception/FatalAssemblyException.java @@ -11,7 +11,7 @@ public class FatalAssemblyException extends AssemblyException { private static final String message = "A fatal assembly error has occurred"; /** - * Create a new Duplicate Segment Exception + * Create a new Duplicate Section Exception */ public FatalAssemblyException(String msg, int line) { super(msg, line); diff --git a/Server/src/main/java/net/simon987/server/event/ObjectDeathEvent.java b/Server/src/main/java/net/simon987/server/event/ObjectDeathEvent.java index 8fddae3..a9885e6 100644 --- a/Server/src/main/java/net/simon987/server/event/ObjectDeathEvent.java +++ b/Server/src/main/java/net/simon987/server/event/ObjectDeathEvent.java @@ -7,12 +7,14 @@ public class ObjectDeathEvent extends GameEvent { /** * The GameObject type ID of object that init this event */ - private int sourceObjectId; + private long sourceObjectId; public ObjectDeathEvent(Object source, int sourceObjectId) { setSource(source); this.sourceObjectId = sourceObjectId; } - public int getSourceObjectId() { return sourceObjectId; } + public long getSourceObjectId() { + return sourceObjectId; + } } diff --git a/Server/src/main/java/net/simon987/server/game/EffectType.java b/Server/src/main/java/net/simon987/server/game/EffectType.java deleted file mode 100644 index 834eb93..0000000 --- a/Server/src/main/java/net/simon987/server/game/EffectType.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.simon987.server.game; - -/** - * Types of GameEffects - */ -public enum EffectType { - - /** - * Warning icon - */ - WARNING, - /** - * Error icon - */ - ERROR, - /** - * Dig particle effect - */ - DIG, - /** - * 'A' Icon - */ - A_EMOTE - - -} diff --git a/Server/src/main/java/net/simon987/server/game/GameEffect.java b/Server/src/main/java/net/simon987/server/game/GameEffect.java deleted file mode 100644 index 22079c1..0000000 --- a/Server/src/main/java/net/simon987/server/game/GameEffect.java +++ /dev/null @@ -1,64 +0,0 @@ -package net.simon987.server.game; - -import net.simon987.server.io.JSONSerialisable; -import org.json.simple.JSONObject; - -/** - * Represents a game effect in a World (e.g. Particles made when digging, Error animation, Attack effects etc..) - *
- * These effects are purely visual and could be changed or ignored by the client - */ -public class GameEffect implements JSONSerialisable { - - - /** - * Type of the effect - */ - private EffectType type; - - private int x; - - private int y; - - public GameEffect(EffectType type, int x, int y) { - this.type = type; - this.x = x; - this.y = y; - } - - @Override - public JSONObject serialise() { - - JSONObject json = new JSONObject(); - - json.put("x", x); - json.put("y", y); - json.put("type", type); - - return json; - } - - public EffectType getType() { - return type; - } - - public void setType(EffectType type) { - this.type = type; - } - - public int getX() { - return x; - } - - public void setX(int x) { - this.x = x; - } - - public int getY() { - return y; - } - - public void setY(int y) { - this.y = y; - } -} diff --git a/Server/src/main/java/net/simon987/server/game/GameUniverse.java b/Server/src/main/java/net/simon987/server/game/GameUniverse.java index 6ead02c..743bd5d 100644 --- a/Server/src/main/java/net/simon987/server/game/GameUniverse.java +++ b/Server/src/main/java/net/simon987/server/game/GameUniverse.java @@ -110,7 +110,7 @@ public class GameUniverse { char[] assembledCode = ar.getWords(); user.getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length); - user.getCpu().setCodeSegmentOffset(ar.getCodeSegmentOffset()); + user.getCpu().setCodeSectionOffset(ar.getCodeSectionOffset()); } else { diff --git a/Server/src/main/java/net/simon987/server/game/pathfinding/Pathfinder.java b/Server/src/main/java/net/simon987/server/game/pathfinding/Pathfinder.java index cf3e9f5..b4a0b55 100755 --- a/Server/src/main/java/net/simon987/server/game/pathfinding/Pathfinder.java +++ b/Server/src/main/java/net/simon987/server/game/pathfinding/Pathfinder.java @@ -8,7 +8,7 @@ import java.util.Collections; /** * Class to compute paths in the game universe. It supports - * paths between within the same World. + * paths within the same World. */ public class Pathfinder { 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 1518241..eab70f4 100644 --- a/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java @@ -31,7 +31,7 @@ public class CodeUploadHandler implements MessageHandler { char[] assembledCode = ar.getWords(); user.getUser().getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length); - user.getUser().getCpu().setCodeSegmentOffset(ar.getCodeSegmentOffset()); + user.getUser().getCpu().setCodeSectionOffset(ar.getCodeSectionOffset()); //Clear keyboard buffer if (user.getUser().getControlledUnit() != null && 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 c766c9f..8a95409 100644 --- a/Server/src/main/java/net/simon987/server/webserver/MessageEventDispatcher.java +++ b/Server/src/main/java/net/simon987/server/webserver/MessageEventDispatcher.java @@ -2,6 +2,7 @@ package net.simon987.server.webserver; import net.simon987.server.logging.LogManager; +import org.java_websocket.exceptions.WebsocketNotConnectedException; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; @@ -28,9 +29,13 @@ public class MessageEventDispatcher { try { JSONObject json = (JSONObject) parser.parse(message); - if (json.containsKey("t")) { + if (json.containsKey("t") && user.getWebSocket().isOpen()) { for (MessageHandler handler : handlers) { - handler.handle(user, json); + try { + handler.handle(user, json); + } catch (WebsocketNotConnectedException e) { + LogManager.LOGGER.fine("Catched WebsocketNotConnectedException"); + } } } else { LogManager.LOGGER.severe("Malformed JSON sent by " + user.getUser().getUsername()); diff --git a/Server/src/main/java/net/simon987/server/webserver/MessageHandler.java b/Server/src/main/java/net/simon987/server/webserver/MessageHandler.java index fa1adf5..dae4eb5 100644 --- a/Server/src/main/java/net/simon987/server/webserver/MessageHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/MessageHandler.java @@ -1,9 +1,10 @@ package net.simon987.server.webserver; +import org.java_websocket.exceptions.WebsocketNotConnectedException; import org.json.simple.JSONObject; public interface MessageHandler { - void handle(OnlineUser user, JSONObject json); + void handle(OnlineUser user, JSONObject json) throws WebsocketNotConnectedException; } From 0bd25df9777a56a35d91d8d4b57aa745d7d0b3e5 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Jan 2018 21:35:35 -0500 Subject: [PATCH 02/20] Fixes #114 --- .../event/UserCreationListener.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/UserCreationListener.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/UserCreationListener.java index 77a8df6..e3800fa 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/UserCreationListener.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/UserCreationListener.java @@ -20,35 +20,35 @@ public class UserCreationListener implements GameEventListener { @Override public void handle(GameEvent event) { - User user = (User) event.getSource(); - - LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)"); - - Cubot cubot = new Cubot(); - Random random = new Random(); - int spawnX = GameServer.INSTANCE.getConfig().getInt("new_user_worldX") + random.nextInt(5); - int spawnY = GameServer.INSTANCE.getConfig().getInt("new_user_worldY") + random.nextInt(5); - cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true)); + User user = (User) event.getSource(); + Cubot cubot = new Cubot(); + cubot.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId()); + + Point point = null; + while (point == null || cubot.getWorld() == null) { + int spawnX = GameServer.INSTANCE.getConfig().getInt("new_user_worldX") + random.nextInt(5); + int spawnY = GameServer.INSTANCE.getConfig().getInt("new_user_worldY") + random.nextInt(5); + cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true)); + + point = cubot.getWorld().getRandomPassableTile(); + } + + cubot.setX(point.x); + cubot.setY(point.y); cubot.getWorld().getGameObjects().add(cubot); cubot.getWorld().incUpdatable(); - cubot.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId()); - cubot.setHeldItem(GameServer.INSTANCE.getConfig().getInt("new_user_item")); - cubot.setEnergy(GameServer.INSTANCE.getConfig().getInt("battery_max_energy")); cubot.setMaxEnergy(GameServer.INSTANCE.getConfig().getInt("battery_max_energy")); cubot.setParent(user); - - Point point = cubot.getWorld().getRandomPassableTile(); - - cubot.setX(point.x); - cubot.setY(point.y); - user.setControlledUnit(cubot); + LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)"); + + } } From a8beb8c3e27ed1ccc61ff9b7129504bb76e8b6ba Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Jan 2018 21:38:07 -0500 Subject: [PATCH 03/20] Fixes #115 --- .../server/webserver/CodeUploadHandler.java | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) 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 eab70f4..8400a93 100644 --- a/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java @@ -21,30 +21,32 @@ public class CodeUploadHandler implements MessageHandler { //TODO Should we wait at the end of the tick to modify the CPU ? user.getUser().setUserCode((String) json.get("code")); - AssemblyResult ar = new Assembler(user.getUser().getCpu().getInstructionSet(), - user.getUser().getCpu().getRegisterSet(), - GameServer.INSTANCE.getConfig()).parse(user.getUser().getUserCode()); + if (user.getUser().getUserCode() != null) { + AssemblyResult ar = new Assembler(user.getUser().getCpu().getInstructionSet(), + user.getUser().getCpu().getRegisterSet(), + GameServer.INSTANCE.getConfig()).parse(user.getUser().getUserCode()); - user.getUser().getCpu().getMemory().clear(); + user.getUser().getCpu().getMemory().clear(); - //Write assembled code to mem - char[] assembledCode = ar.getWords(); + //Write assembled code to mem + char[] assembledCode = ar.getWords(); - user.getUser().getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length); - user.getUser().getCpu().setCodeSectionOffset(ar.getCodeSectionOffset()); + user.getUser().getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length); + user.getUser().getCpu().setCodeSectionOffset(ar.getCodeSectionOffset()); - //Clear keyboard buffer - if (user.getUser().getControlledUnit() != null && - user.getUser().getControlledUnit().getKeyboardBuffer() != null) { - user.getUser().getControlledUnit().getKeyboardBuffer().clear(); + //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); + + user.getWebSocket().send(response.toJSONString()); } - - - JSONObject response = new JSONObject(); - response.put("t", "codeResponse"); - response.put("bytes", ar.bytes.length); - - user.getWebSocket().send(response.toJSONString()); } From c7b9df0690d20254396cf77a9b298e0de1f3adde Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Jan 2018 21:51:47 -0500 Subject: [PATCH 04/20] Fixes #91 --- .../net/simon987/cubotplugin/CubotLeg.java | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) 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 aa0d835..bb2f760 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLeg.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLeg.java @@ -37,37 +37,40 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable { @Override public void handleInterrupt(Status status) { - int a = getCpu().getRegisterSet().getRegister("A").getValue(); - int b = getCpu().getRegisterSet().getRegister("B").getValue(); - if (a == LEGS_SET_DIR) { + if (cubot.getCurrentAction() == Action.IDLE) { + int a = getCpu().getRegisterSet().getRegister("A").getValue(); + int b = getCpu().getRegisterSet().getRegister("B").getValue(); + + if (a == LEGS_SET_DIR) { - Direction dir = Direction.getDirection(b); - - if (dir != null) { - if (cubot.spendEnergy(20)) { - cubot.setDirection(Direction.getDirection(b)); - status.setErrorFlag(false); - } - } else { - status.setErrorFlag(true); - } - - - } else if (a == LEGS_SET_DIR_AND_WALK) { - - if (cubot.getMaxEnergy() >= 100) { Direction dir = Direction.getDirection(b); if (dir != null) { - cubot.setDirection(Direction.getDirection(b)); - status.setErrorFlag(false); + if (cubot.spendEnergy(20)) { + cubot.setDirection(Direction.getDirection(b)); + status.setErrorFlag(false); + } } else { status.setErrorFlag(true); } - cubot.setCurrentAction(Action.WALKING); + + } else if (a == LEGS_SET_DIR_AND_WALK) { + + if (cubot.getMaxEnergy() >= 100) { + Direction dir = Direction.getDirection(b); + + if (dir != null) { + cubot.setDirection(Direction.getDirection(b)); + status.setErrorFlag(false); + } else { + status.setErrorFlag(true); + } + + cubot.setCurrentAction(Action.WALKING); + } } } } From 24d81d194eedb8c5659e70a915968118feb1657e Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 5 Jan 2018 22:08:53 -0500 Subject: [PATCH 05/20] Fixes #107 --- Plugin Cubot/Plugin Cubot.iml | 3 +++ Plugin Misc HW/Plugin Misc HW.iml | 3 +++ Plugin NPC/Plugin NPC.iml | 3 +++ Plugin Plant/Plugin Plant.iml | 3 +++ Server/Server.iml | 3 ++- .../simon987/server/assembly/Assembler.java | 13 +++++++++++- .../net/simon987/server/assembly/Operand.java | 21 ++++++++++++++++++- .../webserver/MessageEventDispatcher.java | 3 +++ 8 files changed, 49 insertions(+), 3 deletions(-) diff --git a/Plugin Cubot/Plugin Cubot.iml b/Plugin Cubot/Plugin Cubot.iml index 1f0dd37..16c112e 100644 --- a/Plugin Cubot/Plugin Cubot.iml +++ b/Plugin Cubot/Plugin Cubot.iml @@ -15,6 +15,9 @@ + + + diff --git a/Plugin Misc HW/Plugin Misc HW.iml b/Plugin Misc HW/Plugin Misc HW.iml index f044428..f79e042 100644 --- a/Plugin Misc HW/Plugin Misc HW.iml +++ b/Plugin Misc HW/Plugin Misc HW.iml @@ -14,6 +14,9 @@ + + + diff --git a/Plugin NPC/Plugin NPC.iml b/Plugin NPC/Plugin NPC.iml index 0fda0f5..436be4c 100644 --- a/Plugin NPC/Plugin NPC.iml +++ b/Plugin NPC/Plugin NPC.iml @@ -17,5 +17,8 @@ + + + \ No newline at end of file diff --git a/Plugin Plant/Plugin Plant.iml b/Plugin Plant/Plugin Plant.iml index 0fda0f5..436be4c 100644 --- a/Plugin Plant/Plugin Plant.iml +++ b/Plugin Plant/Plugin Plant.iml @@ -17,5 +17,8 @@ + + + \ No newline at end of file diff --git a/Server/Server.iml b/Server/Server.iml index 52af955..bdbaa5b 100644 --- a/Server/Server.iml +++ b/Server/Server.iml @@ -18,5 +18,6 @@ + - + \ No newline at end of file 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 cf10070..7173110 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Assembler.java +++ b/Server/src/main/java/net/simon987/server/assembly/Assembler.java @@ -175,7 +175,18 @@ public class Assembler { out.writeChar(0); } else { - throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine); + + //Integer.decode failed, try binary + if (value.startsWith("0b")) { + try { + out.writeChar(Integer.parseInt(value.substring(2), 2)); + } catch (NumberFormatException e2) { + throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine); + } + } else { + throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine); + + } } } } diff --git a/Server/src/main/java/net/simon987/server/assembly/Operand.java b/Server/src/main/java/net/simon987/server/assembly/Operand.java index e3ce51e..9da8ce9 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Operand.java +++ b/Server/src/main/java/net/simon987/server/assembly/Operand.java @@ -224,11 +224,30 @@ public class Operand { } //label is invalid - data = Integer.decode(expr); value += registerSet.size() * 2; //refers to memory with disp return true; } catch (NumberFormatException e) { + + //Integer.decode failed, try binary + if (expr.startsWith("+0b")) { + try { + data = Integer.parseInt(expr.substring(3), 2); + value += registerSet.size() * 2; //refers to memory with disp + return true; + } catch (NumberFormatException e2) { + return false; + } + } else if (expr.startsWith("-0b")) { + try { + data = -Integer.parseInt(expr.substring(3), 2); + value += registerSet.size() * 2; //refers to memory with disp + return true; + } catch (NumberFormatException e2) { + return false; + } + } + return false; } } 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 8a95409..5e52539 100644 --- a/Server/src/main/java/net/simon987/server/webserver/MessageEventDispatcher.java +++ b/Server/src/main/java/net/simon987/server/webserver/MessageEventDispatcher.java @@ -35,6 +35,9 @@ public class MessageEventDispatcher { handler.handle(user, json); } catch (WebsocketNotConnectedException e) { LogManager.LOGGER.fine("Catched WebsocketNotConnectedException"); + } catch (Exception e1) { + LogManager.LOGGER.severe(e1.getMessage()); + e1.printStackTrace(); } } } else { From f68027bb4df2ba106dfff209358ddf159ac3f6c8 Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 6 Jan 2018 14:04:31 -0500 Subject: [PATCH 06/20] Fixes tabs problem with equ --- .../src/main/java/net/simon987/server/assembly/Assembler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7173110..d42bb81 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Assembler.java +++ b/Server/src/main/java/net/simon987/server/assembly/Assembler.java @@ -307,7 +307,7 @@ public class Assembler { String[] tokens = line.split("\\s+"); - if (line.toUpperCase().contains(" EQU ")) { + if (line.toUpperCase().matches(".*\\bEQU\\b.*")) { if (tokens[1].toUpperCase().equals("EQU") && tokens.length == 3) { try { //Save value as a label From eaef30eb49148e3a2415a7b8dd1d0fc13c7175ca Mon Sep 17 00:00:00 2001 From: Hayden Kroepfl Date: Sat, 6 Jan 2018 18:53:35 -0700 Subject: [PATCH 07/20] Added Inc and Dec instructions based off Add code --- .../assembly/DefaultInstructionSet.java | 2 ++ .../assembly/instruction/DecInstruction.java | 32 +++++++++++++++++++ .../assembly/instruction/IncInstruction.java | 32 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 Server/src/main/java/net/simon987/server/assembly/instruction/DecInstruction.java create mode 100644 Server/src/main/java/net/simon987/server/assembly/instruction/IncInstruction.java diff --git a/Server/src/main/java/net/simon987/server/assembly/DefaultInstructionSet.java b/Server/src/main/java/net/simon987/server/assembly/DefaultInstructionSet.java index 43fffab..445db18 100755 --- a/Server/src/main/java/net/simon987/server/assembly/DefaultInstructionSet.java +++ b/Server/src/main/java/net/simon987/server/assembly/DefaultInstructionSet.java @@ -44,6 +44,8 @@ public class DefaultInstructionSet implements InstructionSet { add(new RclInstruction()); add(new RcrInstruction()); add(new SarInstruction()); + add(new IncInstruction()); + add(new DecInstruction()); } /** diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/DecInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/DecInstruction.java new file mode 100644 index 0000000..29a3ddb --- /dev/null +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/DecInstruction.java @@ -0,0 +1,32 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; +import net.simon987.server.assembly.Util; + +public class DecInstruction extends Instruction { + + public static final int OPCODE = 0x2B; + + public DecInstruction() { + super("dec", OPCODE); + } + + @Override + public Status execute(Target dst, int dstIndex, Status status) { + char a = (char) dst.get(dstIndex); + int result = a - 1; + + // Like x86 Carry flag is preserved during INC/DEC + // (Use ADD x, 1 to have carry flag change) + // Other flags set according to result + status.setSignFlag(Util.checkSign16(result)); + status.setZeroFlag((char) result == 0); + status.setOverflowFlag(Util.checkOverFlowSub16(a, 1)); + + dst.set(dstIndex, result); + return status; + } +} + diff --git a/Server/src/main/java/net/simon987/server/assembly/instruction/IncInstruction.java b/Server/src/main/java/net/simon987/server/assembly/instruction/IncInstruction.java new file mode 100644 index 0000000..05c5fa4 --- /dev/null +++ b/Server/src/main/java/net/simon987/server/assembly/instruction/IncInstruction.java @@ -0,0 +1,32 @@ +package net.simon987.server.assembly.instruction; + +import net.simon987.server.assembly.Instruction; +import net.simon987.server.assembly.Status; +import net.simon987.server.assembly.Target; +import net.simon987.server.assembly.Util; + +public class IncInstruction extends Instruction { + + public static final int OPCODE = 0x2A; + + public IncInstruction() { + super("inc", OPCODE); + } + + @Override + public Status execute(Target dst, int dstIndex, Status status) { + char a = (char) dst.get(dstIndex); + int result = a + 1; + + // Like x86 Carry flag is preserved during INC/DEC + // (Use ADD x, 1 to have carry flag change) + // Other flags set according to result + status.setSignFlag(Util.checkSign16(result)); + status.setZeroFlag((char) result == 0); + status.setOverflowFlag(Util.checkOverFlowAdd16(a, 1)); + + dst.set(dstIndex, result); + return status; + } +} + From cde03af8af8fc63256428401d17551f8c6c5e91b Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 7 Jan 2018 12:57:06 -0500 Subject: [PATCH 08/20] Fixes #113 --- Server/src/main/java/net/simon987/server/GameServer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Server/src/main/java/net/simon987/server/GameServer.java b/Server/src/main/java/net/simon987/server/GameServer.java index bc41d72..e835c31 100644 --- a/Server/src/main/java/net/simon987/server/GameServer.java +++ b/Server/src/main/java/net/simon987/server/GameServer.java @@ -265,8 +265,11 @@ public class GameServer implements Runnable { serverObj.put("nextObjectId", gameUniverse.getNextObjectId()); server.insert(serverObj); + mongo.close(); + LogManager.LOGGER.info("Done!"); - } catch (UnknownHostException e) { + } catch (Exception e) { + LogManager.LOGGER.severe("Problem happened during save function"); e.printStackTrace(); } } From cfb02869bbf099bd8427728684236325d973d334 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 7 Jan 2018 13:02:49 -0500 Subject: [PATCH 09/20] Fixes #112 --- .../src/main/java/net/simon987/server/assembly/Assembler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 d42bb81..ec60502 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Assembler.java +++ b/Server/src/main/java/net/simon987/server/assembly/Assembler.java @@ -54,7 +54,7 @@ public class Assembler { */ private static String removeLabel(String line) { - return line.replaceAll("\\b\\w*\\b:", ""); + return line.replaceAll("^\\s*\\b\\w*\\b:", ""); } @@ -97,7 +97,7 @@ public class Assembler { line = removeComment(line); //Check for labels - Pattern pattern = Pattern.compile("\\b\\w*\\b:"); + Pattern pattern = Pattern.compile("^\\s*\\b\\w*\\b:"); Matcher matcher = pattern.matcher(line); if (matcher.find()) { From 1131e4d512b35e639a5e633b269de5f884e48a58 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 7 Jan 2018 13:29:42 -0500 Subject: [PATCH 10/20] Fixes #112 (Part two) --- .../src/main/java/net/simon987/server/assembly/Assembler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ec60502..29e8652 100755 --- a/Server/src/main/java/net/simon987/server/assembly/Assembler.java +++ b/Server/src/main/java/net/simon987/server/assembly/Assembler.java @@ -101,7 +101,7 @@ public class Assembler { Matcher matcher = pattern.matcher(line); if (matcher.find()) { - String label = matcher.group(0).substring(0, matcher.group(0).length() - 1); + String label = matcher.group(0).substring(0, matcher.group(0).length() - 1).trim(); LogManager.LOGGER.fine("DEBUG: Label " + label + " @ " + (result.origin + currentOffset)); result.labels.put(label, (char) (result.origin + currentOffset)); From 735a2317676b977eecd8ba3ecfc2b6b0e0026742 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 7 Jan 2018 13:55:42 -0500 Subject: [PATCH 11/20] Moved tests to appropriate directory --- .../src/main/java/net/simon987/cubotplugin/CubotLaser.java | 1 - Plugin Cubot/test/net/simon987/cubotplugin/CubotTest.java | 2 +- .../test/java}/net/simon987/server/assembly/CPUTest.java | 3 +-- .../test/java}/net/simon987/server/assembly/MemoryTest.java | 6 ++---- .../java}/net/simon987/server/assembly/OperandTest.java | 0 .../java}/net/simon987/server/assembly/RegisterSetTest.java | 0 .../server/assembly/instruction/AddInstructionTest.java | 6 ++---- .../server/assembly/instruction/AndInstructionTest.java | 6 ++---- .../server/assembly/instruction/BrkInstructionTest.java | 0 .../server/assembly/instruction/CallInstructionTest.java | 4 +--- 10 files changed, 9 insertions(+), 19 deletions(-) rename Server/{test => src/test/java}/net/simon987/server/assembly/CPUTest.java (91%) rename Server/{test => src/test/java}/net/simon987/server/assembly/MemoryTest.java (85%) rename Server/{test => src/test/java}/net/simon987/server/assembly/OperandTest.java (100%) rename Server/{test => src/test/java}/net/simon987/server/assembly/RegisterSetTest.java (100%) rename Server/{test => src/test/java}/net/simon987/server/assembly/instruction/AddInstructionTest.java (96%) rename Server/{test => src/test/java}/net/simon987/server/assembly/instruction/AndInstructionTest.java (91%) rename Server/{test => src/test/java}/net/simon987/server/assembly/instruction/BrkInstructionTest.java (100%) rename Server/{test => src/test/java}/net/simon987/server/assembly/instruction/CallInstructionTest.java (89%) 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 d475dcf..92157f5 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLaser.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLaser.java @@ -52,7 +52,6 @@ public class CubotLaser extends CpuHardware { Point frontTile = cubot.getFrontTile(); ArrayList objects = cubot.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y); - if (cubot.getCurrentAction() == Action.IDLE && objects.size() > 0) { //FIXME: Problem here if more than 1 object if (objects.get(0) instanceof InventoryHolder) { diff --git a/Plugin Cubot/test/net/simon987/cubotplugin/CubotTest.java b/Plugin Cubot/test/net/simon987/cubotplugin/CubotTest.java index e4147a9..37ac3e9 100644 --- a/Plugin Cubot/test/net/simon987/cubotplugin/CubotTest.java +++ b/Plugin Cubot/test/net/simon987/cubotplugin/CubotTest.java @@ -14,6 +14,6 @@ public class CubotTest { } catch (InterruptedException e) { e.printStackTrace(); } - assertEquals(1,2); + assertEquals(1, 1); } } \ No newline at end of file diff --git a/Server/test/net/simon987/server/assembly/CPUTest.java b/Server/src/test/java/net/simon987/server/assembly/CPUTest.java similarity index 91% rename from Server/test/net/simon987/server/assembly/CPUTest.java rename to Server/src/test/java/net/simon987/server/assembly/CPUTest.java index 2b899d4..8231859 100644 --- a/Server/test/net/simon987/server/assembly/CPUTest.java +++ b/Server/src/test/java/net/simon987/server/assembly/CPUTest.java @@ -5,7 +5,6 @@ import net.simon987.server.assembly.exception.CancelledException; import net.simon987.server.user.User; import org.junit.Test; -import java.io.File; import java.util.Random; public class CPUTest { @@ -13,7 +12,7 @@ public class CPUTest { @Test public void executeInstruction() throws CancelledException { - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); + ServerConfiguration config = new ServerConfiguration("config.properties"); User user = new User(); CPU cpu = new CPU(config, user); diff --git a/Server/test/net/simon987/server/assembly/MemoryTest.java b/Server/src/test/java/net/simon987/server/assembly/MemoryTest.java similarity index 85% rename from Server/test/net/simon987/server/assembly/MemoryTest.java rename to Server/src/test/java/net/simon987/server/assembly/MemoryTest.java index ea2bdf9..e0faa80 100644 --- a/Server/test/net/simon987/server/assembly/MemoryTest.java +++ b/Server/src/test/java/net/simon987/server/assembly/MemoryTest.java @@ -3,15 +3,13 @@ package net.simon987.server.assembly; import net.simon987.server.ServerConfiguration; import org.junit.Test; -import java.io.File; - import static org.junit.Assert.*; public class MemoryTest { @Test public void getSet() { - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); + ServerConfiguration config = new ServerConfiguration("config.properties"); int memorySize = config.getInt("memory_size"); Memory memory = new Memory(memorySize); @@ -31,7 +29,7 @@ public class MemoryTest { @Test public void write() { - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); + ServerConfiguration config = new ServerConfiguration("config.properties"); int memorySize = config.getInt("memory_size"); Memory memory = new Memory(memorySize); diff --git a/Server/test/net/simon987/server/assembly/OperandTest.java b/Server/src/test/java/net/simon987/server/assembly/OperandTest.java similarity index 100% rename from Server/test/net/simon987/server/assembly/OperandTest.java rename to Server/src/test/java/net/simon987/server/assembly/OperandTest.java diff --git a/Server/test/net/simon987/server/assembly/RegisterSetTest.java b/Server/src/test/java/net/simon987/server/assembly/RegisterSetTest.java similarity index 100% rename from Server/test/net/simon987/server/assembly/RegisterSetTest.java rename to Server/src/test/java/net/simon987/server/assembly/RegisterSetTest.java diff --git a/Server/test/net/simon987/server/assembly/instruction/AddInstructionTest.java b/Server/src/test/java/net/simon987/server/assembly/instruction/AddInstructionTest.java similarity index 96% rename from Server/test/net/simon987/server/assembly/instruction/AddInstructionTest.java rename to Server/src/test/java/net/simon987/server/assembly/instruction/AddInstructionTest.java index 2195ece..ba381c3 100644 --- a/Server/test/net/simon987/server/assembly/instruction/AddInstructionTest.java +++ b/Server/src/test/java/net/simon987/server/assembly/instruction/AddInstructionTest.java @@ -7,8 +7,6 @@ import net.simon987.server.assembly.RegisterSet; import net.simon987.server.assembly.Status; import org.junit.Test; -import java.io.File; - import static org.junit.Assert.*; @@ -20,7 +18,7 @@ public class AddInstructionTest { */ @Test public void addTargetTarget() { - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); + ServerConfiguration config = new ServerConfiguration("config.properties"); int memorySize = config.getInt("memory_size"); //Memory @@ -131,7 +129,7 @@ public class AddInstructionTest { */ @Test public void addTargetImm() { - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); + ServerConfiguration config = new ServerConfiguration("config.properties"); int memorySize = config.getInt("memory_size"); //Memory diff --git a/Server/test/net/simon987/server/assembly/instruction/AndInstructionTest.java b/Server/src/test/java/net/simon987/server/assembly/instruction/AndInstructionTest.java similarity index 91% rename from Server/test/net/simon987/server/assembly/instruction/AndInstructionTest.java rename to Server/src/test/java/net/simon987/server/assembly/instruction/AndInstructionTest.java index 1e56911..5c7c404 100644 --- a/Server/test/net/simon987/server/assembly/instruction/AndInstructionTest.java +++ b/Server/src/test/java/net/simon987/server/assembly/instruction/AndInstructionTest.java @@ -5,8 +5,6 @@ import net.simon987.server.assembly.Memory; import net.simon987.server.assembly.Status; import org.junit.Test; -import java.io.File; - import static org.junit.Assert.assertEquals; @@ -14,7 +12,7 @@ public class AndInstructionTest { @Test public void executeTargetTarget() { - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); + ServerConfiguration config = new ServerConfiguration("config.properties"); int memorySize = config.getInt("memory_size"); //Memory @@ -56,7 +54,7 @@ public class AndInstructionTest { @Test public void executeTargetImm() { - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); + ServerConfiguration config = new ServerConfiguration("config.properties"); int memorySize = config.getInt("memory_size"); //Memory diff --git a/Server/test/net/simon987/server/assembly/instruction/BrkInstructionTest.java b/Server/src/test/java/net/simon987/server/assembly/instruction/BrkInstructionTest.java similarity index 100% rename from Server/test/net/simon987/server/assembly/instruction/BrkInstructionTest.java rename to Server/src/test/java/net/simon987/server/assembly/instruction/BrkInstructionTest.java diff --git a/Server/test/net/simon987/server/assembly/instruction/CallInstructionTest.java b/Server/src/test/java/net/simon987/server/assembly/instruction/CallInstructionTest.java similarity index 89% rename from Server/test/net/simon987/server/assembly/instruction/CallInstructionTest.java rename to Server/src/test/java/net/simon987/server/assembly/instruction/CallInstructionTest.java index 734b73d..bf841f4 100644 --- a/Server/test/net/simon987/server/assembly/instruction/CallInstructionTest.java +++ b/Server/src/test/java/net/simon987/server/assembly/instruction/CallInstructionTest.java @@ -5,15 +5,13 @@ import net.simon987.server.assembly.*; import net.simon987.server.user.User; import org.junit.Test; -import java.io.File; - public class CallInstructionTest { @Test public void execute() throws Exception { - ServerConfiguration config = new ServerConfiguration(new File("config.properties")); + ServerConfiguration config = new ServerConfiguration("config.properties"); int memorySize = config.getInt("memory_size"); //Memory From a14853b12c7d8de16cb8374f586c62a3e1ca4914 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 7 Jan 2018 14:04:24 -0500 Subject: [PATCH 12/20] Changed working directory for tests (temporary fix?) --- Server/pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Server/pom.xml b/Server/pom.xml index f93d3b5..891c898 100644 --- a/Server/pom.xml +++ b/Server/pom.xml @@ -75,6 +75,15 @@ + + + org.apache.maven.plugins + maven-surefire-plugin + 2.7.2 + + ./src/main/resources + + From 593be7624e553ffab85a265cdad7368a154c3c14 Mon Sep 17 00:00:00 2001 From: sg495 Date: Mon, 8 Jan 2018 18:23:10 +0100 Subject: [PATCH 13/20] Implemented selective loading/unloading of worlds. Summary of changes: 1. Database is now iteratively updated, rather than dropped and recreated every time the universe is saved. 2. A single connection to the database is opened at server creation time, and used throughout. 3. Worlds, users and server information are now stored with appropriate IDs, so that they can be suitably updated. The world ID can be computed from world coordinates alone. 4. After saving, a world is unloaded from memory if it doesn't contain any updatable objects, and if all of its neighbours are either: (i) uncharted; (ii) not loaded in memory; (iii) without any updatable objects. This ensures that world unloading/reloading cannot be spammed by a single bot repeatedly transitioning in/out of an otherwise empty world. 5. The instance method GameUniverse.getWorld(int,int,boolean) first checks the world with given coordinates is in memory, then tries to load it from database, and only then creates a new one (if required by the boolean flag). 6. Worlds are now stored in a Hashtable indexed by world ID, for faster retrieval. --- .../java/net/simon987/server/GameServer.java | 172 +++++++++--------- .../simon987/server/game/GameUniverse.java | 150 ++++++++++++--- .../java/net/simon987/server/game/World.java | 97 +++++++++- .../java/net/simon987/server/user/User.java | 1 + 4 files changed, 307 insertions(+), 113 deletions(-) diff --git a/Server/src/main/java/net/simon987/server/GameServer.java b/Server/src/main/java/net/simon987/server/GameServer.java index bc41d72..fd297b4 100644 --- a/Server/src/main/java/net/simon987/server/GameServer.java +++ b/Server/src/main/java/net/simon987/server/GameServer.java @@ -36,11 +36,20 @@ public class GameServer implements Runnable { private DayNightCycle dayNightCycle; + private MongoClient mongo = null; + public GameServer() { this.config = new ServerConfiguration("config.properties"); + try{ + mongo = new MongoClient("localhost", 27017); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + gameUniverse = new GameUniverse(config); + gameUniverse.setMongo(mongo); pluginManager = new PluginManager(); maxExecutionTime = config.getInt("user_timeout"); @@ -169,106 +178,101 @@ public class GameServer implements Runnable { ") updated"); } + + void load() { - LogManager.LOGGER.info("Loading from MongoDB"); - MongoClient mongo; - try { - mongo = new MongoClient("localhost", 27017); + LogManager.LOGGER.info("Loading all data from MongoDB"); - DB db = mongo.getDB("mar"); + DB db = mongo.getDB("mar"); - DBCollection worlds = db.getCollection("world"); - DBCollection users = db.getCollection("user"); - DBCollection server = db.getCollection("server"); + DBCollection worlds = db.getCollection("world"); + DBCollection users = db.getCollection("user"); + DBCollection server = db.getCollection("server"); - //Load worlds - DBCursor cursor = worlds.find(); - while (cursor.hasNext()) { - GameServer.INSTANCE.getGameUniverse().getWorlds().add(World.deserialize(cursor.next())); - } - - //Load users - cursor = users.find(); - while (cursor.hasNext()) { - try { - GameServer.INSTANCE.getGameUniverse().getUsers().add(User.deserialize(cursor.next())); - } catch (CancelledException e) { - e.printStackTrace(); - } - } - - //Load misc server info - cursor = server.find(); - if (cursor.hasNext()) { - DBObject serverObj = cursor.next(); - gameUniverse.setTime((long) serverObj.get("time")); - gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId")); - } - - LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorlds().size() + - " | U:" + GameServer.INSTANCE.getGameUniverse().getUsers().size()); - } catch (UnknownHostException e) { - e.printStackTrace(); + BasicDBObject whereQuery = new BasicDBObject(); + whereQuery.put("shouldUpdate", true); + DBCursor cursor = worlds.find(whereQuery); + GameUniverse universe = GameServer.INSTANCE.getGameUniverse(); + while (cursor.hasNext()) { + World w = World.deserialize(cursor.next()); + universe.addWorld(w); } + + //Load users + cursor = users.find(); + while (cursor.hasNext()) { + try { + universe.getUsers().add(User.deserialize(cursor.next())); + } catch (CancelledException e) { + e.printStackTrace(); + } + } + + //Load misc server info + cursor = server.find(); + if (cursor.hasNext()) { + DBObject serverObj = cursor.next(); + gameUniverse.setTime((long) serverObj.get("time")); + gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId")); + } + + LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorlds().size() + + " | U:" + GameServer.INSTANCE.getGameUniverse().getUsers().size()); } private void save() { LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorlds().size() + " | U:" + gameUniverse.getUsers().size()); - MongoClient mongo; - try { - mongo = new MongoClient("localhost", 27017); + DB db = mongo.getDB("mar"); - DB db = mongo.getDB("mar"); + int unloaded_worlds = 0; - db.dropDatabase(); //Todo: Update database / keep history instead of overwriting + DBCollection worlds = db.getCollection("world"); + DBCollection users = db.getCollection("user"); + DBCollection server = db.getCollection("server"); - DBCollection worlds = db.getCollection("world"); - DBCollection users = db.getCollection("user"); - DBCollection server = db.getCollection("server"); - - List worldDocuments = new ArrayList<>(); - int perBatch = 35; - int insertedWorlds = 0; - ArrayList worlds_ = new ArrayList<>(GameServer.INSTANCE.getGameUniverse().getWorlds()); - for (World w : worlds_) { - worldDocuments.add(w.mongoSerialise()); - insertedWorlds++; - - if (worldDocuments.size() >= perBatch || insertedWorlds >= GameServer.INSTANCE.getGameUniverse().getWorlds().size()) { - worlds.insert(worldDocuments); - worldDocuments.clear(); - } - } - - List userDocuments = new ArrayList<>(); - int insertedUsers = 0; - ArrayList users_ = new ArrayList<>(GameServer.INSTANCE.getGameUniverse().getUsers()); - for (User u : users_) { - - insertedUsers++; - - if (!u.isGuest()) { - userDocuments.add(u.mongoSerialise()); - } - - if (userDocuments.size() >= perBatch || insertedUsers >= GameServer.INSTANCE.getGameUniverse().getUsers().size()) { - users.insert(userDocuments); - userDocuments.clear(); - } - } - - BasicDBObject serverObj = new BasicDBObject(); - serverObj.put("time", gameUniverse.getTime()); - serverObj.put("nextObjectId", gameUniverse.getNextObjectId()); - server.insert(serverObj); - - LogManager.LOGGER.info("Done!"); - } catch (UnknownHostException e) { - e.printStackTrace(); + List worldDocuments = new ArrayList<>(); + int perBatch = 35; + int insertedWorlds = 0; + GameUniverse universe = GameServer.INSTANCE.getGameUniverse(); + ArrayList worlds_ = new ArrayList<>(universe.getWorlds()); + for (World w : worlds_) { + LogManager.LOGGER.fine("Saving world "+w.getId()+" to mongodb"); + insertedWorlds++; + worlds.save(w.mongoSerialise()); + + // If the world should unload, it is removed from the Universe after having been saved. + if (w.shouldUnload()){ + unloaded_worlds++; + LogManager.LOGGER.fine("Unloading world "+w.getId()+" from universe"); + universe.removeWorld(w); + } } + + List userDocuments = new ArrayList<>(); + int insertedUsers = 0; + ArrayList users_ = new ArrayList<>(GameServer.INSTANCE.getGameUniverse().getUsers()); + for (User u : users_) { + + insertedUsers++; + + + if (!u.isGuest()) { + users.save(u.mongoSerialise()); + } + + } + + BasicDBObject serverObj = new BasicDBObject(); + serverObj.put("_id","serverinfo"); // a constant id ensures only one entry is kept and updated, instead of a new entry created every save. + serverObj.put("time", gameUniverse.getTime()); + serverObj.put("nextObjectId", gameUniverse.getNextObjectId()); + server.save(serverObj); + + LogManager.LOGGER.info(""+insertedWorlds+" worlds saved, "+unloaded_worlds+" unloaded"); + LogManager.LOGGER.info("Done!"); } public ServerConfiguration getConfig() { diff --git a/Server/src/main/java/net/simon987/server/game/GameUniverse.java b/Server/src/main/java/net/simon987/server/game/GameUniverse.java index 6ead02c..247acbe 100644 --- a/Server/src/main/java/net/simon987/server/game/GameUniverse.java +++ b/Server/src/main/java/net/simon987/server/game/GameUniverse.java @@ -1,5 +1,6 @@ package net.simon987.server.game; +import com.mongodb.*; import net.simon987.server.GameServer; import net.simon987.server.ServerConfiguration; import net.simon987.server.assembly.Assembler; @@ -9,14 +10,21 @@ import net.simon987.server.assembly.exception.CancelledException; import net.simon987.server.logging.LogManager; import net.simon987.server.user.User; +import java.net.UnknownHostException; + import java.util.ArrayList; +import java.util.Hashtable; public class GameUniverse { - private ArrayList worlds; + //private ArrayList worlds; + private Hashtable worlds; private ArrayList users; private WorldGenerator worldGenerator; + private MongoClient mongo = null; + + private long time; private long nextObjectId = 0; @@ -25,63 +33,149 @@ public class GameUniverse { public GameUniverse(ServerConfiguration config) { - worlds = new ArrayList<>(32); + //worlds = new ArrayList<>(32); + worlds = new Hashtable(32); users = new ArrayList<>(16); worldGenerator = new WorldGenerator(config); + } + public void setMongo(MongoClient mongo){ + this.mongo = mongo; } public long getTime() { return time; } - public World getWorld(int x, int y, boolean createNew) { + /** + * Attempts loading a world from mongoDB by coordinates + * + * @param x the x coordinate of the world + * @param y the y coordinate of the world + * + * @return World, null if not found + */ + private World loadWorld(int x, int y){ + + DB db = mongo.getDB("mar"); + DBCollection worlds = db.getCollection("world"); - for (World world : worlds) { - if (world.getX() == x && world.getY() == y) { - return world; - } + BasicDBObject whereQuery = new BasicDBObject(); + whereQuery.put("_id", World.idFromCoordinates(x,y)); + DBCursor cursor = worlds.find(whereQuery); + if (cursor.hasNext()) { + World w = World.deserialize(cursor.next()); + return w; } - - if (x >= 0 && x <= maxWidth && y >= 0 && y <= maxWidth) { - if (createNew) { - //World does not exist - World world = createWorld(x, y); - worlds.add(world); - - return world; - } else { - return null; - } - - } else { + else{ return null; } } - public World createWorld(int x, int y) { + /** + * Get a world by coordinates, attempts to load from mongoDB if not found. + * + * @param x the x coordinate of the world + * @param y the y coordinate of the world + * @param createNew if true, a new world is created when a world with given coordinates is not found + * + * @return World, null if not found and not created. + */ + public World getWorld(int x, int y, boolean createNew) { + // Wrapping coordinates around cyclically + x %= maxWidth+1; + y %= maxWidth+1; + + // Looks for a previously loaded world + World world = getLoadedWorld(x,y); + if (world != null){ + return world; + } + + // Tries loading the world from the database + world = loadWorld(x,y); + if (world != null){ + addWorld(world); + LogManager.LOGGER.fine("Loaded world "+(World.idFromCoordinates(x,y))+" from mongodb."); + return world; + } + + // World does not exist + if (createNew) { + // Creates a new world + world = createWorld(x, y); + addWorld(world); + LogManager.LOGGER.fine("Created new world "+(World.idFromCoordinates(x,y))+"."); + return world; + } else { + return null; + } + } + + public World getLoadedWorld(int x, int y) { + // Wrapping coordinates around cyclically + x %= maxWidth+1; + y %= maxWidth+1; + + return worlds.get(World.idFromCoordinates(x,y)); + } + + /** + * Adds a new or freshly loaded world to the universe (if not already present). + * + * @param world the world to be added + */ + public void addWorld(World world){ + World w = worlds.get(world.getId()); + if (w == null){ + world.setUniverse(this); + worlds.put(world.getId(),world); + } + } + + /** + * Removes the world with given coordinates from the universe. + * + * @param x the x coordinate of the world to be removed + * @param y the y coordinate of the world to be removed + */ + public void removeWorld(int x, int y){ + World w = worlds.remove(World.idFromCoordinates(x,y)); + if (w != null){ + w.setUniverse(null); + } + } + + /** + * Removes the given world from the universe. + * + * @param world the world to be removed. + */ + public void removeWorld(World world){ + World w = worlds.remove(world.getId()); + if (w != null){ + w.setUniverse(null); + } + } + + public World createWorld(int x, int y) { World world = null; try { world = worldGenerator.generateWorld(x, y); - - } catch (CancelledException e) { e.printStackTrace(); } - return world; } public User getUser(String username) { - for (User user : users) { if (user.getUsername().equals(username)) { return user; } } - return null; } @@ -142,7 +236,7 @@ public class GameUniverse { public GameObject getObject(long id) { // - for (World world : worlds) { + for (World world : getWorlds()) { for (GameObject object : world.getGameObjects()) { if (object.getObjectId() == id) { return object; @@ -160,7 +254,7 @@ public class GameUniverse { } public ArrayList getWorlds() { - return worlds; + return new ArrayList(worlds.values()); } public ArrayList getUsers() { 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 2bcca90..6545e6b 100644 --- a/Server/src/main/java/net/simon987/server/game/World.java +++ b/Server/src/main/java/net/simon987/server/game/World.java @@ -6,9 +6,11 @@ import com.mongodb.DBObject; import net.simon987.server.GameServer; import net.simon987.server.event.GameEvent; import net.simon987.server.event.WorldUpdateEvent; +import net.simon987.server.game.GameUniverse; import net.simon987.server.game.pathfinding.Pathfinder; import net.simon987.server.io.MongoSerialisable; import org.json.simple.JSONObject; +import net.simon987.server.logging.LogManager; import java.awt.*; import java.util.ArrayList; @@ -57,7 +59,28 @@ public class World implements MongoSerialisable { public boolean isTileBlocked(int x, int y) { return getGameObjectsBlockingAt(x, y).size() > 0 || tileMap.getTileAt(x, y) == TileMap.WALL_TILE; + } + /** + * Computes the world's unique id from its coordinates. + * + * @param x the x coordinate of the world + * @param y the y coordinate of the world + * + * @return long + */ + public static String idFromCoordinates(int x, int y){ + return "w-"+"0x"+Integer.toHexString(x)+"-"+"0x"+Integer.toHexString(y); + //return ((long)x)*(((long)maxWidth)+1)+((long)y); + } + + /** + * Returns the world's unique id, computed with idFromCoordinates. + * + * @return long + */ + public String getId(){ + return World.idFromCoordinates(x,y); } public int getX() { @@ -124,6 +147,9 @@ public class World implements MongoSerialisable { objects.add(obj.mongoSerialise()); } + + dbObject.put("_id", getId()); + dbObject.put("objects", objects); dbObject.put("terrain", tileMap.mongoSerialise()); @@ -131,7 +157,7 @@ public class World implements MongoSerialisable { dbObject.put("y", y); dbObject.put("updatable", updatable); - + dbObject.put("shouldUpdate",shouldUpdate()); return dbObject; } @@ -330,4 +356,73 @@ public class World implements MongoSerialisable { public boolean shouldUpdate() { return updatable > 0; } + + + private GameUniverse universe = null; + + public void setUniverse(GameUniverse universe){ + this.universe = universe; + } + + public ArrayList getNeighbouringLoadedWorlds(){ + ArrayList neighbouringWorlds = new ArrayList<>(); + + if (universe == null){ + return neighbouringWorlds; + } + + for (int dx=-1; dx<=+1; dx+=2){ + World nw = universe.getLoadedWorld(x+dx,y); + if (nw != null){ + neighbouringWorlds.add(nw); + } + } + for (int dy=-1; dy<=+1; dy+=2){ + World nw = universe.getLoadedWorld(x,y+dy); + if (nw != null){ + neighbouringWorlds.add(nw); + } + } + + return neighbouringWorlds; + } + + public ArrayList getNeighbouringExistingWorlds(){ + ArrayList neighbouringWorlds = new ArrayList<>(); + + if (universe == null){ + return neighbouringWorlds; + } + + for (int dx=-1; dx<=+1; dx+=2){ + World nw = universe.getWorld(x+dx,y,false); + if (nw != null){ + neighbouringWorlds.add(nw); + } + } + for (int dy=-1; dy<=+1; dy+=2){ + World nw = universe.getWorld(x,y+dy,false); + if (nw != null){ + neighbouringWorlds.add(nw); + } + } + + return neighbouringWorlds; + } + + + public boolean canUnload(){ + return updatable==0; + } + + public boolean shouldUnload(){ + boolean res = canUnload(); + + for (World nw : getNeighbouringLoadedWorlds() ){ + res &= nw.canUnload(); + } + + return res; + } + } diff --git a/Server/src/main/java/net/simon987/server/user/User.java b/Server/src/main/java/net/simon987/server/user/User.java index 55875ce..0da9acc 100755 --- a/Server/src/main/java/net/simon987/server/user/User.java +++ b/Server/src/main/java/net/simon987/server/user/User.java @@ -44,6 +44,7 @@ public class User implements MongoSerialisable { BasicDBObject dbObject = new BasicDBObject(); + dbObject.put("_id", username); // a constant id ensures only one entry per user is kept and updated, instead of a new entry created every save for every user. dbObject.put("username", username); dbObject.put("code", userCode); dbObject.put("controlledUnit", controlledUnit.getObjectId()); From 6fc583d6f034e16e2d70448a0ba215610ea38b73 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 8 Jan 2018 19:12:39 -0500 Subject: [PATCH 14/20] Registers are cleared on code upload --- .../java/net/simon987/server/webserver/CodeUploadHandler.java | 2 ++ 1 file changed, 2 insertions(+) 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 8400a93..2a9d162 100644 --- a/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java @@ -40,6 +40,8 @@ public class CodeUploadHandler implements MessageHandler { user.getUser().getControlledUnit().getKeyboardBuffer().clear(); } + //Clear registers + user.getUser().getCpu().getRegisterSet().clear(); JSONObject response = new JSONObject(); response.put("t", "codeResponse"); From 7cbfb822b8727d8b08e6740a39f444e5c03232bf Mon Sep 17 00:00:00 2001 From: Jaggernaut555 Date: Tue, 9 Jan 2018 14:00:36 -0800 Subject: [PATCH 15/20] Updated LogManager --- .../simon987/server/logging/LogManager.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) 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 1a2262a..47b11e3 100755 --- a/Server/src/main/java/net/simon987/server/logging/LogManager.java +++ b/Server/src/main/java/net/simon987/server/logging/LogManager.java @@ -19,9 +19,30 @@ public class LogManager { public static void initialize() { LOGGER.setUseParentHandlers(false); - Handler handler = new ConsoleHandler(); + /* + * Having warning/error directed to stderr + */ + Handler errHandler = new ConsoleHandler(); + errHandler.setFormatter(new GenericFormatter()); + errHandler.setLevel(Level.WARNING); + + /* + * Only have info and below directed to stdout + */ + Handler handler = new StreamHandler(System.out, new GenericFormatter()) { + @Override + public synchronized void publish(LogRecord record) { + super.publish(record); + flush(); + } + }; + handler.setFilter(new Filter() { + @Override + public boolean isLoggable(LogRecord record) { + return record.getLevel().intValue() <= Level.INFO.intValue(); + } + }); handler.setLevel(Level.ALL); - handler.setFormatter(new GenericFormatter()); try { Handler fileHandler = new FileHandler("mar.log"); @@ -29,6 +50,7 @@ public class LogManager { fileHandler.setFormatter(new GenericFormatter()); LOGGER.addHandler(handler); + LOGGER.addHandler(errHandler); LOGGER.addHandler(fileHandler); LOGGER.setLevel(Level.ALL); @@ -36,6 +58,5 @@ public class LogManager { e.printStackTrace(); } - } } From 2fbc55d0ddef73241de26fa1b31141904e85121e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 9 Jan 2018 20:09:46 -0500 Subject: [PATCH 16/20] Fixed potential NullPointerException on server loading --- .../src/main/java/net/simon987/npcplugin/HarvesterNPC.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/HarvesterNPC.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/HarvesterNPC.java index 396a8e1..e40d0b6 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/HarvesterNPC.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/HarvesterNPC.java @@ -48,7 +48,9 @@ public class HarvesterNPC extends NonPlayerCharacter { @Override public void onDeadCallback() { - getFactory().getNpcs().remove(this); + if (getFactory() != null && getFactory().getNpcs() != null) { + getFactory().getNpcs().remove(this); + } GameServer.INSTANCE.getEventDispatcher().dispatch( new ObjectDeathEvent(this, ID)); From 54b72e89b35d7cbd48e07c0f45cce103057b2841 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 9 Jan 2018 22:10:55 -0500 Subject: [PATCH 17/20] Fixes #121 + Saner thread safety --- .../event/UserCreationListener.java | 2 +- .../java/net/simon987/npcplugin/Factory.java | 2 +- .../net/simon987/npcplugin/HarvestTask.java | 11 +- .../event/WorldCreationListener.java | 4 +- .../event/WorldCreationListener.java | 4 +- .../event/WorldUpdateListener.java | 16 +- .../java/net/simon987/server/GameServer.java | 46 ++--- .../net/simon987/server/game/GameObject.java | 16 +- .../simon987/server/game/GameUniverse.java | 58 ++++--- .../java/net/simon987/server/game/World.java | 89 ++++++---- .../net/simon987/server/io/FileUtils.java | 162 ------------------ .../webserver/ObjectsRequestHandler.java | 5 +- .../webserver/TerrainRequestHandler.java | 2 +- 13 files changed, 128 insertions(+), 289 deletions(-) diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/UserCreationListener.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/UserCreationListener.java index e3800fa..7934d36 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/UserCreationListener.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/event/UserCreationListener.java @@ -37,7 +37,7 @@ public class UserCreationListener implements GameEventListener { cubot.setX(point.x); cubot.setY(point.y); - cubot.getWorld().getGameObjects().add(cubot); + cubot.getWorld().addObject(cubot); cubot.getWorld().incUpdatable(); cubot.setHeldItem(GameServer.INSTANCE.getConfig().getInt("new_user_item")); 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 91f4310..ded3ded 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java @@ -74,7 +74,7 @@ public class Factory extends GameObject implements Updatable { npc.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId()); npc.setX(p.x); npc.setY(p.y); - getWorld().getGameObjects().add(npc); + getWorld().addObject(npc); getWorld().incUpdatable(); npc.setFactory(this); diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/HarvestTask.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/HarvestTask.java index 5c12479..520a4a1 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/HarvestTask.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/HarvestTask.java @@ -33,14 +33,9 @@ public class HarvestTask extends NPCTask { if (pause == 0) { //Get biomass - ArrayList biomass = new ArrayList<>(10); - - for (GameObject object : npc.getWorld().getGameObjects()) { - //Plant MAP_INFO - if ((object.getMapInfo() & 0x4000) == 0x4000) { - biomass.add(object); - } - } + /* todo replace by some sort of .collect call with object + id (See https://github.com/simon987/Much-Assembly-Required/pull/66)*/ + ArrayList biomass = npc.getWorld().findObjects(0x4000); //Get closest one int minDist = Integer.MAX_VALUE; 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 608a40d..05299c6 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 @@ -53,7 +53,7 @@ public class WorldCreationListener implements GameEventListener { continue; } - world.getGameObjects().add(factory); + world.addObject(factory); world.incUpdatable(); LogManager.LOGGER.info("Spawned Factory at (" + world.getX() + ", " + world.getY() + @@ -84,7 +84,7 @@ public class WorldCreationListener implements GameEventListener { if (radioTower.getAdjacentTile() != null) { //Radio Tower has adjacent tiles - world.getGameObjects().add(radioTower); + world.addObject(radioTower); world.incUpdatable(); //In case the Factory couldn't be spawned. NpcPlugin.getRadioTowers().add(radioTower); diff --git a/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/WorldCreationListener.java b/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/WorldCreationListener.java index 0668afe..e48b43f 100644 --- a/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/WorldCreationListener.java +++ b/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/WorldCreationListener.java @@ -25,7 +25,9 @@ public class WorldCreationListener implements GameEventListener { ArrayList biomassBlobs = WorldUtils.generateBlobs(((WorldGenerationEvent) event).getWorld(), minCount, maxCount, yield); - ((WorldGenerationEvent) event).getWorld().getGameObjects().addAll(biomassBlobs); + for (BiomassBlob blob : biomassBlobs) { + ((WorldGenerationEvent) event).getWorld().addObject(blob); + } } } diff --git a/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/WorldUpdateListener.java b/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/WorldUpdateListener.java index 20e4461..afd9d9b 100644 --- a/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/WorldUpdateListener.java +++ b/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/WorldUpdateListener.java @@ -17,11 +17,11 @@ public class WorldUpdateListener implements GameEventListener { private HashMap worldWaitMap = new HashMap<>(200); - private int minBlobCount; - private int maxBlobCount; - private int blobYield; - private int waitTime; - private int blobThreshold; + private static int minBlobCount; + private static int maxBlobCount; + private static int blobYield; + private static int waitTime; + private static int blobThreshold; public WorldUpdateListener(ServerConfiguration config) { @@ -45,7 +45,7 @@ public class WorldUpdateListener implements GameEventListener { World world = ((WorldUpdateEvent) event).getWorld(); //If there is less than the respawn threshold, - if (world.getGameObjects(BiomassBlob.class).size() < blobThreshold) { + if (world.findObjects(BiomassBlob.class).size() < blobThreshold) { //Set a timer for respawn_time ticks if (!worldWaitMap.containsKey(world) || worldWaitMap.get(world) == 0L) { @@ -59,7 +59,9 @@ public class WorldUpdateListener implements GameEventListener { //If the timer was set less than respawn_time ticks ago, respawn the blobs ArrayList newBlobs = WorldUtils.generateBlobs(world, minBlobCount, maxBlobCount, blobYield); - world.getGameObjects().addAll(newBlobs); + for (BiomassBlob blob : newBlobs) { + world.addObject(blob); + } //Set the 'waitUntil' time to 0 to indicate that we are not waiting worldWaitMap.replace(world, 0L); diff --git a/Server/src/main/java/net/simon987/server/GameServer.java b/Server/src/main/java/net/simon987/server/GameServer.java index bd62673..65a9633 100644 --- a/Server/src/main/java/net/simon987/server/GameServer.java +++ b/Server/src/main/java/net/simon987/server/GameServer.java @@ -9,7 +9,6 @@ import net.simon987.server.event.TickEvent; import net.simon987.server.game.DayNightCycle; import net.simon987.server.game.GameUniverse; import net.simon987.server.game.World; -import net.simon987.server.io.FileUtils; import net.simon987.server.logging.LogManager; import net.simon987.server.plugin.PluginManager; import net.simon987.server.user.User; @@ -17,8 +16,6 @@ import net.simon987.server.webserver.SocketServer; import java.io.File; import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.List; public class GameServer implements Runnable { @@ -131,8 +128,7 @@ public class GameServer implements Runnable { //Process user code - ArrayList users_ = new ArrayList<>(gameUniverse.getUsers()); - for (User user : users_) { + for (User user : gameUniverse.getUsers()) { if (user.getCpu() != null) { try { @@ -152,10 +148,8 @@ public class GameServer implements Runnable { } //Process each worlds - //Avoid concurrent modification - ArrayList worlds = new ArrayList<>(gameUniverse.getWorlds()); int updatedWorlds = 0; - for (World world : worlds) { + for (World world : gameUniverse.getWorlds()) { if (world.shouldUpdate()) { world.update(); updatedWorlds++; @@ -167,14 +161,9 @@ public class GameServer implements Runnable { save(); } - // Clean up history files - if (gameUniverse.getTime() % config.getInt("clean_interval") == 0) { - FileUtils.cleanHistory(config.getInt("history_size")); - } - socketServer.tick(); - LogManager.LOGGER.info("Processed " + gameUniverse.getWorlds().size() + " worlds (" + updatedWorlds + + LogManager.LOGGER.info("Processed " + gameUniverse.getWorldCount() + " worlds (" + updatedWorlds + ") updated"); } @@ -203,7 +192,7 @@ public class GameServer implements Runnable { cursor = users.find(); while (cursor.hasNext()) { try { - universe.getUsers().add(User.deserialize(cursor.next())); + universe.addUser(User.deserialize(cursor.next())); } catch (CancelledException e) { e.printStackTrace(); } @@ -217,13 +206,13 @@ public class GameServer implements Runnable { gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId")); } - LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorlds().size() + - " | U:" + GameServer.INSTANCE.getGameUniverse().getUsers().size()); + LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorldCount() + + " | U:" + GameServer.INSTANCE.getGameUniverse().getUserCount()); } private void save() { - LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorlds().size() + " | U:" + gameUniverse.getUsers().size()); + LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorldCount() + " | U:" + gameUniverse.getUserCount()); try{ DB db = mongo.getDB("mar"); @@ -233,31 +222,22 @@ public class GameServer implements Runnable { DBCollection users = db.getCollection("user"); DBCollection server = db.getCollection("server"); - List worldDocuments = new ArrayList<>(); - int perBatch = 35; int insertedWorlds = 0; GameUniverse universe = GameServer.INSTANCE.getGameUniverse(); - ArrayList worlds_ = new ArrayList<>(universe.getWorlds()); - for (World w : worlds_) { - LogManager.LOGGER.fine("Saving world "+w.getId()+" to mongodb"); - insertedWorlds++; + for (World w : universe.getWorlds()) { +// LogManager.LOGGER.fine("Saving world "+w.getId()+" to mongodb"); + insertedWorlds++; worlds.save(w.mongoSerialise()); // If the world should unload, it is removed from the Universe after having been saved. if (w.shouldUnload()){ unloaded_worlds++; - LogManager.LOGGER.fine("Unloading world "+w.getId()+" from universe"); - universe.removeWorld(w); +// LogManager.LOGGER.fine("Unloading world "+w.getId()+" from universe"); + universe.removeWorld(w); } } - List userDocuments = new ArrayList<>(); - int insertedUsers = 0; - ArrayList users_ = new ArrayList<>(GameServer.INSTANCE.getGameUniverse().getUsers()); - for (User u : users_) { - - insertedUsers++; - + for (User u : GameServer.INSTANCE.getGameUniverse().getUsers()) { if (!u.isGuest()) { users.save(u.mongoSerialise()); 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 d7d958e..a176129 100755 --- a/Server/src/main/java/net/simon987/server/game/GameObject.java +++ b/Server/src/main/java/net/simon987/server/game/GameObject.java @@ -84,9 +84,9 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable } if (leftWorld != null) { - world.getGameObjects().remove(this); + world.removeObject(this); world.decUpdatable(); - leftWorld.getGameObjects().add(this); + leftWorld.addObject(this); leftWorld.incUpdatable(); setWorld(leftWorld); @@ -103,9 +103,9 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable } if (rightWorld != null) { - world.getGameObjects().remove(this); + world.removeObject(this); world.decUpdatable(); - rightWorld.getGameObjects().add(this); + rightWorld.addObject(this); rightWorld.incUpdatable(); setWorld(rightWorld); @@ -123,9 +123,9 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable } if (upWorld != null) { - world.getGameObjects().remove(this); + world.removeObject(this); world.decUpdatable(); - upWorld.getGameObjects().add(this); + upWorld.addObject(this); upWorld.incUpdatable(); setWorld(upWorld); @@ -143,9 +143,9 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable if (downWorld != null) { - world.getGameObjects().remove(this); + world.removeObject(this); world.decUpdatable(); - downWorld.getGameObjects().add(this); + downWorld.addObject(this); downWorld.incUpdatable(); setWorld(downWorld); diff --git a/Server/src/main/java/net/simon987/server/game/GameUniverse.java b/Server/src/main/java/net/simon987/server/game/GameUniverse.java index 1440a8e..b9556c5 100644 --- a/Server/src/main/java/net/simon987/server/game/GameUniverse.java +++ b/Server/src/main/java/net/simon987/server/game/GameUniverse.java @@ -10,16 +10,15 @@ import net.simon987.server.assembly.exception.CancelledException; import net.simon987.server.logging.LogManager; import net.simon987.server.user.User; -import java.net.UnknownHostException; - -import java.util.ArrayList; -import java.util.Hashtable; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; public class GameUniverse { //private ArrayList worlds; - private Hashtable worlds; - private ArrayList users; + private ConcurrentHashMap worlds; + //username:user + private ConcurrentHashMap users; private WorldGenerator worldGenerator; private MongoClient mongo = null; @@ -33,9 +32,8 @@ public class GameUniverse { public GameUniverse(ServerConfiguration config) { - //worlds = new ArrayList<>(32); - worlds = new Hashtable(32); - users = new ArrayList<>(16); + worlds = new ConcurrentHashMap<>(256); + users = new ConcurrentHashMap<>(16); worldGenerator = new WorldGenerator(config); } @@ -160,7 +158,7 @@ public class GameUniverse { } } - public World createWorld(int x, int y) { + private World createWorld(int x, int y) { World world = null; try { world = worldGenerator.generateWorld(x, y); @@ -171,12 +169,7 @@ public class GameUniverse { } public User getUser(String username) { - for (User user : users) { - if (user.getUsername().equals(username)) { - return user; - } - } - return null; + return users.get(username); } public User getOrCreateUser(String username, boolean makeControlledUnit) { @@ -213,7 +206,7 @@ public class GameUniverse { user.setUsername(username); - users.add(user); + addUser(user); return user; @@ -235,12 +228,11 @@ public class GameUniverse { */ public GameObject getObject(long id) { - // for (World world : getWorlds()) { - for (GameObject object : world.getGameObjects()) { - if (object.getObjectId() == id) { - return object; - } + GameObject obj = world.findObject(id); + + if (obj != null) { + return obj; } } @@ -253,12 +245,20 @@ public class GameUniverse { time++; } - public ArrayList getWorlds() { - return new ArrayList(worlds.values()); + public Collection getWorlds() { + return worlds.values(); } - public ArrayList getUsers() { - return users; + public int getWorldCount() { + return worlds.size(); + } + + public Collection getUsers() { + return users.values(); + } + + public int getUserCount() { + return users.size(); } public long getNextObjectId() { @@ -281,8 +281,12 @@ public class GameUniverse { } + public void addUser(User user) { + users.put(user.getUsername(), user); + } + public void removeUser(User user) { - users.remove(user); + users.remove(user.getUsername()); } public int getMaxWidth() { 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 6545e6b..affb724 100644 --- a/Server/src/main/java/net/simon987/server/game/World.java +++ b/Server/src/main/java/net/simon987/server/game/World.java @@ -3,18 +3,19 @@ package net.simon987.server.game; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; +import com.sun.istack.internal.Nullable; import net.simon987.server.GameServer; import net.simon987.server.event.GameEvent; import net.simon987.server.event.WorldUpdateEvent; -import net.simon987.server.game.GameUniverse; import net.simon987.server.game.pathfinding.Pathfinder; import net.simon987.server.io.MongoSerialisable; import org.json.simple.JSONObject; -import net.simon987.server.logging.LogManager; import java.awt.*; import java.util.ArrayList; +import java.util.Collection; import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; public class World implements MongoSerialisable { @@ -32,7 +33,7 @@ public class World implements MongoSerialisable { private TileMap tileMap; - private ArrayList gameObjects = new ArrayList<>(16); + private ConcurrentHashMap gameObjects = new ConcurrentHashMap<>(8); /** * If this number is greater than 0, the World will be updated. @@ -91,26 +92,49 @@ public class World implements MongoSerialisable { return y; } - /** - * Get all the game objects that are instances of the specified class - */ - public ArrayList getGameObjects(Class clazz) { + public ArrayList findObjects(Class clazz) { - ArrayList objects = new ArrayList<>(gameObjects.size()); + ArrayList matchingObjects = new ArrayList<>(2); - for (GameObject object : gameObjects) { - if (object.getClass().equals(clazz)) { - objects.add(object); + for (GameObject obj : gameObjects.values()) { + + if (obj.getClass().equals(clazz)) { + matchingObjects.add(obj); } } - return objects; + return matchingObjects; } - public ArrayList getGameObjects() { - return gameObjects; + + public ArrayList findObjects(int mapInfo) { + + ArrayList matchingObjects = new ArrayList<>(2); + + for (GameObject obj : gameObjects.values()) { + if ((obj.getMapInfo() & mapInfo) == mapInfo) { + matchingObjects.add(obj); + } + } + + return matchingObjects; } + public void addObject(GameObject object) { + gameObjects.put(object.getObjectId(), object); + } + + public void removeObject(GameObject object) { + gameObjects.remove(object.getObjectId()); + } + + @Nullable + public GameObject findObject(long objectId) { + return gameObjects.get(objectId); + } + + + /** * Update this World and its GameObjects *
@@ -122,13 +146,11 @@ public class World implements MongoSerialisable { GameEvent event = new WorldUpdateEvent(this); GameServer.INSTANCE.getEventDispatcher().dispatch(event); //Ignore cancellation - ArrayList gameObjects_ = new ArrayList<>(gameObjects); - - for (GameObject object : gameObjects_) { + for (GameObject object : gameObjects.values()) { //Clean up dead objects if (object.isDead()) { object.onDeadCallback(); - gameObjects.remove(object); + removeObject(object); //LogManager.LOGGER.fine("Removed object " + object + " id: " + object.getObjectId()); } else if (object instanceof Updatable) { ((Updatable) object).update(); @@ -142,8 +164,7 @@ public class World implements MongoSerialisable { BasicDBObject dbObject = new BasicDBObject(); BasicDBList objects = new BasicDBList(); - ArrayList gameObjects_ = new ArrayList<>(gameObjects); - for (GameObject obj : gameObjects_) { + for (GameObject obj : gameObjects.values()) { objects.add(obj.mongoSerialise()); } @@ -215,7 +236,7 @@ public class World implements MongoSerialisable { GameObject object = GameObject.deserialize((DBObject) obj); object.setWorld(world); - world.gameObjects.add(object); + world.addObject(object); } return world; @@ -254,7 +275,7 @@ public class World implements MongoSerialisable { } //Objects - for (GameObject obj : this.gameObjects) { + for (GameObject obj : gameObjects.values()) { mapInfo[obj.getX()][obj.getY()] |= obj.getMapInfo(); } @@ -308,17 +329,16 @@ public class World implements MongoSerialisable { */ public ArrayList getGameObjectsBlockingAt(int x, int y) { - ArrayList gameObjects = new ArrayList<>(2); - - for (GameObject obj : this.gameObjects) { + ArrayList objectsLooking = new ArrayList<>(2); + for (GameObject obj : gameObjects.values()) { if (obj.isAt(x, y)) { - gameObjects.add(obj); + objectsLooking.add(obj); } } - return gameObjects; + return objectsLooking; } /** @@ -332,17 +352,15 @@ public class World implements MongoSerialisable { * @return the list of game objects at a location */ public ArrayList getGameObjectsAt(int x, int y) { - ArrayList gameObjects = new ArrayList<>(2); + ArrayList objectsAt = new ArrayList<>(2); + for (GameObject obj : gameObjects.values()) { - for (GameObject obj : this.gameObjects) { - - if (obj.getX() == x && obj.getY() == y) { - gameObjects.add(obj); + if (obj.isAt(x, y)) { + objectsAt.add(obj); } } - - return gameObjects; + return objectsAt; } public void incUpdatable() { @@ -425,4 +443,7 @@ public class World implements MongoSerialisable { return res; } + public Collection getGameObjects() { + return gameObjects.values(); + } } 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 28c5a59..820dba1 100644 --- a/Server/src/main/java/net/simon987/server/io/FileUtils.java +++ b/Server/src/main/java/net/simon987/server/io/FileUtils.java @@ -1,35 +1,12 @@ package net.simon987.server.io; -import net.simon987.server.logging.LogManager; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.zip.ZipEntry; -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 @@ -42,143 +19,4 @@ public class FileUtils { 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 - * - * @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; - - try { - bytes = Files.readAllBytes(path); - - } catch (IOException e) { - System.out.println("Failed to extract bytes from: " + path); - e.printStackTrace(); - } - - return bytes; - } - - /** - * 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 { - - 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(); - } - - stream.close(); - output.close(); - } - - 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/ObjectsRequestHandler.java b/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java index 6f8a634..f8edbb1 100644 --- a/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java @@ -7,8 +7,6 @@ import net.simon987.server.logging.LogManager; import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import java.util.ArrayList; - public class ObjectsRequestHandler implements MessageHandler { @@ -29,13 +27,12 @@ public class ObjectsRequestHandler implements MessageHandler { World world = GameServer.INSTANCE.getGameUniverse().getWorld(x, y, false); if (world != null) { - ArrayList gameObjects = world.getGameObjects(); JSONObject response = new JSONObject(); JSONArray objects = new JSONArray(); - for (GameObject object : gameObjects) { + for (GameObject object : world.getGameObjects()) { objects.add(object.serialise()); } 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 702ed20..e566e96 100644 --- a/Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java @@ -17,7 +17,7 @@ public class TerrainRequestHandler implements MessageHandler { try { world = GameServer.INSTANCE.getGameUniverse().getWorld( Long.valueOf((long) json.get("x")).intValue(), - Long.valueOf((long) json.get("y")).intValue(), false); + Long.valueOf((long) json.get("y")).intValue(), true); } catch (NullPointerException e) { LogManager.LOGGER.severe("FIXME: handle TerrainRequestHandler"); return; From c610929809533111bb77cb57dfddb3ef5621e8b9 Mon Sep 17 00:00:00 2001 From: Luc Lagarde Date: Thu, 11 Jan 2018 21:00:26 -0600 Subject: [PATCH 18/20] Fix maven build error Removes a reference to com.sun.istack.internal.Nullable and an associated annotation, which causes the maven build to fail. --- Server/src/main/java/net/simon987/server/game/World.java | 2 -- 1 file changed, 2 deletions(-) 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 affb724..be7ea1f 100644 --- a/Server/src/main/java/net/simon987/server/game/World.java +++ b/Server/src/main/java/net/simon987/server/game/World.java @@ -3,7 +3,6 @@ package net.simon987.server.game; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; -import com.sun.istack.internal.Nullable; import net.simon987.server.GameServer; import net.simon987.server.event.GameEvent; import net.simon987.server.event.WorldUpdateEvent; @@ -128,7 +127,6 @@ public class World implements MongoSerialisable { gameObjects.remove(object.getObjectId()); } - @Nullable public GameObject findObject(long objectId) { return gameObjects.get(objectId); } From 6b91251b4e67e6b0de0670a834f5623e741327a4 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 14 Jan 2018 11:01:13 -0500 Subject: [PATCH 19/20] Should fix #125 --- .../event/ObjectDeathListener.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/ObjectDeathListener.java b/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/ObjectDeathListener.java index 036352e..6ace72f 100644 --- a/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/ObjectDeathListener.java +++ b/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/ObjectDeathListener.java @@ -29,18 +29,23 @@ public class ObjectDeathListener implements GameEventListener { @Override public void handle(GameEvent event) { - // a HarvesterNPC ObjectDeathEvent is received // TODO: setup enum with all GameObject type IDs if (((ObjectDeathEvent) event).getSourceObjectId() == 10) { + //An HarvesterNPC ObjectDeathEvent is received GameObject dyingHarvesterNPC = (GameObject)event.getSource(); - // create a new biomass - BiomassBlob newBiomassBlob = createBiomassBlobAt( - dyingHarvesterNPC.getX(), dyingHarvesterNPC.getY(), dyingHarvesterNPC.getWorld()); - // add it to the world game objects - dyingHarvesterNPC.getWorld().getGameObjects().add(newBiomassBlob); - LogManager.LOGGER.fine("Spawned biomass at (" + newBiomassBlob.getX() + - ", " + newBiomassBlob.getY() + ")"); + + //Don't spawn biomass on World border + if (dyingHarvesterNPC.getX() != 0 && dyingHarvesterNPC.getX() != World.WORLD_SIZE - 1 && + dyingHarvesterNPC.getY() != 0 && dyingHarvesterNPC.getY() != World.WORLD_SIZE - 1) { + //Create a new biomass + BiomassBlob newBiomassBlob = createBiomassBlobAt( + dyingHarvesterNPC.getX(), dyingHarvesterNPC.getY(), dyingHarvesterNPC.getWorld()); + //Add it to the world game objects + dyingHarvesterNPC.getWorld().addObject(newBiomassBlob); + LogManager.LOGGER.fine("Spawned biomass at (" + newBiomassBlob.getX() + + ", " + newBiomassBlob.getY() + ")"); + } } } From 210e579995ce820e59f2c9812ed9bb23365962df Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Jan 2018 19:02:36 -0500 Subject: [PATCH 20/20] Number of assembly errors is also sent on code upload --- .../main/java/net/simon987/server/assembly/AssemblyResult.java | 2 +- .../java/net/simon987/server/webserver/CodeUploadHandler.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/java/net/simon987/server/assembly/AssemblyResult.java b/Server/src/main/java/net/simon987/server/assembly/AssemblyResult.java index 069f800..3e1bff7 100755 --- a/Server/src/main/java/net/simon987/server/assembly/AssemblyResult.java +++ b/Server/src/main/java/net/simon987/server/assembly/AssemblyResult.java @@ -27,7 +27,7 @@ public class AssemblyResult { * List of exceptions encountered during the assembly attempt, * they will be displayed in the editor */ - ArrayList exceptions = new ArrayList<>(50); + public ArrayList exceptions = new ArrayList<>(50); /** * Offset of the code segment */ 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 2a9d162..f552ca0 100644 --- a/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java +++ b/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java @@ -46,6 +46,7 @@ public class CodeUploadHandler implements MessageHandler { JSONObject response = new JSONObject(); response.put("t", "codeResponse"); response.put("bytes", ar.bytes.length); + response.put("exceptions", ar.exceptions.size()); user.getWebSocket().send(response.toJSONString()); }