Added basic Radio Tower functionality #32

Keypress buffer is cleared on code upload
This commit is contained in:
simon
2017-12-29 21:49:42 -05:00
parent 5afa767b4a
commit ef7f573256
15 changed files with 391 additions and 12 deletions

View File

@@ -124,7 +124,7 @@ public class Factory extends GameObject implements Updatable {
factory.setX((int) (long) json.get("x"));
factory.setY((int) (long) json.get("y"));
factory.tmpNpcArray = (Object[]) ((JSONArray) json.get("n")).toArray();
factory.tmpNpcArray = ((JSONArray) json.get("n")).toArray();
return factory;
}

View File

@@ -1,35 +1,65 @@
package net.simon987.npcplugin;
import net.simon987.npcplugin.event.CpuInitialisationListener;
import net.simon987.npcplugin.event.WorldCreationListener;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.game.GameObject;
import net.simon987.server.io.CpuHardwareDeserializer;
import net.simon987.server.io.GameObjectDeserializer;
import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.ServerPlugin;
import org.json.simple.JSONObject;
public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer {
import java.util.ArrayList;
public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer, CpuHardwareDeserializer {
/**
* Radio tower cache
*/
private static ArrayList<RadioTower> radioTowers;
@Override
public void init(ServerConfiguration configuration) {
listeners.add(new WorldCreationListener());
listeners.add(new CpuInitialisationListener());
radioTowers = new ArrayList<>(32);
LogManager.LOGGER.info("Initialised NPC plugin");
}
@Override
public GameObject deserializeObject(JSONObject object) {
public GameObject deserializeObject(JSONObject json) {
int objType = (int) (long) object.get("t");
int objType = (int) (long) json.get("t");
if (objType == HarvesterNPC.ID) {
return HarvesterNPC.deserialize(object);
return HarvesterNPC.deserialize(json);
} else if (objType == Factory.ID) {
return Factory.deserialise(object);
return Factory.deserialise(json);
} else if (objType == RadioTower.ID) {
return RadioTower.deserialize(json);
}
return null;
}
@Override
public CpuHardware deserializeHardware(JSONObject hwJson) {
int hwid = (int) (long) hwJson.get("hwid");
switch (hwid) {
case RadioReceiverHardware.HWID:
return RadioReceiverHardware.deserialize(hwJson);
}
return null;
}
public static ArrayList<RadioTower> getRadioTowers() {
return radioTowers;
}
}

View File

@@ -0,0 +1,78 @@
package net.simon987.npcplugin;
import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status;
import net.simon987.server.assembly.Util;
import net.simon987.server.game.Action;
import net.simon987.server.game.ControllableUnit;
import org.json.simple.JSONObject;
import java.util.ArrayList;
public class RadioReceiverHardware extends CpuHardware {
public static final char HWID = 0xC; //12
private static final int LISTEN = 1;
public static final int DEFAULT_ADDRESS = 0xC;
private ControllableUnit cubot;
public RadioReceiverHardware(ControllableUnit cubot) {
this.cubot = cubot;
}
@Override
public void handleInterrupt(Status status) {
int x = getCpu().getRegisterSet().getRegister("X").getValue();
int a = getCpu().getRegisterSet().getRegister("A").getValue();
if (a == LISTEN) {
//Find the nearest Radio Tower and query it
cubot.setAction(Action.LISTENING);
ArrayList<char[]> messages = new ArrayList<>(6);
ArrayList<RadioTower> towers = new ArrayList<>(NpcPlugin.getRadioTowers()); //Avoid ConcurrentModificationException
for (RadioTower tower : towers) {
if (Util.manhattanDist(tower.getX(), tower.getY(), cubot.getX(), cubot.getY()) <= RadioTower.MAX_RANGE) {
//Tower is in range
messages.addAll(tower.getMessages());
}
}
//Write messages to memory
int offset = 0;
for (char[] message : messages) {
getCpu().getMemory().write(x + offset, message, 0, message.length);
offset += message.length;
}
//Write the amount of messages received to B
getCpu().getRegisterSet().getRegister("B").setValue(messages.size());
}
}
@Override
public char getId() {
return HWID;
}
@Override
public JSONObject serialise() {
JSONObject json = new JSONObject();
json.put("hwid", (int) HWID);
json.put("cubot", cubot.getObjectId());
return json;
}
public static RadioReceiverHardware deserialize(JSONObject json) {
return new RadioReceiverHardware((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((int) (long) json.get("cubot")));
}
}

View File

@@ -1,4 +1,103 @@
package net.simon987.npcplugin;
public class RadioTower {
import net.simon987.server.game.GameObject;
import net.simon987.server.game.Programmable;
import net.simon987.server.game.Updatable;
import org.json.simple.JSONObject;
import java.awt.*;
import java.util.ArrayList;
public class RadioTower extends GameObject implements Programmable, Updatable {
private static final int MAP_INFO = 0x1000;
public static final int ID = 4;
public static final int MAX_RANGE = 3; //todo load from config
private static final int MAX_MESSAGES = 16;
@Override
public char getMapInfo() {
return MAP_INFO;
}
/**
* Messages from the current tick
*/
private ArrayList<char[]> messages = new ArrayList<>(4);
/**
* Messages from the last tick
*/
private ArrayList<char[]> lastMessages = new ArrayList<>(4);
@Override
public void update() {
lastMessages = new ArrayList<>(messages);
messages.clear();
}
@Override
public void sendMessage(char[] message) {
if (message.length < MAX_MESSAGES) {
messages.add(message);
}
}
@Override
public JSONObject serialise() {
JSONObject json = new JSONObject();
json.put("i", getObjectId());
json.put("x", getX());
json.put("y", getY());
json.put("t", ID);
return json;
}
public static RadioTower deserialize(JSONObject json) {
RadioTower tower = new RadioTower();
tower.setObjectId((long) json.get("i"));
tower.setX((int) (long) json.get("x"));
tower.setY((int) (long) json.get("y"));
NpcPlugin.getRadioTowers().add(tower);
return tower;
}
public ArrayList<char[]> getMessages() {
return lastMessages;
}
/**
* Get the first directly adjacent tile (starting east, going clockwise)
*/
public Point getAdjacentTile() {
if (!getWorld().isTileBlocked(getX() + 1, getY())) {
return new Point(getX() + 1, getY());
} else if (!getWorld().isTileBlocked(getX(), getY() + 1)) {
return new Point(getX(), getY() + 1);
} else if (!getWorld().isTileBlocked(getX() - 1, getY())) {
return new Point(getX() - 1, getY());
} else if (!getWorld().isTileBlocked(getX(), getY() - 1)) {
return new Point(getX(), getY() - 1);
} else {
return null;
}
}
}

View File

@@ -0,0 +1,27 @@
package net.simon987.npcplugin.event;
import net.simon987.npcplugin.RadioReceiverHardware;
import net.simon987.server.assembly.CPU;
import net.simon987.server.event.CpuInitialisationEvent;
import net.simon987.server.event.GameEvent;
import net.simon987.server.event.GameEventListener;
import net.simon987.server.user.User;
public class CpuInitialisationListener implements GameEventListener {
@Override
public Class getListenedEventType() {
return CpuInitialisationEvent.class;
}
@Override
public void handle(GameEvent event) {
CPU cpu = (CPU) event.getSource();
User user = ((CpuInitialisationEvent) event).getUser();
RadioReceiverHardware radioHw = new RadioReceiverHardware(user.getControlledUnit());
radioHw.setCpu(cpu);
cpu.attachHardware(radioHw, RadioReceiverHardware.DEFAULT_ADDRESS);
}
}

View File

@@ -1,6 +1,8 @@
package net.simon987.npcplugin.event;
import net.simon987.npcplugin.Factory;
import net.simon987.npcplugin.NpcPlugin;
import net.simon987.npcplugin.RadioTower;
import net.simon987.server.GameServer;
import net.simon987.server.event.GameEvent;
import net.simon987.server.event.GameEventListener;
@@ -8,6 +10,7 @@ import net.simon987.server.event.WorldGenerationEvent;
import net.simon987.server.game.World;
import net.simon987.server.logging.LogManager;
import java.awt.*;
import java.util.Random;
public class WorldCreationListener implements GameEventListener {
@@ -31,6 +34,7 @@ public class WorldCreationListener implements GameEventListener {
World world = ((WorldGenerationEvent) event).getWorld();
outerLoopFactory:
for (int x = 2; x < 12; x++) {
for (int y = 2; y < 12; y++) {
@@ -54,10 +58,40 @@ public class WorldCreationListener implements GameEventListener {
LogManager.LOGGER.info("Spawned Factory at (" + world.getX() + ", " + world.getY() +
") (" + x + ", " + y + ")");
break outerLoopFactory;
}
}
}
//Also spawn a radio tower in the same World
Point p = world.getRandomPassableTile();
if (p != null) {
while (p.x == 0 || p.x == World.WORLD_SIZE - 1 || p.y == World.WORLD_SIZE - 1 || p.y == 0) {
p = world.getRandomPassableTile();
if (p == null) {
//World is full
return;
}
}
RadioTower radioTower = new RadioTower();
radioTower.setWorld(world);
radioTower.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
radioTower.setX(p.x);
radioTower.setY(p.y);
if (radioTower.getAdjacentTile() != null) {
//Radio Tower has adjacent tiles
world.getGameObjects().add(radioTower);
world.incUpdatable(); //In case the Factory couldn't be spawned.
NpcPlugin.getRadioTowers().add(radioTower);
LogManager.LOGGER.info("Spawned RadioTower at (" + world.getX() + ", " + world.getY() +
") (" + p.x + ", " + p.y + ")");
}
}
}
}