diff --git a/Plugin Cubot/src/net/simon987/cubotplugin/Cubot.java b/Plugin Cubot/src/net/simon987/cubotplugin/Cubot.java index f2f56c0..b10680a 100644 --- a/Plugin Cubot/src/net/simon987/cubotplugin/Cubot.java +++ b/Plugin Cubot/src/net/simon987/cubotplugin/Cubot.java @@ -1,6 +1,7 @@ package net.simon987.cubotplugin; import net.simon987.server.game.*; +import net.simon987.server.user.User; import org.json.simple.JSONObject; import java.util.ArrayList; @@ -23,6 +24,8 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { private ArrayList keyboardBuffer = new ArrayList<>(); + private User parent; + public Cubot() { } @@ -67,6 +70,9 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { json.put("heldItem", heldItem); json.put("hp", hp); json.put("action", lastAction.ordinal()); + if(parent != null){ + json.put("parent", parent.getUsername()); //Only used client-side for now + } return json; } @@ -80,6 +86,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { cubot.hp = (int)(long)json.get("hp"); cubot.setDirection(Direction.getDirection((int)(long)json.get("direction"))); cubot.heldItem = (int)(long)json.get("heldItem"); + cubot.heldItem = (int)(long)json.get("heldItem"); return cubot; @@ -110,4 +117,12 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit { public void setCurrentAction(CubotAction currentAction) { this.currentAction = currentAction; } + + public User getParent() { + return parent; + } + + public void setParent(User parent) { + this.parent = parent; + } } diff --git a/Plugin Cubot/src/net/simon987/cubotplugin/event/UserCreationListener.java b/Plugin Cubot/src/net/simon987/cubotplugin/event/UserCreationListener.java index 4648a9e..4a5f5a7 100644 --- a/Plugin Cubot/src/net/simon987/cubotplugin/event/UserCreationListener.java +++ b/Plugin Cubot/src/net/simon987/cubotplugin/event/UserCreationListener.java @@ -7,6 +7,8 @@ import net.simon987.server.event.GameEventListener; import net.simon987.server.event.UserCreationEvent; import net.simon987.server.user.User; +import java.awt.*; + public class UserCreationListener implements GameEventListener { @Override public Class getListenedEventType() { @@ -20,12 +22,18 @@ public class UserCreationListener implements GameEventListener { Cubot cubot = new Cubot(); + cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(0,0)); + cubot.getWorld().getGameObjects().add(cubot); cubot.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId()); - cubot.setX(6); - cubot.setY(6); + cubot.setParent(user); + + Point point = cubot.getWorld().getRandomPassableTile(); + + cubot.setX(point.x); + cubot.setY(point.y); user.setControlledUnit(cubot); diff --git a/Plugin Plant/src/net/simon987/plantplugin/event/WorldCreationListener.java b/Plugin Plant/src/net/simon987/plantplugin/event/WorldCreationListener.java index 1b07270..f43f49b 100644 --- a/Plugin Plant/src/net/simon987/plantplugin/event/WorldCreationListener.java +++ b/Plugin Plant/src/net/simon987/plantplugin/event/WorldCreationListener.java @@ -61,7 +61,7 @@ public class WorldCreationListener implements GameEventListener { outerLoop: for (int i = 0; i < treeCount; i++) { - Point p = WorldGenerator.getRandomPlainTile(world.getTileMap().getTiles()); + Point p = world.getTileMap().getRandomPlainTile(); if (p != null) { diff --git a/Server/src/net/simon987/server/Main.java b/Server/src/net/simon987/server/Main.java index 1611649..0746370 100644 --- a/Server/src/net/simon987/server/Main.java +++ b/Server/src/net/simon987/server/Main.java @@ -10,9 +10,6 @@ import java.net.InetSocketAddress; public class Main { public static void main(String[] args){ - //todo: User registration - //todo: Display usernames under cubot - LogManager.initialize(); ServerConfiguration config = new ServerConfiguration(new File("config.properties")); diff --git a/Server/src/net/simon987/server/assembly/instruction/MulInstruction.java b/Server/src/net/simon987/server/assembly/instruction/MulInstruction.java index c3c8fa1..81d43d1 100644 --- a/Server/src/net/simon987/server/assembly/instruction/MulInstruction.java +++ b/Server/src/net/simon987/server/assembly/instruction/MulInstruction.java @@ -18,7 +18,7 @@ public class MulInstruction extends Instruction { @Override public Status execute(Target src, int srcIndex, Status status) { - int result = (char)cpu.getRegisterSet().getRegister("A").getValue() * (char)src.get(srcIndex); + int result = cpu.getRegisterSet().getRegister("A").getValue() * (char)src.get(srcIndex); int hWord = Util.getHigherWord(result); if (hWord != 0) { diff --git a/Server/src/net/simon987/server/game/ControllableUnit.java b/Server/src/net/simon987/server/game/ControllableUnit.java index 57c8bff..a08f7c6 100644 --- a/Server/src/net/simon987/server/game/ControllableUnit.java +++ b/Server/src/net/simon987/server/game/ControllableUnit.java @@ -1,5 +1,7 @@ package net.simon987.server.game; +import net.simon987.server.user.User; + import java.util.ArrayList; public interface ControllableUnit { @@ -8,6 +10,8 @@ public interface ControllableUnit { void setKeyboardBuffer(ArrayList kbBuffer); + void setParent(User user); + ArrayList getKeyboardBuffer(); } diff --git a/Server/src/net/simon987/server/game/GameUniverse.java b/Server/src/net/simon987/server/game/GameUniverse.java index 516ed45..181767f 100644 --- a/Server/src/net/simon987/server/game/GameUniverse.java +++ b/Server/src/net/simon987/server/game/GameUniverse.java @@ -1,6 +1,10 @@ package net.simon987.server.game; +import net.simon987.server.GameServer; import net.simon987.server.ServerConfiguration; +import net.simon987.server.assembly.Assembler; +import net.simon987.server.assembly.AssemblyResult; +import net.simon987.server.assembly.CPU; import net.simon987.server.assembly.exception.CancelledException; import net.simon987.server.io.JSONSerialisable; import net.simon987.server.logging.LogManager; @@ -82,6 +86,43 @@ public class GameUniverse implements JSONSerialisable{ return null; } + public User getOrCreateUser(String username){ + User user = getUser(username); + + if(user != null) { + return user; + } else { + + LogManager.LOGGER.info("Creating new User: " + username); + + try { + user = new User(); + user.setUsername(username); + user.setCpu(new CPU(GameServer.INSTANCE.getConfig(), user)); + user.setUserCode(GameServer.INSTANCE.getConfig().getString("new_user_code")); + + //Compile user code + AssemblyResult ar = new Assembler(user.getCpu().getInstructionSet(), user.getCpu().getRegisterSet(), + GameServer.INSTANCE.getConfig()).parse(user.getUserCode()); + + user.getCpu().getMemory().clear(); + + //Write assembled code to mem + user.getCpu().getMemory().write((short) ar.origin, ar.bytes, ar.bytes.length); + user.getCpu().setCodeSegmentOffset(ar.origin); + + users.add(user); + + return user; + + } catch (CancelledException e) { + e.printStackTrace(); + return null; + } + + } + } + public GameObject getObject(int id) { for (World world : worlds) { diff --git a/Server/src/net/simon987/server/game/TileMap.java b/Server/src/net/simon987/server/game/TileMap.java index c80b03f..126b0a0 100755 --- a/Server/src/net/simon987/server/game/TileMap.java +++ b/Server/src/net/simon987/server/game/TileMap.java @@ -4,9 +4,11 @@ package net.simon987.server.game; import net.simon987.server.io.JSONSerialisable; import org.json.simple.JSONObject; +import java.awt.*; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Base64; +import java.util.Random; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.Inflater; @@ -157,4 +159,27 @@ public class TileMap implements JSONSerialisable { return null; } + + public Point getRandomPlainTile() { + + Random random = new Random(); + + int counter = 0; + while (true) { + counter++; + + //Prevent infinite loop + if (counter >= 2500) { + return null; + } + + int rx = random.nextInt(World.WORLD_SIZE); + int ry = random.nextInt(World.WORLD_SIZE); + + if (tiles[rx][ry] == TileMap.PLAIN_TILE) { + return new Point(rx, ry); + } + } + + } } diff --git a/Server/src/net/simon987/server/game/World.java b/Server/src/net/simon987/server/game/World.java index 86a5e10..5230ffe 100644 --- a/Server/src/net/simon987/server/game/World.java +++ b/Server/src/net/simon987/server/game/World.java @@ -1,10 +1,13 @@ package net.simon987.server.game; +import net.simon987.server.game.pathfinding.Pathfinder; import net.simon987.server.io.JSONSerialisable; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import java.awt.*; import java.util.ArrayList; +import java.util.Random; public class World implements JSONSerialisable{ @@ -168,6 +171,42 @@ public class World implements JSONSerialisable{ } + /** + * Get a random tile that is empty and passable + * The function ensures that a object spawned there will not be trapped + * and will be able to leave the World + *
+ * Note: This function is quite expensive and shouldn't be used + * by some CpuHardware in its current state + * + * @return random non-blocked tile + */ + public Point getRandomPassableTile(){ + Random random = new Random(); + + int counter = 0; + while (true) { + counter++; + + //Prevent infinite loop + if (counter >= 2500) { + return null; + } + + int rx = random.nextInt(World.WORLD_SIZE); + int ry = random.nextInt(World.WORLD_SIZE); + + if(!isTileBlocked(rx, ry)){ + + Object path = Pathfinder.findPath(this, rx, ry, 1,1,0); + + if(path != null) { + return new Point(rx, ry); + } + } + } + } + /** * Get the list of game objects at a location * diff --git a/Server/src/net/simon987/server/game/WorldGenerator.java b/Server/src/net/simon987/server/game/WorldGenerator.java index bb1ed64..8d2f105 100755 --- a/Server/src/net/simon987/server/game/WorldGenerator.java +++ b/Server/src/net/simon987/server/game/WorldGenerator.java @@ -81,29 +81,6 @@ public class WorldGenerator { } - public static Point getRandomPlainTile(int[][] tiles) { - - Random random = new Random(); - - int counter = 0; - while (true) { - counter++; - - //Prevent infinite loop - if (counter >= 1000) { - return null; - } - - int rx = random.nextInt(World.WORLD_SIZE); - int ry = random.nextInt(World.WORLD_SIZE); - - if (tiles[rx][ry] == TileMap.PLAIN_TILE) { - return new Point(rx, ry); - } - } - - } - /** * Generates an empty World */ @@ -192,7 +169,7 @@ public class WorldGenerator { for (int i = 0; i < ironCount; i++) { - Point p = getRandomPlainTile(world.getTileMap().getTiles()); + Point p = world.getTileMap().getRandomPlainTile(); if (p != null) { world.getTileMap().getTiles()[p.x][p.y] = TileMap.IRON_TILE; @@ -200,7 +177,7 @@ public class WorldGenerator { } for (int i = 0; i < copperCount; i++) { - Point p = getRandomPlainTile(world.getTileMap().getTiles()); + Point p = world.getTileMap().getRandomPlainTile(); if (p != null) { world.getTileMap().getTiles()[p.x][p.y] = TileMap.COPPER_TILE; diff --git a/Server/src/net/simon987/server/user/User.java b/Server/src/net/simon987/server/user/User.java index 8fb8c77..1db9e60 100755 --- a/Server/src/net/simon987/server/user/User.java +++ b/Server/src/net/simon987/server/user/User.java @@ -55,6 +55,8 @@ public class User implements JSONSerialisable{ user.username = (String)userJson.get("username"); user.userCode = (String)userJson.get("code"); + user.getControlledUnit().setParent(user); + user.cpu = CPU.deserialize((JSONObject)userJson.get("cpu"), user); return user; diff --git a/Server/src/net/simon987/server/webserver/SocketServer.java b/Server/src/net/simon987/server/webserver/SocketServer.java index 854af95..0c3c982 100644 --- a/Server/src/net/simon987/server/webserver/SocketServer.java +++ b/Server/src/net/simon987/server/webserver/SocketServer.java @@ -62,20 +62,26 @@ public class SocketServer extends WebSocketServer { } else { LogManager.LOGGER.info("(WS) Received message from unauthenticated user " + conn.getRemoteSocketAddress()); - String username = database.validateAuthToken(message); - User user = GameServer.INSTANCE.getGameUniverse().getUser(username); + //We expect a 128 characters long token + if(message.length() == 128) { - if (user != null) { - LogManager.LOGGER.info("(WS) User was successfully authenticated: " + user.getUsername()); + String username = database.validateAuthToken(message); - onlineUser.setUser(user); - onlineUser.setAuthenticated(true); + if (username != null) { + User user = GameServer.INSTANCE.getGameUniverse().getOrCreateUser(username); - conn.send("{\"t\":\"auth\", \"m\":\"ok\"}"); + LogManager.LOGGER.info("(WS) User was successfully authenticated: " + user.getUsername()); - } else { - LogManager.LOGGER.info("(WS) Unsuccessful authentication attempt " + conn.getRemoteSocketAddress()); - conn.send("{\"t\":\"auth\", \"m\":\"failed\"}"); + onlineUser.setUser(user); + onlineUser.setAuthenticated(true); + + conn.send("{\"t\":\"auth\", \"m\":\"ok\"}"); + + } else { + LogManager.LOGGER.info("(WS) Unsuccessful authentication attempt " + conn.getRemoteSocketAddress()); + conn.send("{\"t\":\"auth\", \"m\":\"failed\"}"); + conn.close(); + } } diff --git a/config.properties b/config.properties index cff4e33..87ff28d 100644 --- a/config.properties +++ b/config.properties @@ -1,13 +1,13 @@ # MySQL username mysql_user=mar -# MySQL password +# MySQL password/ mysql_pass=mar # MySQL address mysql_url=jdbc:mysql://localhost:3306/mar?useSSL=false save_interval=10 # Web server port webSocket_port=8887 -webSocket_host=localhost +webSocket_host=0.0.0.0 # ---------------------------------------------- # Length of a tick in ms @@ -29,13 +29,11 @@ new_user_worldY = 0 # Effect when the new user's controlled unit spawns new_user_effect=WARNING # Default user code -new_user_code=; TODO: Add link to wiki or something here\n\ - .data\n\ - ; Declare data here\n\ +new_user_code=; Welcome to Much Assembly required!\n\ + ; You will find useful information on the game here: https://github.com/simon987/Much-Assembly-Required/wiki\n\ .text\n\ - main:\n\ - ; Write code here\n\ - brk + \t; Write code here\n\ + \tbrk # Default held item new_user_item=0 # ----------------------------------------------