From e4a06e79d43259ccad9182d17c8305820b47bb44 Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 22 Dec 2018 11:26:34 -0500 Subject: [PATCH] Hacked NPC minimum viable --- .../java/net/simon987/cubotplugin/Cubot.java | 54 ++- .../simon987/cubotplugin/CubotBattery.java | 88 ++++- .../simon987/cubotplugin/CubotComPort.java | 31 +- .../net/simon987/cubotplugin/CubotCore.java | 17 +- .../net/simon987/cubotplugin/CubotDrill.java | 17 +- .../cubotplugin/CubotHardwareModule.java | 7 - .../simon987/cubotplugin/CubotHologram.java | 9 +- .../simon987/cubotplugin/CubotInventory.java | 17 +- .../net/simon987/cubotplugin/CubotLaser.java | 29 +- .../net/simon987/cubotplugin/CubotLeg.java | 23 +- .../net/simon987/cubotplugin/CubotLidar.java | 35 +- .../event/UserCreationListener.java | 11 +- .../java/net/simon987/npcplugin/Factory.java | 83 ++++- .../net/simon987/npcplugin/HackedNPC.java | 314 ++++++++++++++++++ .../net/simon987/npcplugin/NpcBattery.java | 109 ++++++ .../net/simon987/npcplugin/NpcInventory.java | 109 ++++++ .../net/simon987/npcplugin/NpcPlugin.java | 12 + .../net/simon987/npcplugin/Settlement.java | 3 +- .../resources/defaultHackedCubotHardware.json | 62 ++++ .../src/main/resources/plugin.properties | 3 +- .../net/simon987/server/assembly/CPU.java | 44 ++- .../server/assembly/HardwareModule.java | 11 +- .../server/game/objects/ControllableUnit.java | 14 +- Server/src/main/resources/config.properties | 1 + Server/src/main/resources/static/js/mar.js | 40 ++- Server/src/main/typescript/GameObject.ts | 48 ++- 26 files changed, 1030 insertions(+), 161 deletions(-) create mode 100644 Plugin NPC/src/main/java/net/simon987/npcplugin/HackedNPC.java create mode 100644 Plugin NPC/src/main/java/net/simon987/npcplugin/NpcBattery.java create mode 100644 Plugin NPC/src/main/java/net/simon987/npcplugin/NpcInventory.java create mode 100644 Plugin NPC/src/main/resources/defaultHackedCubotHardware.json diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java index 1bdf597..f7693d3 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java @@ -91,25 +91,10 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me */ private User parent; - /** - * Energy units in kJ - */ - private int energy; - - /** - * Maximum energy units in kJ - */ - private int maxEnergy; - - /** - * Solar panel multiplier - *
TODO: Set this constant in dimension - */ - private static final float SOLAR_PANEL_MULTIPLIER = 1; /** * Maximum size of the console buffer (also called 'internal buffer') */ - private static final int CONSOLE_BUFFER_MAX_SIZE = 40; + public static final int CONSOLE_BUFFER_MAX_SIZE = 40; /** * List of attached hardware, 'modules' @@ -143,10 +128,8 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me hp = document.getInteger("hp"); shield = document.getInteger("shield"); setDirection(Direction.getDirection(document.getInteger("direction"))); - energy = document.getInteger("energy"); ServerConfiguration config = GameServer.INSTANCE.getConfig(); - maxEnergy = config.getInt("battery_max_energy"); maxHp = config.getInt("cubot_max_hp"); maxShield = config.getInt("cubot_max_shield"); @@ -176,8 +159,6 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me @Override public void update() { - storeEnergy((int) (SOLAR_PANEL_MULTIPLIER * GameServer.INSTANCE.getDayNightCycle().getSunIntensity())); - if (currentAction == Action.WALKING) { if (spendEnergy(100)) { if (!incrementLocation()) { @@ -225,7 +206,6 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me json.put("hp", hp); json.put("shield", shield); json.put("action", lastAction.ordinal()); - json.put("energy", energy); if (parent != null) { json.put("parent", parent.getUsername()); //Only used client-side for now @@ -249,7 +229,6 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me dbObject.put("hp", hp); dbObject.put("shield", shield); dbObject.put("action", lastAction.ordinal()); - dbObject.put("energy", energy); if (parent != null) { dbObject.put("parent", parent.getUsername()); //Only used client-side for now @@ -279,7 +258,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me setDead(false); setHp(maxHp); setShield(0); - setEnergy(maxEnergy); + setEnergy(((CubotBattery) getHardware(CubotBattery.class)).getMaxEnergy()); clearKeyboardBuffer(); consoleMessagesBuffer.clear(); lastConsoleMessagesBuffer.clear(); @@ -354,34 +333,41 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me } public int getEnergy() { - return energy; + CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class); + return battery.getEnergy(); } public void setEnergy(int energy) { - this.energy = energy; + CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class); + battery.setEnergy(energy); } public boolean spendEnergy(int amount) { - if (energy - amount < 0) { + CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class); + + if (battery.getEnergy() - amount < 0) { return false; } else { - energy -= amount; + battery.setEnergy(battery.getEnergy() - amount); return true; } } public void storeEnergy(int amount) { - energy = Math.min(energy + amount, maxEnergy); + CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class); + battery.setEnergy(Math.min(battery.getEnergy() + amount, battery.getMaxEnergy())); } public void setMaxEnergy(int maxEnergy) { - this.maxEnergy = maxEnergy; + CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class); + battery.setMaxEnergy(maxEnergy); } public int getMaxEnergy() { - return maxEnergy; + CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class); + return battery.getMaxEnergy(); } public int getShield() { @@ -422,8 +408,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me @Override public Memory getFloppyData() { - //TODO change DEFAULT_ADDRESS to getHW(class) to allow mutable addresses - CubotFloppyDrive drive = ((CubotFloppyDrive) getHardware(CubotFloppyDrive.DEFAULT_ADDRESS)); + CubotFloppyDrive drive = (CubotFloppyDrive) getHardware(CubotFloppyDrive.class); if (drive.getFloppy() != null) { return drive.getFloppy().getMemory(); @@ -515,6 +500,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me public void setMaxShield(int maxShield) { this.maxShield = maxShield; } + @Override public void heal(int amount) { hp += amount; @@ -538,11 +524,13 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me } } + @Override public void attachHardware(HardwareModule hardware, int address) { hardwareAddresses.put(address, hardware); hardwareModules.put(hardware.getClass(), address); } + @Override public void detachHardware(int address) { hardwareAddresses.remove(address); @@ -555,6 +543,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me hardwareModules.remove(toRemove); } + @Override public boolean hardwareInterrupt(int address, Status status) { HardwareModule hardware = hardwareAddresses.get(address); @@ -566,6 +555,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Me } } + @Override public int hardwareQuery(int address) { HardwareModule hardware = hardwareAddresses.get(address); diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotBattery.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotBattery.java index d345501..4c8b80a 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotBattery.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotBattery.java @@ -1,10 +1,13 @@ package net.simon987.cubotplugin; +import net.simon987.server.GameServer; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Status; import net.simon987.server.game.objects.ControllableUnit; import org.bson.Document; +import org.json.simple.JSONObject; -public class CubotBattery extends CubotHardwareModule { +public class CubotBattery extends HardwareModule { public static final int DEFAULT_ADDRESS = 0x000A; @@ -12,16 +15,38 @@ public class CubotBattery extends CubotHardwareModule { * Hardware ID (Should be unique) */ public static final char HWID = 0x000A; + /** + * Solar panel multiplier + *
TODO: Set this constant in dimension + */ + private static final float SOLAR_PANEL_MULTIPLIER = 1; + + /** + * Energy units in kJ + */ + private int energy; + + /** + * Maximum energy units in kJ + */ + private int maxEnergy; + private static final int BATTERY_POLL = 1; private static final int BATTERY_GET_MAX_CAPACITY = 2; - public CubotBattery(Cubot cubot) { - super(cubot); + public CubotBattery(ControllableUnit unit) { + super(null, unit); + + energy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy"); + maxEnergy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy"); } public CubotBattery(Document document, ControllableUnit cubot) { super(document, cubot); + + energy = document.getInteger("energy"); + maxEnergy = document.getInteger("max_energy"); } @Override @@ -30,16 +55,12 @@ public class CubotBattery extends CubotHardwareModule { int a = getCpu().getRegisterSet().getRegister("A").getValue(); if (a == BATTERY_POLL) { - getCpu().getRegisterSet().getRegister("B").setValue(cubot.getEnergy()); + getCpu().getRegisterSet().getRegister("B").setValue(energy); } else if (a == BATTERY_GET_MAX_CAPACITY) { - getCpu().getRegisterSet().getRegister("B").setValue(cubot.getMaxEnergy()); + getCpu().getRegisterSet().getRegister("B").setValue(maxEnergy); - //TODO: Remove debug action - } else if (a == 0xFFFF) { - cubot.setEnergy(cubot.getMaxEnergy()); } - } @Override @@ -47,4 +68,53 @@ public class CubotBattery extends CubotHardwareModule { return HWID; } + @Override + public JSONObject jsonSerialise() { + JSONObject json = new JSONObject(); + + json.put("energy", energy); + + return json; + } + + @Override + public JSONObject debugJsonSerialise() { + JSONObject json = jsonSerialise(); + + json.put("max_energy", maxEnergy); + + return json; + } + + @Override + public Document mongoSerialise() { + Document document = super.mongoSerialise(); + + document.put("energy", energy); + document.put("max_energy", maxEnergy); + + return document; + } + + public int getEnergy() { + return energy; + } + + public void setEnergy(int energy) { + this.energy = energy; + } + + public int getMaxEnergy() { + return maxEnergy; + } + + public void setMaxEnergy(int maxEnergy) { + this.maxEnergy = maxEnergy; + } + + @Override + public void update() { + energy = Math.min(maxEnergy, + energy + (int) (SOLAR_PANEL_MULTIPLIER * GameServer.INSTANCE.getDayNightCycle().getSunIntensity())); + } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotComPort.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotComPort.java index c0eb4e6..65efed4 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotComPort.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotComPort.java @@ -1,5 +1,6 @@ package net.simon987.cubotplugin; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Status; import net.simon987.server.game.objects.ControllableUnit; import net.simon987.server.game.objects.GameObject; @@ -9,7 +10,7 @@ import org.bson.Document; import java.awt.*; import java.util.ArrayList; -public class CubotComPort extends CubotHardwareModule { +public class CubotComPort extends HardwareModule { public static final char HWID = 0xD; public static final int DEFAULT_ADDRESS = 0xD; @@ -20,8 +21,8 @@ public class CubotComPort extends CubotHardwareModule { private static final int COMPORT_SELF_OUT = 3; private static final int COMPORT_CONSOLE_CLEAR = 4; - public CubotComPort(Cubot cubot) { - super(cubot); + public CubotComPort(ControllableUnit unit) { + super(null, unit); } public CubotComPort(Document document, ControllableUnit cubot) { @@ -37,21 +38,23 @@ public class CubotComPort extends CubotHardwareModule { if (a == COMPORT_BUFFER_CLEAR) { - cubot.getConsoleMessagesBuffer().clear(); + unit.getConsoleMessagesBuffer().clear(); } else if (a == COMPORT_CONSOLE_CLEAR) { - - cubot.setConsoleMode(Cubot.ConsoleMode.CLEAR); + + if (unit instanceof Cubot) { + ((Cubot) unit).setConsoleMode(Cubot.ConsoleMode.CLEAR); + } } else if (a == COMPORT_POLL) { - if (cubot.spendEnergy(4)) { + if (unit.spendEnergy(4)) { int x = getCpu().getRegisterSet().getRegister("X").getValue(); //Read all messages in the console buffer to memory at X - for (char[] message : cubot.getConsoleMessagesBuffer()) { + for (char[] message : unit.getConsoleMessagesBuffer()) { if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) { //todo set interrupt ? getCpu().getStatus().setErrorFlag(true); @@ -61,17 +64,17 @@ public class CubotComPort extends CubotHardwareModule { } //Set B = number of messages - getCpu().getRegisterSet().getRegister("B").setValue(cubot.getConsoleMessagesBuffer().size()); + getCpu().getRegisterSet().getRegister("B").setValue(unit.getConsoleMessagesBuffer().size()); } } else if (a == COMPORT_FRONT_PORT_OUT) { - if (cubot.spendEnergy(5)) { + if (unit.spendEnergy(5)) { //Get object directly in front of the Cubot - Point frontTile = cubot.getFrontTile(); + Point frontTile = unit.getFrontTile(); //Todo will have to add getGameObjectsBlockingAt to enable Factory - ArrayList objects = cubot.getWorld().getGameObjectsAt(frontTile.x, frontTile.y); + ArrayList objects = unit.getWorld().getGameObjectsAt(frontTile.x, frontTile.y); if (objects.size() > 0 && objects.get(0) instanceof MessageReceiver) { @@ -98,7 +101,7 @@ public class CubotComPort extends CubotHardwareModule { } else if (a == COMPORT_SELF_OUT) { - if (cubot.spendEnergy(1)) { + if (unit.spendEnergy(1)) { int x = getCpu().getRegisterSet().getRegister("X").getValue(); @@ -111,7 +114,7 @@ public class CubotComPort extends CubotHardwareModule { //Get MESSAGE_LENGTH-word message pointed by X char[] message = new char[MESSAGE_LENGTH]; System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH); - getCpu().getRegisterSet().getRegister("B").setValue(cubot.sendMessage(message) ? 1 : 0); + getCpu().getRegisterSet().getRegister("B").setValue(unit.sendMessage(message) ? 1 : 0); return; } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotCore.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotCore.java index 74a303f..6a8996a 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotCore.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotCore.java @@ -1,10 +1,11 @@ package net.simon987.cubotplugin; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Status; import net.simon987.server.game.objects.ControllableUnit; import org.bson.Document; -public class CubotCore extends CubotHardwareModule { +public class CubotCore extends HardwareModule { public static final int DEFAULT_ADDRESS = 0x000E; @@ -16,12 +17,12 @@ public class CubotCore extends CubotHardwareModule { private static final int CORE_STATUS_POLL = 1; private static final int CORE_HULL_POLL = 2; - public CubotCore(Cubot cubot) { - super(cubot); + public CubotCore(ControllableUnit unit) { + super(null, unit); } - public CubotCore(Document document, ControllableUnit cubot) { - super(document, cubot); + public CubotCore(Document document, ControllableUnit unit) { + super(document, unit); } @Override @@ -30,9 +31,11 @@ public class CubotCore extends CubotHardwareModule { int a = getCpu().getRegisterSet().getRegister("A").getValue(); if (a == CORE_STATUS_POLL) { - getCpu().getRegisterSet().getRegister("B").setValue(cubot.getStatus()); + if (unit instanceof Cubot) { + getCpu().getRegisterSet().getRegister("B").setValue(((Cubot) unit).getStatus()); + } } else if (a == CORE_HULL_POLL) { - getCpu().getRegisterSet().getRegister("B").setValue(cubot.getHp()); + getCpu().getRegisterSet().getRegister("B").setValue(unit.getHp()); } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotDrill.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotDrill.java index 884fe90..88dc0b9 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotDrill.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotDrill.java @@ -1,5 +1,6 @@ package net.simon987.cubotplugin; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Status; import net.simon987.server.game.item.Item; import net.simon987.server.game.objects.Action; @@ -7,7 +8,7 @@ import net.simon987.server.game.objects.ControllableUnit; import net.simon987.server.game.world.Tile; import org.bson.Document; -public class CubotDrill extends CubotHardwareModule { +public class CubotDrill extends HardwareModule { /** * Hardware ID (Should be unique) @@ -19,8 +20,8 @@ public class CubotDrill extends CubotHardwareModule { private static final int DRILL_POLL = 1; private static final int DRILL_GATHER = 2; // simplified gather - public CubotDrill(Cubot cubot) { - super(cubot); + public CubotDrill(ControllableUnit unit) { + super(null, unit); } public CubotDrill(Document document, ControllableUnit cubot) { @@ -42,15 +43,15 @@ public class CubotDrill extends CubotHardwareModule { } else if (a == DRILL_GATHER) { - if (cubot.spendEnergy(1400)) { - if (cubot.getCurrentAction() == Action.IDLE) { + if (unit.spendEnergy(1400)) { + if (unit.getCurrentAction() == Action.IDLE) { - Tile tile = cubot.getWorld().getTileMap().getTileAt(cubot.getX(), cubot.getY()); + Tile tile = unit.getWorld().getTileMap().getTileAt(unit.getX(), unit.getY()); Item newItem = tile.drill(); if (newItem != null) { - cubot.setCurrentAction(Action.DIGGING); - cubot.giveItem(newItem); + unit.setCurrentAction(Action.DIGGING); + unit.giveItem(newItem); } } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHardwareModule.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHardwareModule.java index 4f9a5f5..0df894b 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHardwareModule.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHardwareModule.java @@ -16,11 +16,4 @@ public abstract class CubotHardwareModule extends HardwareModule { this.cubot = cubot; } - @Override - public Document mongoSerialise() { - Document document = new Document(); - - document.put("type", getClass().getCanonicalName()); - return document; - } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHologram.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHologram.java index 9e291c2..f19e88c 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHologram.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotHologram.java @@ -1,11 +1,12 @@ package net.simon987.cubotplugin; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Status; import net.simon987.server.game.objects.ControllableUnit; import org.bson.Document; import org.json.simple.JSONObject; -public class CubotHologram extends CubotHardwareModule { +public class CubotHologram extends HardwareModule { /** * Hardware ID (Should be unique) @@ -31,8 +32,8 @@ public class CubotHologram extends CubotHardwareModule { */ private int displayColor = 0; - public CubotHologram(Cubot cubot) { - super(cubot); + public CubotHologram(ControllableUnit unit) { + super(null, unit); } public CubotHologram(Document document, ControllableUnit cubot) { @@ -80,7 +81,7 @@ public class CubotHologram extends CubotHardwareModule { } else if (a == HOLO_DISPLAY_COLOR) { - if (cubot.spendEnergy(4)) { + if (unit.spendEnergy(4)) { int b = getCpu().getRegisterSet().getRegister("B").getValue(); int c = getCpu().getRegisterSet().getRegister("C").getValue(); diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotInventory.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotInventory.java index 263b9b4..0a344a4 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotInventory.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotInventory.java @@ -1,16 +1,16 @@ package net.simon987.cubotplugin; import net.simon987.server.GameServer; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Status; import net.simon987.server.game.item.Item; -import net.simon987.server.game.item.ItemCopper; import net.simon987.server.game.objects.ControllableUnit; import org.bson.Document; import java.util.HashMap; import java.util.Map; -public class CubotInventory extends CubotHardwareModule { +public class CubotInventory extends HardwareModule { /** * Hardware ID (Should be unique) @@ -29,11 +29,10 @@ public class CubotInventory extends CubotHardwareModule { private int position = 0; - public CubotInventory(Cubot cubot) { - super(cubot); + public CubotInventory(ControllableUnit unit) { + super(null, unit); inventory = new HashMap<>(); - inventory.put(2, new ItemCopper(new Document())); // TODO: Remove debug value } public CubotInventory(Document document, ControllableUnit cubot) { @@ -56,12 +55,12 @@ public class CubotInventory extends CubotHardwareModule { private void scanItem() { int x = getCpu().getRegisterSet().getRegister("X").getValue(); Item item = inventory.get(position); - item.digitize(cubot.getCpu().getMemory(), x); + item.digitize(unit.getCpu().getMemory(), x); } public Item clearItem() { Item item = inventory.get(position); - item.clear(cubot); + item.clear(unit); inventory.remove(position); return item; @@ -100,13 +99,13 @@ public class CubotInventory extends CubotHardwareModule { getCpu().getRegisterSet().getRegister("B").setValue(result); } else if (a == INV_CLEAR) { - if (cubot.spendEnergy(100)) { + if (unit.spendEnergy(100)) { clearItem(); } } else if (a == INV_SEEK) { setPosition(getCpu().getRegisterSet().getRegister("X").getValue()); } else if (a == INV_SCAN) { - if (cubot.spendEnergy(200)) { + if (unit.spendEnergy(200)) { scanItem(); clearItem(); } 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 186f2e6..040c3ad 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLaser.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLaser.java @@ -1,6 +1,7 @@ package net.simon987.cubotplugin; import net.simon987.server.GameServer; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Status; import net.simon987.server.game.objects.*; import org.bson.Document; @@ -8,7 +9,7 @@ import org.bson.Document; import java.awt.*; import java.util.ArrayList; -public class CubotLaser extends CubotHardwareModule { +public class CubotLaser extends HardwareModule { /** * Hardware ID (Should be unique) @@ -23,8 +24,8 @@ public class CubotLaser extends CubotHardwareModule { private static final int LASER_DAMAGE = 25; - public CubotLaser(Cubot cubot) { - super(cubot); + public CubotLaser(ControllableUnit unit) { + super(null, unit); } public CubotLaser(Document document, ControllableUnit cubot) { @@ -46,19 +47,19 @@ public class CubotLaser extends CubotHardwareModule { if (a == LASER_WITHDRAW) { - Point frontTile = cubot.getFrontTile(); - ArrayList objects = cubot.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y); + Point frontTile = unit.getFrontTile(); + ArrayList objects = unit.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y); - if (cubot.getCurrentAction() == Action.IDLE && objects.size() > 0) { + if (unit.getCurrentAction() == Action.IDLE && objects.size() > 0) { //FIXME: Problem here if more than 1 object if (objects.get(0) instanceof InventoryHolder) { if (((InventoryHolder) objects.get(0)).canTakeItem(b)) { - if (cubot.spendEnergy(30)) { + if (unit.spendEnergy(30)) { //Take the item ((InventoryHolder) objects.get(0)).takeItem(b); - cubot.giveItem(GameServer.INSTANCE.getRegistry().makeItem(b)); - cubot.setCurrentAction(Action.WITHDRAWING); + unit.giveItem(GameServer.INSTANCE.getRegistry().makeItem(b)); + unit.setCurrentAction(Action.WITHDRAWING); } } } @@ -69,12 +70,12 @@ public class CubotLaser extends CubotHardwareModule { // TODO } else if (a == LASER_ATTACK) { - if (cubot.getCurrentAction() == Action.IDLE) { - if (cubot.spendEnergy(70)) { + if (unit.getCurrentAction() == Action.IDLE) { + if (unit.spendEnergy(70)) { //Get object directly in front of the Cubot - Point frontTile = cubot.getFrontTile(); - ArrayList objects = cubot.getWorld().getGameObjectsAt(frontTile.x, frontTile.y); + Point frontTile = unit.getFrontTile(); + ArrayList objects = unit.getWorld().getGameObjectsAt(frontTile.x, frontTile.y); //todo: Add option in config to allow PvP if (objects.size() > 0 && objects.get(0) instanceof Attackable && !(objects.get(0) instanceof Cubot)) { @@ -83,7 +84,7 @@ public class CubotLaser extends CubotHardwareModule { } - cubot.setCurrentAction(Action.ATTACKING); + unit.setCurrentAction(Action.ATTACKING); } } 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 99710e1..f91c329 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLeg.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLeg.java @@ -1,12 +1,13 @@ package net.simon987.cubotplugin; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Status; import net.simon987.server.game.objects.Action; import net.simon987.server.game.objects.ControllableUnit; import net.simon987.server.game.objects.Direction; import org.bson.Document; -public class CubotLeg extends CubotHardwareModule { +public class CubotLeg extends HardwareModule { public static final int DEFAULT_ADDRESS = 1; @@ -18,12 +19,12 @@ public class CubotLeg extends CubotHardwareModule { */ static final char HWID = 0x0001; - public CubotLeg(Cubot cubot) { - super(cubot); + public CubotLeg(ControllableUnit unit) { + super(null, unit); } - public CubotLeg(Document document, ControllableUnit cubot) { - super(document, cubot); + public CubotLeg(Document document, ControllableUnit unit) { + super(document, unit); } @Override @@ -34,7 +35,7 @@ public class CubotLeg extends CubotHardwareModule { @Override public void handleInterrupt(Status status) { - if (cubot.getCurrentAction() == Action.IDLE) { + if (unit.getCurrentAction() == Action.IDLE) { int a = getCpu().getRegisterSet().getRegister("A").getValue(); int b = getCpu().getRegisterSet().getRegister("B").getValue(); @@ -44,8 +45,8 @@ public class CubotLeg extends CubotHardwareModule { Direction dir = Direction.getDirection(b); if (dir != null) { - if (cubot.spendEnergy(20)) { - cubot.setDirection(Direction.getDirection(b)); + if (unit.spendEnergy(20)) { + unit.setDirection(Direction.getDirection(b)); status.setErrorFlag(false); } } else { @@ -55,17 +56,17 @@ public class CubotLeg extends CubotHardwareModule { } else if (a == LEGS_SET_DIR_AND_WALK) { - if (cubot.getMaxEnergy() >= 100) { + if (unit.getMaxEnergy() >= 100) { Direction dir = Direction.getDirection(b); if (dir != null) { - cubot.setDirection(Direction.getDirection(b)); + unit.setDirection(Direction.getDirection(b)); status.setErrorFlag(false); } else { status.setErrorFlag(true); } - cubot.setCurrentAction(Action.WALKING); + unit.setCurrentAction(Action.WALKING); } } } diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLidar.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLidar.java index 04da704..dd5eb0b 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLidar.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotLidar.java @@ -1,5 +1,6 @@ package net.simon987.cubotplugin; +import net.simon987.server.assembly.HardwareModule; import net.simon987.server.assembly.Memory; import net.simon987.server.assembly.Status; import net.simon987.server.game.objects.ControllableUnit; @@ -9,7 +10,7 @@ import org.bson.Document; import java.util.ArrayList; -public class CubotLidar extends CubotHardwareModule { +public class CubotLidar extends HardwareModule { /** * Hardware ID (Should be unique) @@ -24,12 +25,12 @@ public class CubotLidar extends CubotHardwareModule { private static final int LIDAR_GET_WORLD_POS = 4; private static final int LIDAR_GET_WORLD_SIZE = 5; - public CubotLidar(Cubot cubot) { - super(cubot); + public CubotLidar(ControllableUnit unit) { + super(null, unit); } - public CubotLidar(Document document, ControllableUnit cubot) { - super(document, cubot); + public CubotLidar(Document document, ControllableUnit unit) { + super(document, unit); } @Override @@ -44,18 +45,18 @@ public class CubotLidar extends CubotHardwareModule { switch (a) { case LIDAR_GET_POS: - getCpu().getRegisterSet().getRegister("X").setValue(cubot.getX()); - getCpu().getRegisterSet().getRegister("Y").setValue(cubot.getY()); + getCpu().getRegisterSet().getRegister("X").setValue(unit.getX()); + getCpu().getRegisterSet().getRegister("Y").setValue(unit.getY()); break; case LIDAR_GET_PATH: - if (cubot.spendEnergy(50)) { + if (unit.spendEnergy(50)) { int c = getCpu().getRegisterSet().getRegister("C").getValue(); int b = getCpu().getRegisterSet().getRegister("B").getValue(); int destX = getCpu().getRegisterSet().getRegister("X").getValue(); int destY = getCpu().getRegisterSet().getRegister("Y").getValue(); //Get path - ArrayList nodes = Pathfinder.findPath(cubot.getWorld(), cubot.getX(), cubot.getY(), + ArrayList nodes = Pathfinder.findPath(unit.getWorld(), unit.getX(), unit.getY(), destX, destY, b); //Write to memory @@ -102,13 +103,13 @@ public class CubotLidar extends CubotHardwareModule { break; case LIDAR_GET_MAP: - if (cubot.spendEnergy(10)) { - char[][] mapInfo = cubot.getWorld().getMapInfo(); + if (unit.spendEnergy(10)) { + char[][] mapInfo = unit.getWorld().getMapInfo(); //Write map data to the location specified by register X int i = getCpu().getRegisterSet().getRegister("X").getValue(); - for (int x = 0; x < cubot.getWorld().getWorldSize(); x++) { - for (int y = 0; y < cubot.getWorld().getWorldSize(); y++) { + for (int x = 0; x < unit.getWorld().getWorldSize(); x++) { + for (int y = 0; y < unit.getWorld().getWorldSize(); y++) { getCpu().getMemory().set(i++, mapInfo[x][y]); } } @@ -116,13 +117,13 @@ public class CubotLidar extends CubotHardwareModule { break; case LIDAR_GET_WORLD_SIZE: - getCpu().getRegisterSet().getRegister("X").setValue(cubot.getWorld().getWorldSize()); - getCpu().getRegisterSet().getRegister("Y").setValue(cubot.getWorld().getWorldSize()); + getCpu().getRegisterSet().getRegister("X").setValue(unit.getWorld().getWorldSize()); + getCpu().getRegisterSet().getRegister("Y").setValue(unit.getWorld().getWorldSize()); break; case LIDAR_GET_WORLD_POS: - getCpu().getRegisterSet().getRegister("X").setValue(cubot.getWorld().getX()); - getCpu().getRegisterSet().getRegister("Y").setValue(cubot.getWorld().getY()); + getCpu().getRegisterSet().getRegister("X").setValue(unit.getWorld().getX()); + getCpu().getRegisterSet().getRegister("Y").setValue(unit.getWorld().getY()); break; } 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 08d78e0..c34c085 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 @@ -50,13 +50,6 @@ public class UserCreationListener implements GameEventListener { cubot.getWorld().addObject(cubot); cubot.getWorld().incUpdatable(); - cubot.setEnergy(config.getInt("battery_max_energy")); - cubot.setMaxEnergy(config.getInt("battery_max_energy")); - - cubot.setHp(config.getInt("cubot_max_hp")); - cubot.setMaxHp(config.getInt("cubot_max_hp")); - cubot.setMaxShield(config.getInt("cubot_max_shield")); - cubot.setParent(user); user.setControlledUnit(cubot); @@ -81,6 +74,10 @@ public class UserCreationListener implements GameEventListener { e.printStackTrace(); } + cubot.setHp(config.getInt("cubot_max_hp")); + cubot.setMaxHp(config.getInt("cubot_max_hp")); + cubot.setMaxShield(config.getInt("cubot_max_shield")); + LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)"); } } 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 0d82c14..175f372 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java @@ -1,17 +1,19 @@ package net.simon987.npcplugin; import net.simon987.server.GameServer; +import net.simon987.server.game.objects.MessageReceiver; import net.simon987.server.game.objects.Structure; import net.simon987.server.game.objects.Updatable; import org.bson.Document; import org.bson.types.ObjectId; import java.awt.*; +import java.util.Arrays; /** * Game objects that regularly creates NonPlayerCharacters */ -public class Factory extends Structure implements Updatable { +public class Factory extends Structure implements Updatable, MessageReceiver { private static final int MAP_INFO = 0x0401; @@ -30,6 +32,15 @@ public class Factory extends Structure implements Updatable { */ private int cooldown = 0; + private boolean locked = true; + + /** + * If non-null, the next spawned NPC will be a HackedNPC and the program will be + * injected in its memory + */ + private char[] program; + private int programIndex = 0; + public Factory() { super(2, 2); } @@ -57,14 +68,7 @@ public class Factory extends Structure implements Updatable { Point p = getAdjacentTile(); if (p != null) { - NonPlayerCharacter npc = new HarvesterNPC(); - npc.setWorld(getWorld()); - npc.setObjectId(new ObjectId()); - npc.setX(p.x); - npc.setY(p.y); - getWorld().addObject(npc); - getWorld().incUpdatable(); - + NonPlayerCharacter npc = spawnNPC(p); settlement.addNpc(npc); } } @@ -75,4 +79,65 @@ public class Factory extends Structure implements Updatable { cooldown--; } } + + private NonPlayerCharacter spawnNPC(Point p) { + + NonPlayerCharacter npc; + if (programIndex == 0) { + npc = new HarvesterNPC(); + npc.setWorld(getWorld()); + npc.setObjectId(new ObjectId()); + npc.setX(p.x); + npc.setY(p.y); + getWorld().addObject(npc); + getWorld().incUpdatable(); + } else { + + npc = new HackedNPC(program); + npc.setWorld(getWorld()); + npc.setObjectId(new ObjectId()); + npc.setX(p.x); + npc.setY(p.y); + getWorld().addObject(npc); + getWorld().incUpdatable(); + + System.out.println("NEW HACKED NPC"); + this.locked = true; + } + + return npc; + } + + @Override + public boolean sendMessage(char[] message) { + + String strMessage = String.valueOf(message); + + System.out.println("Received message " + strMessage); + if (locked) { + Settlement settlement = NpcPlugin.settlementMap.get(getWorld().getId()); + + if (Arrays.equals(settlement.getPassword(), message)) { + System.out.println("Factory unlock"); + this.locked = false; + + return true; + } + System.out.println("Wrong password, " + strMessage + "!=" + String.valueOf(settlement.getPassword())); + } else if (programIndex <= 2048) { //todo config + + if (programIndex == 0) { + program = new char[2048]; + } + + System.arraycopy(message, 0, program, programIndex, message.length); + System.out.println("Factory append code: " + strMessage); + System.out.println("Wrote " + message.length + " chars"); + programIndex += message.length; + + return true; + } + + return false; + } } diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/HackedNPC.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/HackedNPC.java new file mode 100644 index 0000000..ea85a61 --- /dev/null +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/HackedNPC.java @@ -0,0 +1,314 @@ +package net.simon987.npcplugin; + +import net.simon987.server.GameServer; +import net.simon987.server.assembly.*; +import net.simon987.server.game.item.Item; +import net.simon987.server.game.item.ItemVoid; +import net.simon987.server.game.objects.Action; +import net.simon987.server.game.objects.ControllableUnit; +import net.simon987.server.game.objects.Direction; +import net.simon987.server.game.objects.HardwareHost; +import net.simon987.server.user.User; +import org.bson.Document; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HackedNPC extends NonPlayerCharacter implements ControllableUnit, HardwareHost { + + private static final int MEM_SIZE = GameServer.INSTANCE.getConfig().getInt("hacked_npc_mem_size"); + + private CPU cpu; + /** + * List of attached hardware, 'modules' + */ + private Map hardwareAddresses = new HashMap<>(); + private Map, Integer> hardwareModules = new HashMap<>(); + + private Action currentAction = Action.IDLE; + private Action lastAction = Action.IDLE; + private ArrayList consoleMessagesBuffer = new ArrayList<>(30); //todo load from conf + private ArrayList lastConsoleMessagesBuffer = new ArrayList<>(30); + + HackedNPC(char[] program) { + + cpu = new CPU(); + + cpu.setMemory(new Memory(MEM_SIZE)); + cpu.setHardwareHost(this); + //Write program + boolean write = cpu.getMemory().write(0, program, 0, program.length); + System.out.println("Write " + write); + + for (Object serialisedHw : (List) NpcPlugin.DEFAULT_HACKED_NPC.get("hardware")) { + HardwareModule hardware = GameServer.INSTANCE.getRegistry().deserializeHardware((Document) serialisedHw, this); + hardware.setCpu(cpu); + attachHardware(hardware, ((Document) serialisedHw).getInteger("address")); + } + } + + public HackedNPC(Document document) { + super(document); + + setHp(document.getInteger("hp")); + setDirection(Direction.getDirection(document.getInteger("direction"))); + + cpu = new CPU(); + cpu.setHardwareHost(this); + cpu.setMemory(new Memory((Document) document.get("memory"))); + cpu.setRegisterSet(RegisterSet.deserialize((Document) document.get("registerSet"))); + + ArrayList hardwareList = (ArrayList) document.get("hardware"); + + for (Object serialisedHw : hardwareList) { + HardwareModule hardware = GameServer.INSTANCE.getRegistry().deserializeHardware((Document) serialisedHw, this); + hardware.setCpu(cpu); + attachHardware(hardware, ((Document) serialisedHw).getInteger("address")); + } + } + + @Override + public void update() { + + + System.out.println(Util.toHex(cpu.getMemory().getBytes())); + + //Execute code + System.out.println("HACKED NPC " + this.getObjectId()); + int timeout = Math.min(getEnergy(), 30); //todo get from config + cpu.reset(); + int cost = cpu.execute(timeout); + spendEnergy(cost); + + if (currentAction == Action.WALKING) { + if (spendEnergy(100)) { + if (!incrementLocation()) { + //Couldn't walk + currentAction = Action.IDLE; + } + } else { + currentAction = Action.IDLE; + } + } + + /* + * CurrentAction is set during the code execution and this function is called right after + * If no action as been set, the action sent to the client is the action in currentAction that + * was set last tick (IDLE) + */ + lastAction = currentAction; + currentAction = Action.IDLE; + + lastConsoleMessagesBuffer = new ArrayList<>(consoleMessagesBuffer); + consoleMessagesBuffer.clear(); + + for (HardwareModule module : hardwareAddresses.values()) { + module.update(); + } + } + + @Override + public void setKeyboardBuffer(ArrayList kbBuffer) { + } + + @Override + public void setParent(User user) { + } + + @Override + public User getParent() { + return null; + } + + @Override + public ArrayList getKeyboardBuffer() { + return null; + } + + @Override + public Memory getFloppyData() { + return null; + } + + + @Override + public void setAction(Action action) { + currentAction = action; + } + + @Override + public ArrayList getConsoleMessagesBuffer() { + return null; + } + + @Override + public int getConsoleMode() { + return 0; + } + + @Override + public CPU getCpu() { + return cpu; + } + + @Override + public void giveItem(Item item) { + //Overwrite item at current position + ((NpcInventory) getHardware(NpcInventory.class)).putItem(item); + } + + @Override + public void attachHardware(HardwareModule hardware, int address) { + hardwareAddresses.put(address, hardware); + hardwareModules.put(hardware.getClass(), address); + } + + @Override + public void detachHardware(int address) { + hardwareAddresses.remove(address); + + Class toRemove = null; + for (Class clazz : hardwareModules.keySet()) { + if (hardwareModules.get(clazz) == address) { + toRemove = clazz; + } + } + hardwareModules.remove(toRemove); + } + + @Override + public boolean hardwareInterrupt(int address, Status status) { + HardwareModule hardware = hardwareAddresses.get(address); + + if (hardware != null) { + hardware.handleInterrupt(status); + return true; + } else { + return false; + } + } + + @Override + public int hardwareQuery(int address) { + HardwareModule hardware = hardwareAddresses.get(address); + + if (hardware != null) { + return hardware.getId(); + } else { + return 0; + } + } + + public int getEnergy() { + NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class); + return battery.getEnergy(); + } + + public void setEnergy(int energy) { + NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class); + battery.setEnergy(energy); + } + + public boolean spendEnergy(int amount) { + + NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class); + + if (battery.getEnergy() - amount < 0) { + return false; + } else { + battery.setEnergy(battery.getEnergy() - amount); + return true; + } + } + + @Override + public Document mongoSerialise() { + Document dbObject = super.mongoSerialise(); + + dbObject.put("direction", getDirection().ordinal()); + dbObject.put("hp", getHp()); + dbObject.put("action", lastAction.ordinal()); + + List hardwareList = new ArrayList<>(); + + for (Integer address : hardwareAddresses.keySet()) { + + HardwareModule hardware = hardwareAddresses.get(address); + + Document serialisedHw = hardware.mongoSerialise(); + serialisedHw.put("address", address); + hardwareList.add(serialisedHw); + } + + dbObject.put("hardware", hardwareList); + + dbObject.put("memory", cpu.getMemory().mongoSerialise()); + + dbObject.put("registerSet", cpu.getRegisterSet().mongoSerialise()); + return dbObject; + } + + public void storeEnergy(int amount) { + + NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class); + battery.setEnergy(Math.min(battery.getEnergy() + amount, battery.getMaxEnergy())); + } + + private HardwareModule getHardware(Class clazz) { + return hardwareAddresses.get(hardwareModules.get(clazz)); + } + + public void setMaxEnergy(int maxEnergy) { + NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class); + battery.setMaxEnergy(maxEnergy); + } + + public int getMaxEnergy() { + NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class); + return battery.getMaxEnergy(); + } + + @Override + public boolean sendMessage(char[] message) { + return false; + } + + @Override + public void setCurrentAction(Action action) { + currentAction = action; + } + + @Override + public Action getCurrentAction() { + return currentAction; + } + + @Override + public JSONObject jsonSerialise() { + JSONObject json = super.jsonSerialise(); + + for (HardwareModule module : hardwareAddresses.values()) { + JSONObject hwJson = module.jsonSerialise(); + if (hwJson != null) { + json.put(module.getClass().getName(), hwJson); + } + } + + json.put("direction", getDirection().ordinal()); + NpcInventory inv = (NpcInventory) getHardware(NpcInventory.class); + Item item = inv.getItem(); + json.put("heldItem", item == null ? new ItemVoid().getId() : item.getId()); + json.put("hp", getHp()); + json.put("action", lastAction.ordinal()); + + return json; + } + + @Override + public JSONObject debugJsonSerialise() { + return jsonSerialise(); + } +} diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcBattery.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcBattery.java new file mode 100644 index 0000000..d5eb401 --- /dev/null +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcBattery.java @@ -0,0 +1,109 @@ +package net.simon987.npcplugin; + +import net.simon987.server.GameServer; +import net.simon987.server.assembly.HardwareModule; +import net.simon987.server.assembly.Status; +import net.simon987.server.game.objects.ControllableUnit; +import org.bson.Document; +import org.json.simple.JSONObject; + +public class NpcBattery extends HardwareModule { + + public static final int DEFAULT_ADDRESS = 0x010A; + + /** + * Hardware ID (Should be unique) + */ + public static final char HWID = 0x010A; + + /** + * Energy units in kJ + */ + private int energy; + + /** + * Maximum energy units in kJ + */ + private int maxEnergy; + + + private static final int BATTERY_POLL = 1; + private static final int BATTERY_GET_MAX_CAPACITY = 2; + + public NpcBattery(ControllableUnit unit) { + super(null, unit); + + energy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy"); + maxEnergy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy"); + } + + public NpcBattery(Document document, ControllableUnit cubot) { + super(document, cubot); + + energy = document.getInteger("energy"); + maxEnergy = document.getInteger("max_energy"); + } + + @Override + public void handleInterrupt(Status status) { + + int a = getCpu().getRegisterSet().getRegister("A").getValue(); + + if (a == BATTERY_POLL) { + getCpu().getRegisterSet().getRegister("B").setValue(unit.getEnergy()); + + } else if (a == BATTERY_GET_MAX_CAPACITY) { + getCpu().getRegisterSet().getRegister("B").setValue(unit.getMaxEnergy()); + + } + } + + @Override + public char getId() { + return HWID; + } + + @Override + public JSONObject jsonSerialise() { + JSONObject json = new JSONObject(); + + json.put("energy", energy); + + return json; + } + + @Override + public JSONObject debugJsonSerialise() { + JSONObject json = jsonSerialise(); + + json.put("max_energy", maxEnergy); + + return json; + } + + @Override + public Document mongoSerialise() { + Document document = super.mongoSerialise(); + + document.put("energy", energy); + document.put("max_energy", maxEnergy); + + return document; + } + + public int getEnergy() { + return energy; + } + + public void setEnergy(int energy) { + this.energy = energy; + } + + public int getMaxEnergy() { + return maxEnergy; + } + + public void setMaxEnergy(int maxEnergy) { + this.maxEnergy = maxEnergy; + } +} diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcInventory.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcInventory.java new file mode 100644 index 0000000..43477eb --- /dev/null +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcInventory.java @@ -0,0 +1,109 @@ +package net.simon987.npcplugin; + +import net.simon987.server.GameServer; +import net.simon987.server.assembly.HardwareModule; +import net.simon987.server.assembly.Status; +import net.simon987.server.game.item.Item; +import net.simon987.server.game.objects.ControllableUnit; +import org.bson.Document; + + +public class NpcInventory extends HardwareModule { + + /** + * Hardware ID (Should be unique) + */ + static final char HWID = 0x0106; + + public static final int DEFAULT_ADDRESS = 0x0106; + + private static final int INV_CLEAR = 0; + private static final int INV_POLL = 1; + private static final int INV_SCAN = 3; + + private Item item; + + public NpcInventory(ControllableUnit unit) { + super(null, unit); + } + + public NpcInventory(Document document, ControllableUnit cubot) { + super(document, cubot); + + Document itemDoc = (Document) document.get("item"); + if (itemDoc != null) { + item = GameServer.INSTANCE.getRegistry().deserializeItem(itemDoc); + } + } + + public void putItem(Item item) { + this.item = item; + } + + private void scanItem() { + int x = getCpu().getRegisterSet().getRegister("X").getValue(); + item.digitize(unit.getCpu().getMemory(), x); + } + + public Item clearItem() { + + Item oldItem = item; + item.clear(unit); + item = null; + + return oldItem; + } + + @Override + public char getId() { + return HWID; + } + + public Item getItem() { + return item; + } + + @Override + public void handleInterrupt(Status status) { + + int a = getCpu().getRegisterSet().getRegister("A").getValue(); + + if (a == INV_POLL) { + char result; + if (item == null) { + result = 0; + } else { + result = item.poll(); + } + getCpu().getRegisterSet().getRegister("B").setValue(result); + + } else if (a == INV_CLEAR) { + if (unit.spendEnergy(100)) { + clearItem(); + } + } else if (a == INV_SCAN) { + if (unit.spendEnergy(200)) { + scanItem(); + clearItem(); + } + } + } + + @Override + public Document mongoSerialise() { + Document document = super.mongoSerialise(); + + if (item != null) { + document.put("item", item.mongoSerialise()); + } else { + document.put("item", null); + } + + return document; + } + + @Override + public String toString() { + return String.format("{NpcInventory [%s]}", item); + } +} \ No newline at end of file diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java index 8d6f3ad..e6b790d 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java @@ -13,13 +13,17 @@ import net.simon987.server.logging.LogManager; import net.simon987.server.plugin.ServerPlugin; import org.bson.Document; +import java.io.InputStream; import java.util.Map; +import java.util.Scanner; import java.util.concurrent.ConcurrentHashMap; public class NpcPlugin extends ServerPlugin { public static Map settlementMap; + public static Document DEFAULT_HACKED_NPC; + @Override public void init(GameServer gameServer) { @@ -39,14 +43,22 @@ public class NpcPlugin extends ServerPlugin { registry.registerGameObject(ElectricBox.class); registry.registerGameObject(Portal.class); registry.registerGameObject(VaultExitPortal.class); + registry.registerGameObject(HackedNPC.class); registry.registerHardware(RadioReceiverHardware.class); + registry.registerHardware(NpcBattery.class); + registry.registerHardware(NpcInventory.class); registry.registerTile(TileVaultFloor.ID, TileVaultFloor.class); registry.registerTile(TileVaultWall.ID, TileVaultWall.class); settlementMap = new ConcurrentHashMap<>(); + InputStream is = getClass().getClassLoader().getResourceAsStream("defaultHackedCubotHardware.json"); + Scanner scanner = new Scanner(is).useDelimiter("\\A"); + String json = scanner.next(); + DEFAULT_HACKED_NPC = Document.parse(json); + LogManager.LOGGER.info("(NPC Plugin) Initialised NPC plugin"); } diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/Settlement.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/Settlement.java index 667329c..0afc06c 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/Settlement.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/Settlement.java @@ -59,6 +59,7 @@ public class Settlement implements MongoSerializable { this.world = world; this.difficultyLevel = DifficultyLevel.NORMAL; //TODO randomize ? + this.password = "12345678".toCharArray(); outerLoopFactory: for (int x = 2; x < 12; x++) { @@ -175,7 +176,7 @@ public class Settlement implements MongoSerializable { } document.put("factory", factory.getObjectId()); document.put("difficulty_level", difficultyLevel.ordinal()); - document.put("password", "1234567"); //todo + document.put("password", String.valueOf(password)); List npcArray = new ArrayList<>(npcs.size()); diff --git a/Plugin NPC/src/main/resources/defaultHackedCubotHardware.json b/Plugin NPC/src/main/resources/defaultHackedCubotHardware.json new file mode 100644 index 0000000..1784c2e --- /dev/null +++ b/Plugin NPC/src/main/resources/defaultHackedCubotHardware.json @@ -0,0 +1,62 @@ +{ + "hardware": [ + { + "type": "net.simon987.cubotplugin.CubotLeg", + "address": 1 + }, + { + "type": "net.simon987.cubotplugin.CubotLaser", + "address": 2 + }, + { + "type": "net.simon987.cubotplugin.CubotLidar", + "address": 3 + }, + { + "type": "net.simon987.cubotplugin.CubotDrill", + "address": 5 + }, + { + "type": "net.simon987.npcplugin.NpcInventory", + "item": null, + "address": 6 + }, + { + "type": "net.simon987.mischwplugin.RandomNumberGenerator", + "address": 7 + }, + { + "type": "net.simon987.mischwplugin.Clock", + "address": 8 + }, + { + "type": "net.simon987.cubotplugin.CubotHologram", + "color": 0, + "value": 0, + "string": "", + "mode": 0, + "address": 9 + }, + { + "type": "net.simon987.npcplugin.NpcBattery", + "energy": 60000, + "max_energy": 60000, + "address": 262 + }, + { + "type": "net.simon987.npcplugin.RadioReceiverHardware", + "cubot": { + "$oid": "5c1d43e40d3d2530aba636df" + }, + "address": 12 + }, + { + "type": "net.simon987.cubotplugin.CubotComPort", + "address": 13 + }, + { + "type": "net.simon987.cubotplugin.CubotCore", + "address": 14 + } + ] +} \ No newline at end of file diff --git a/Plugin NPC/src/main/resources/plugin.properties b/Plugin NPC/src/main/resources/plugin.properties index 91f14e5..bfd7fd6 100644 --- a/Plugin NPC/src/main/resources/plugin.properties +++ b/Plugin NPC/src/main/resources/plugin.properties @@ -1,3 +1,4 @@ classpath=net.simon987.npcplugin.NpcPlugin name=NPC Plugin -version=1.1 \ No newline at end of file +version=1.1 +depend=Cubot Plugin \ No newline at end of file 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 38898bc..c25fc3f 100755 --- a/Server/src/main/java/net/simon987/server/assembly/CPU.java +++ b/Server/src/main/java/net/simon987/server/assembly/CPU.java @@ -60,6 +60,41 @@ public class CPU implements MongoSerializable { private static final char EXECUTION_COST_ADDR = 0x0050; private static final char EXECUTED_INS_ADDR = 0x0051; + public CPU() { + instructionSet = new DefaultInstructionSet(); + registerSet = new DefaultRegisterSet(); + codeSectionOffset = 0; + + instructionSet.add(new JmpInstruction(this)); + instructionSet.add(new JnzInstruction(this)); + instructionSet.add(new JzInstruction(this)); + instructionSet.add(new JgInstruction(this)); + instructionSet.add(new JgeInstruction(this)); + instructionSet.add(new JleInstruction(this)); + instructionSet.add(new JlInstruction(this)); + instructionSet.add(new PushInstruction(this)); + instructionSet.add(new PopInstruction(this)); + instructionSet.add(new CallInstruction(this)); + instructionSet.add(new RetInstruction(this)); + instructionSet.add(new MulInstruction(this)); + instructionSet.add(new DivInstruction(this)); + instructionSet.add(new JnsInstruction(this)); + instructionSet.add(new JsInstruction(this)); + instructionSet.add(new HwiInstruction(this)); + instructionSet.add(new HwqInstruction(this)); + instructionSet.add(new XchgInstruction(this)); + instructionSet.add(new JcInstruction(this)); + instructionSet.add(new JncInstruction(this)); + instructionSet.add(new JnoInstruction(this)); + instructionSet.add(new JoInstruction(this)); + instructionSet.add(new PushfInstruction(this)); + instructionSet.add(new PopfInstruction(this)); + instructionSet.add(new JnaInstruction(this)); + instructionSet.add(new JaInstruction(this)); + + status = new Status(); + } + /** * Creates a new CPU */ @@ -359,7 +394,6 @@ public class CPU implements MongoSerializable { cpu.codeSectionOffset = obj.getInteger("codeSegmentOffset"); - cpu.memory = new Memory((Document) obj.get("memory")); cpu.registerSet = RegisterSet.deserialize((Document) obj.get("registerSet")); @@ -379,6 +413,14 @@ public class CPU implements MongoSerializable { return memory; } + public void setMemory(Memory memory) { + this.memory = memory; + } + + public void setRegisterSet(RegisterSet registerSet) { + this.registerSet = registerSet; + } + public Status getStatus() { return status; } diff --git a/Server/src/main/java/net/simon987/server/assembly/HardwareModule.java b/Server/src/main/java/net/simon987/server/assembly/HardwareModule.java index 290365e..b352e6d 100644 --- a/Server/src/main/java/net/simon987/server/assembly/HardwareModule.java +++ b/Server/src/main/java/net/simon987/server/assembly/HardwareModule.java @@ -11,13 +11,14 @@ import org.json.simple.JSONObject; public abstract class HardwareModule implements MongoSerializable, JSONSerializable { private CPU cpu; + protected ControllableUnit unit; public HardwareModule() { } public HardwareModule(Document document, ControllableUnit unit) { - + this.unit = unit; } /** @@ -58,4 +59,12 @@ public abstract class HardwareModule implements MongoSerializable, JSONSerializa public JSONObject debugJsonSerialise() { return null; } + + @Override + public Document mongoSerialise() { + Document document = new Document(); + + document.put("type", getClass().getCanonicalName()); + return document; + } } diff --git a/Server/src/main/java/net/simon987/server/game/objects/ControllableUnit.java b/Server/src/main/java/net/simon987/server/game/objects/ControllableUnit.java index d326da3..989c1f0 100644 --- a/Server/src/main/java/net/simon987/server/game/objects/ControllableUnit.java +++ b/Server/src/main/java/net/simon987/server/game/objects/ControllableUnit.java @@ -7,9 +7,10 @@ import net.simon987.server.game.world.World; import net.simon987.server.user.User; import org.bson.types.ObjectId; +import java.awt.*; import java.util.ArrayList; -public interface ControllableUnit { +public interface ControllableUnit extends MessageReceiver, Rechargeable, Attackable { ObjectId getObjectId(); @@ -31,7 +32,11 @@ public interface ControllableUnit { int getY(); - void setAction(Action listening); + void setAction(Action action); + + void setCurrentAction(Action action); + + Action getCurrentAction(); World getWorld(); @@ -42,4 +47,9 @@ public interface ControllableUnit { CPU getCpu(); void giveItem(Item item); + + Point getFrontTile(); + + void setDirection(Direction direction); } + diff --git a/Server/src/main/resources/config.properties b/Server/src/main/resources/config.properties index dc7fd82..40806f5 100644 --- a/Server/src/main/resources/config.properties +++ b/Server/src/main/resources/config.properties @@ -71,6 +71,7 @@ harvester_hp_max=100 harvester_regen=5 harvester_biomass_drop_count=8 radio_tower_range=3 +hacked_npc_mem_size=5120 #Vaults vault_door_open_time=4 min_electric_box_count=1 diff --git a/Server/src/main/resources/static/js/mar.js b/Server/src/main/resources/static/js/mar.js index 1c7ae54..610f2fb 100644 --- a/Server/src/main/resources/static/js/mar.js +++ b/Server/src/main/resources/static/js/mar.js @@ -830,6 +830,7 @@ var ObjectType; ObjectType["OBSTACLE"] = "net.simon987.npcplugin.Obstacle"; ObjectType["ELECTRIC_BOX"] = "net.simon987.npcplugin.ElectricBox"; ObjectType["PORTAL"] = "net.simon987.npcplugin.Portal"; + ObjectType["HACKED_NPC"] = "net.simon987.npcplugin.HackedNPC"; })(ObjectType || (ObjectType = {})); var ItemType; (function (ItemType) { @@ -873,6 +874,8 @@ var GameObject = (function (_super) { return new ElectricBox(json); case ObjectType.PORTAL: return new Portal(json); + case ObjectType.HACKED_NPC: + return new HackedNPC(json); default: return null; } @@ -917,7 +920,7 @@ var Cubot = (function (_super) { _this.heldItem = json.heldItem; _this.direction = json.direction; _this.action = json.action; - _this.energy = json.energy; + _this.energy = _this.getEnergy(json); _this.cubotSprite = mar.game.make.sprite(0, 0, "sheet", null); _this.cubotSprite.anchor.set(0.5, 0); _this.addChild(_this.cubotSprite); @@ -949,6 +952,10 @@ var Cubot = (function (_super) { _this.setShield(false); return _this; } + + Cubot.prototype.getEnergy = function (json) { + return json["net.simon987.cubotplugin.CubotBattery"].energy; + }; Cubot.prototype.setShield = function (shield) { this.shieldBackSprite.visible = shield; this.shieldFrontSprite.visible = shield; @@ -1012,7 +1019,7 @@ var Cubot = (function (_super) { console.log("Updating Cubot object"); } this.action = json.action; - this.energy = json.energy; + this.energy = this.getEnergy(json); this.direction = json.direction; this.shield = json.shield; this.createInventory([json.heldItem]); @@ -1207,6 +1214,13 @@ var HarvesterNPC = (function (_super) { break; } }; + HarvesterNPC.prototype.getEnergy = function (json) { + if (json.hasOwnProperty("net.simon987.npcplugin.NpcBattery")) { + return json["net.simon987.npcplugin.NpcBattery"].energy; + } else { + return 0; + } + }; HarvesterNPC.prototype.updateObject = function (json) { if (DEBUG) { console.log("Updating Harvester NPC object"); @@ -1226,6 +1240,28 @@ var HarvesterNPC = (function (_super) { }; return HarvesterNPC; }(Cubot)); +var HackedNPC = (function (_super) { + __extends(HackedNPC, _super); + + function HackedNPC(json) { + var _this = _super.call(this, json) || this; + _this.updateDirection(); + _this.setText("Hacked NPC"); + _this.text.visible = false; + _this.tint = 0xE040FB; + return _this; + } + + HackedNPC.prototype.updateObject = function (json) { + _super.prototype.updateObject.call(this, json); + var holoHw = json["net.simon987.cubotplugin.CubotHologram"]; + this.updateHologram(holoHw.mode, holoHw.color, holoHw.value, holoHw.string); + }; + HackedNPC.prototype.getEnergy = function (json) { + return json["net.simon987.npcplugin.NpcBattery"].energy; + }; + return HackedNPC; +}(HarvesterNPC)); var BiomassBlob = (function (_super) { __extends(BiomassBlob, _super); function BiomassBlob(json) { diff --git a/Server/src/main/typescript/GameObject.ts b/Server/src/main/typescript/GameObject.ts index f649d9a..ff106c1 100644 --- a/Server/src/main/typescript/GameObject.ts +++ b/Server/src/main/typescript/GameObject.ts @@ -7,7 +7,8 @@ enum ObjectType { VAULT_DOOR = "net.simon987.npcplugin.VaultDoor", OBSTACLE = "net.simon987.npcplugin.Obstacle", ELECTRIC_BOX = "net.simon987.npcplugin.ElectricBox", - PORTAL = "net.simon987.npcplugin.Portal" + PORTAL = "net.simon987.npcplugin.Portal", + HACKED_NPC = "net.simon987.npcplugin.HackedNPC" } enum ItemType { @@ -59,7 +60,6 @@ abstract class GameObject extends Phaser.Plugin.Isometric.IsoSprite { switch (json.t) { case ObjectType.CUBOT: return new Cubot(json); - case ObjectType.BIOMASS: return new BiomassBlob(json); case ObjectType.HARVESTER_NPC: @@ -76,6 +76,8 @@ abstract class GameObject extends Phaser.Plugin.Isometric.IsoSprite { return new ElectricBox(json); case ObjectType.PORTAL: return new Portal(json); + case ObjectType.HACKED_NPC: + return new HackedNPC(json); default: return null; @@ -155,7 +157,7 @@ class Cubot extends GameObject { this.heldItem = json.heldItem; this.direction = json.direction; this.action = json.action; - this.energy = json.energy; + this.energy = this.getEnergy(json); this.cubotSprite = mar.game.make.sprite(0, 0, "sheet", null); this.cubotSprite.anchor.set(0.5, 0); @@ -197,6 +199,10 @@ class Cubot extends GameObject { this.setShield(false); } + protected getEnergy(json): number { + return json["net.simon987.cubotplugin.CubotBattery"].energy + } + public setShield(shield: boolean) { this.shieldBackSprite.visible = shield; this.shieldFrontSprite.visible = shield; @@ -277,7 +283,7 @@ class Cubot extends GameObject { } this.action = json.action; - this.energy = json.energy; + this.energy = this.getEnergy(json); this.direction = json.direction; this.shield = json.shield; @@ -333,7 +339,7 @@ class Cubot extends GameObject { this.setShield(this.shield > 0) } - private updateHologram(holoMode: HologramMode, holoColor: number, holoValue: number, holoStr: string): void { + protected updateHologram(holoMode: HologramMode, holoColor: number, holoValue: number, holoStr: string): void { let fillColor: string = (holoColor & 0xFFFFFF).toString(16); fillColor = "#" + ("000000".substr(fillColor.length) + fillColor); @@ -548,6 +554,14 @@ class HarvesterNPC extends Cubot { } } + protected getEnergy(json): number { + if (json.hasOwnProperty("net.simon987.npcplugin.NpcBattery")) { + return json["net.simon987.npcplugin.NpcBattery"].energy; + } else { + return 0; + } + } + updateObject(json) { if (DEBUG) { console.log("Updating Harvester NPC object") @@ -578,6 +592,30 @@ class HarvesterNPC extends Cubot { } +class HackedNPC extends HarvesterNPC { + + constructor(json) { + super(json); + + this.updateDirection(); + this.setText("Hacked NPC"); + this.text.visible = false; + this.tint = 0xE040FB; + } + + updateObject(json) { + super.updateObject(json); + + let holoHw = json["net.simon987.cubotplugin.CubotHologram"]; + this.updateHologram(holoHw.mode, holoHw.color, holoHw.value, holoHw.string); + } + + protected getEnergy(json): number { + return json["net.simon987.npcplugin.NpcBattery"].energy + } + +} + class BiomassBlob extends GameObject {