Merge pull request #153 from simon987/spark

Moved frontend to main server application
This commit is contained in:
Simon Fortier 2018-05-11 21:13:01 -04:00 committed by GitHub
commit c5cb5df335
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
202 changed files with 163352 additions and 1111 deletions

View File

@ -1,7 +1,6 @@
FROM alpine:3.7 FROM maven:3.5-jdk-8
RUN apk add --no-cache maven openjdk8
COPY /. /app/ COPY /. /app/
WORKDIR /app WORKDIR /app
RUN mvn package \ RUN mvn package
&& cp Server/src/main/resources/config.properties /app/ WORKDIR /app/target
CMD ["java", "-jar", "/app/target/server-1.2a.jar"] CMD ["java", "-jar", "/app/target/server-1.4a.jar"]

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" /> <output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" /> <output-test url="file://$MODULE_DIR$/target/test-classes" />
@ -13,11 +18,38 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="Server" /> <orderEntry type="module" module-name="Server" />
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" /> <orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:3.7.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.7.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.13" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.21" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" /> <orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" /> <orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" /> <orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />

View File

@ -1,13 +1,12 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration; import net.simon987.server.ServerConfiguration;
import net.simon987.server.assembly.Memory; import net.simon987.server.assembly.Memory;
import net.simon987.server.game.*; import net.simon987.server.game.*;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.user.User; import net.simon987.server.user.User;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.awt.*; import java.awt.*;
@ -19,42 +18,160 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
private static final char MAP_INFO = 0x0080; private static final char MAP_INFO = 0x0080;
public static final int ID = 1; public static final int ID = 1;
/**
* Hologram value that is displayed
* <br>TODO: Move to CubotHologram class
*/
private int hologram = 0; private int hologram = 0;
/**
* Hologram string that is displayed
* <br>TODO: Move to CubotHologram class
*/
private String hologramString = ""; private String hologramString = "";
/**
* Hologram mode that was set during this tick
* <br>TODO: Move to CubotHologram class
*/
private HologramMode hologramMode = HologramMode.CLEARED; private HologramMode hologramMode = HologramMode.CLEARED;
/**
* Hologram mode at the end of the last tick
* <br>TODO: Move to CubotHologram class
*/
private HologramMode lastHologramMode = HologramMode.CLEARED; private HologramMode lastHologramMode = HologramMode.CLEARED;
/**
* Hologram color code. Format is handled by the client
* <br>TODO: Move to CubotHologram class
*/
private int hologramColor = 0; private int hologramColor = 0;
/** /**
* Hit points * Hit points
*/ */
private int hp; private int hp;
/**
* Maximum hit points
*/
private int maxHp; private int maxHp;
/**
* Shield points
*/
private int shield; private int shield;
/**
* Maximum shield points
*/
private int maxShield; private int maxShield;
/**
* Item ID of the current 'active' item
*/
private int heldItem; private int heldItem;
/**
* Action that was set during the current tick. It is set to IDLE by default
*/
private Action currentAction = Action.IDLE; private Action currentAction = Action.IDLE;
/**
* Action at the end of the last tick
*/
private Action lastAction = Action.IDLE; private Action lastAction = Action.IDLE;
/**
* Status bit field that was set during the current tick. It is set to 0 by default
* <br>See CubotStatus and addStatus() method
*/
private char currentStatus; private char currentStatus;
/**
* Status bit field at the end of the last tick
*/
private char lastStatus; private char lastStatus;
/**
* Buffer of keypress codes. It is not changed between ticks and it is reset when
* the player uploads their code
*/
private ArrayList<Integer> keyboardBuffer = new ArrayList<>(); private ArrayList<Integer> keyboardBuffer = new ArrayList<>();
/**
* Buffer of console messages (also called 'internal buffer') that was set during the current tick
*/
private ArrayList<char[]> consoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE); private ArrayList<char[]> consoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE);
/**
* Buffer of console messages (also called 'internal buffer') at the end of the last tick
*/
private ArrayList<char[]> lastConsoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE); private ArrayList<char[]> lastConsoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE);
/**
* Console mode that was set during the current tick. It is set to NORMAL by default
*/
private ConsoleMode consoleMode = ConsoleMode.NORMAL; private ConsoleMode consoleMode = ConsoleMode.NORMAL;
/**
* Console mode at the end of the last tick
*/
private ConsoleMode lastConsoleMode = ConsoleMode.NORMAL; private ConsoleMode lastConsoleMode = ConsoleMode.NORMAL;
/**
* User that controls this Cubot
*/
private User parent; private User parent;
/**
* Energy units in kJ
*/
private int energy; private int energy;
/**
* Maximum energy units in kJ
*/
private int maxEnergy; private int maxEnergy;
/**
* Solar panel multiplier
* <br>TODO: Set this constant in dimension
*/
private static final float SOLAR_PANEL_MULTIPLIER = 1; 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; private static final int CONSOLE_BUFFER_MAX_SIZE = 40;
/**
* Display mode of the hologram hardware
* <br>TODO: move this inside CubotHologram class
*/
public enum HologramMode {
/**
* Display nothing
*/
CLEARED,
/**
* Display value as hexadecimal in format 0x0000
*/
HEX,
/**
* Display string
*/
STRING,
/**
* Display value as decimal
*/
DEC
}
public enum ConsoleMode {
/**
* Used by the ComPort hardware - clears the console screen (client-side)
*/
CLEAR,
/**
* No specific client-side action
*/
NORMAL
}
public Cubot() { public Cubot() {
} }
@ -64,6 +181,9 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
return MAP_INFO; return MAP_INFO;
} }
/**
* Called every tick
*/
@Override @Override
public void update() { public void update() {
@ -130,8 +250,8 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("t", ID); dbObject.put("t", ID);
@ -155,7 +275,7 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
return dbObject; return dbObject;
} }
public static Cubot deserialize(DBObject obj) { public static Cubot deserialize(Document obj) {
Cubot cubot = new Cubot(); Cubot cubot = new Cubot();
cubot.setObjectId((long) obj.get("i")); cubot.setObjectId((long) obj.get("i"));
@ -173,7 +293,52 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
cubot.maxShield = config.getInt("cubot_max_shield"); cubot.maxShield = config.getInt("cubot_max_shield");
return cubot; return cubot;
}
/**
* Reset to 'factory settings', as it were when it was first created
*/
private void reset() {
setDead(false);
setHp(maxHp);
setShield(0);
setHeldItem(0);
setEnergy(maxEnergy);
clearKeyboardBuffer();
consoleMessagesBuffer.clear();
lastConsoleMessagesBuffer.clear();
hologramColor = 0;
currentStatus = 0;
lastStatus = 0;
addStatus(CubotStatus.FACTORY_NEW);
}
@Override
public boolean onDeadCallback() {
LogManager.LOGGER.info(getParent().getUsername() + "'s Cubot died");
reset();
//Teleport to spawn point
this.getWorld().removeObject(this);
this.getWorld().decUpdatable();
ServerConfiguration config = GameServer.INSTANCE.getConfig();
Random random = new Random();
int spawnX = config.getInt("new_user_worldX") + random.nextInt(5);
int spawnY = config.getInt("new_user_worldY") + random.nextInt(5);
String dimension = config.getString("new_user_dimension");
this.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true, dimension));
Point point = this.getWorld().getRandomPassableTile();
this.setX(point.x);
this.setY(point.y);
this.getWorld().addObject(this);
this.getWorld().incUpdatable();
return true;
} }
public void setHeldItem(int heldItem) { public void setHeldItem(int heldItem) {
@ -314,18 +479,6 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
this.hologramMode = hologramMode; this.hologramMode = hologramMode;
} }
public enum HologramMode {
CLEARED,
HEX,
STRING,
DEC
}
public enum ConsoleMode {
CLEAR,
NORMAL
}
@Override @Override
public void setAction(Action action) { public void setAction(Action action) {
currentAction = action; currentAction = action;
@ -373,6 +526,9 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
return lastStatus; return lastStatus;
} }
/**
* Currently has no effect
*/
@Override @Override
public void setHealRate(int hp) { public void setHealRate(int hp) {
//no op //no op
@ -398,6 +554,13 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
this.maxHp = hp; this.maxHp = hp;
} }
public int getMaxShield() {
return maxShield;
}
public void setMaxShield(int maxShield) {
this.maxShield = maxShield;
}
@Override @Override
public void heal(int amount) { public void heal(int amount) {
hp += amount; hp += amount;
@ -420,55 +583,4 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
setDead(true); setDead(true);
} }
} }
public void reset() {
setDead(false);
setHp(maxHp);
setShield(0);
setHeldItem(0);
setEnergy(maxEnergy);
clearKeyboardBuffer();
consoleMessagesBuffer.clear();
lastConsoleMessagesBuffer.clear();
hologramColor = 0;
currentStatus = 0;
lastStatus = 0;
addStatus(CubotStatus.FACTORY_NEW);
}
@Override
public boolean onDeadCallback() {
LogManager.LOGGER.info(getParent().getUsername() + "'s Cubot died");
reset();
//Teleport to spawn point
this.getWorld().removeObject(this);
this.getWorld().decUpdatable();
ServerConfiguration config = GameServer.INSTANCE.getConfig();
Random random = new Random();
int spawnX = config.getInt("new_user_worldX") + random.nextInt(5);
int spawnY = config.getInt("new_user_worldY") + random.nextInt(5);
String dimension = config.getString("new_user_dimension");
this.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true, dimension));
Point point = this.getWorld().getRandomPassableTile();
this.setX(point.x);
this.setY(point.y);
this.getWorld().addObject(this);
this.getWorld().incUpdatable();
return true;
}
public int getMaxShield() {
return maxShield;
}
public void setMaxShield(int maxShield) {
this.maxShield = maxShield;
}
} }

View File

@ -1,10 +1,9 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import org.bson.Document;
public class CubotBattery extends CpuHardware { public class CubotBattery extends CpuHardware {
@ -45,9 +44,9 @@ public class CubotBattery extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -56,7 +55,7 @@ public class CubotBattery extends CpuHardware {
} }
public static CubotBattery deserialize(DBObject obj) { public static CubotBattery deserialize(Document obj) {
return new CubotBattery((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotBattery((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }

View File

@ -1,12 +1,11 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import net.simon987.server.game.Programmable; import net.simon987.server.game.Programmable;
import org.bson.Document;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
@ -128,9 +127,9 @@ public class CubotComPort extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -138,7 +137,7 @@ public class CubotComPort extends CpuHardware {
return dbObject; return dbObject;
} }
public static CubotComPort deserialize(DBObject obj) { public static CubotComPort deserialize(Document obj) {
return new CubotComPort((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotComPort((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,10 +1,9 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import org.bson.Document;
public class CubotCore extends CpuHardware { public class CubotCore extends CpuHardware {
@ -42,9 +41,9 @@ public class CubotCore extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -53,7 +52,7 @@ public class CubotCore extends CpuHardware {
} }
public static CubotCore deserialize(DBObject obj) { public static CubotCore deserialize(Document obj) {
return new CubotCore((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotCore((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,12 +1,11 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import net.simon987.server.game.Action; import net.simon987.server.game.Action;
import net.simon987.server.game.TileMap; import net.simon987.server.game.TileMap;
import org.bson.Document;
public class CubotDrill extends CpuHardware { public class CubotDrill extends CpuHardware {
@ -62,9 +61,9 @@ public class CubotDrill extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -72,7 +71,7 @@ public class CubotDrill extends CpuHardware {
return dbObject; return dbObject;
} }
public static CubotDrill deserialize(DBObject obj) { public static CubotDrill deserialize(Document obj) {
return new CubotDrill((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotDrill((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,10 +1,9 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import org.bson.Document;
public class CubotFloppyDrive extends CpuHardware { public class CubotFloppyDrive extends CpuHardware {
@ -79,9 +78,9 @@ public class CubotFloppyDrive extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -93,12 +92,12 @@ public class CubotFloppyDrive extends CpuHardware {
return dbObject; return dbObject;
} }
public static CubotFloppyDrive deserialize(DBObject obj) { public static CubotFloppyDrive deserialize(Document obj) {
CubotFloppyDrive drive = new CubotFloppyDrive((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); CubotFloppyDrive drive = new CubotFloppyDrive((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
if (obj.containsField("floppy")) { if (obj.containsKey("floppy")) {
drive.floppyDisk = FloppyDisk.deserialise((DBObject) obj.get("floppy")); drive.floppyDisk = FloppyDisk.deserialise((Document) obj.get("floppy"));
} }
return drive; return drive;

View File

@ -1,10 +1,9 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import org.bson.Document;
public class CubotHologram extends CpuHardware { public class CubotHologram extends CpuHardware {
@ -83,14 +82,14 @@ public class CubotHologram extends CpuHardware {
return HWID; return HWID;
} }
public static CubotHologram deserialize(DBObject obj) { public static CubotHologram deserialize(Document obj) {
return new CubotHologram((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotHologram((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());

View File

@ -1,10 +1,9 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import org.bson.Document;
public class CubotInventory extends CpuHardware { public class CubotInventory extends CpuHardware {
@ -52,9 +51,9 @@ public class CubotInventory extends CpuHardware {
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -62,7 +61,7 @@ public class CubotInventory extends CpuHardware {
return dbObject; return dbObject;
} }
public static CubotInventory deserialize(DBObject obj) { public static CubotInventory deserialize(Document obj) {
return new CubotInventory((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotInventory((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,10 +1,9 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import org.bson.Document;
public class CubotKeyboard extends CpuHardware { public class CubotKeyboard extends CpuHardware {
@ -53,9 +52,9 @@ public class CubotKeyboard extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -63,7 +62,7 @@ public class CubotKeyboard extends CpuHardware {
return dbObject; return dbObject;
} }
public static CubotKeyboard deserialize(DBObject obj) { public static CubotKeyboard deserialize(Document obj) {
return new CubotKeyboard((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotKeyboard((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,7 +1,5 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
@ -9,6 +7,7 @@ import net.simon987.server.game.Action;
import net.simon987.server.game.Attackable; import net.simon987.server.game.Attackable;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import net.simon987.server.game.InventoryHolder; import net.simon987.server.game.InventoryHolder;
import org.bson.Document;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
@ -93,9 +92,9 @@ public class CubotLaser extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -103,7 +102,7 @@ public class CubotLaser extends CpuHardware {
return dbObject; return dbObject;
} }
public static CubotLaser deserialize(DBObject obj) { public static CubotLaser deserialize(Document obj) {
return new CubotLaser((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotLaser((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,13 +1,12 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import net.simon987.server.game.Action; import net.simon987.server.game.Action;
import net.simon987.server.game.Direction; import net.simon987.server.game.Direction;
import net.simon987.server.io.JSONSerialisable; import net.simon987.server.io.JSONSerialisable;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
public class CubotLeg extends CpuHardware implements JSONSerialisable { public class CubotLeg extends CpuHardware implements JSONSerialisable {
@ -86,9 +85,9 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -96,7 +95,7 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable {
return dbObject; return dbObject;
} }
public static CubotLeg deserialize(DBObject obj) { public static CubotLeg deserialize(Document obj) {
return new CubotLeg((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotLeg((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }

View File

@ -1,7 +1,5 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Memory; import net.simon987.server.assembly.Memory;
@ -10,6 +8,7 @@ import net.simon987.server.game.pathfinding.Node;
import net.simon987.server.game.pathfinding.Pathfinder; import net.simon987.server.game.pathfinding.Pathfinder;
import net.simon987.server.io.JSONSerialisable; import net.simon987.server.io.JSONSerialisable;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
@ -150,9 +149,9 @@ public class CubotLidar extends CpuHardware implements JSONSerialisable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -160,7 +159,7 @@ public class CubotLidar extends CpuHardware implements JSONSerialisable {
return dbObject; return dbObject;
} }
public static CubotLidar deserialize(DBObject obj) { public static CubotLidar deserialize(Document obj) {
return new CubotLidar((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotLidar((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,6 +1,5 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.DBObject;
import net.simon987.cubotplugin.event.ChargeShieldCommandListener; import net.simon987.cubotplugin.event.ChargeShieldCommandListener;
import net.simon987.cubotplugin.event.CpuInitialisationListener; import net.simon987.cubotplugin.event.CpuInitialisationListener;
import net.simon987.cubotplugin.event.UserCreationListener; import net.simon987.cubotplugin.event.UserCreationListener;
@ -11,6 +10,7 @@ import net.simon987.server.io.CpuHardwareDeserializer;
import net.simon987.server.io.GameObjectDeserializer; import net.simon987.server.io.GameObjectDeserializer;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.ServerPlugin; import net.simon987.server.plugin.ServerPlugin;
import org.bson.Document;
public class CubotPlugin extends ServerPlugin implements GameObjectDeserializer, CpuHardwareDeserializer { public class CubotPlugin extends ServerPlugin implements GameObjectDeserializer, CpuHardwareDeserializer {
@ -25,7 +25,7 @@ public class CubotPlugin extends ServerPlugin implements GameObjectDeserializer,
} }
@Override @Override
public GameObject deserializeObject(DBObject object) { public GameObject deserializeObject(Document object) {
int objType = (int) object.get("t"); int objType = (int) object.get("t");
@ -38,7 +38,7 @@ public class CubotPlugin extends ServerPlugin implements GameObjectDeserializer,
} }
@Override @Override
public CpuHardware deserializeHardware(DBObject obj) { public CpuHardware deserializeHardware(Document obj) {
int hwid = (int) obj.get("hwid"); int hwid = (int) obj.get("hwid");
switch (hwid) { switch (hwid) {

View File

@ -1,10 +1,9 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import org.bson.Document;
public class CubotShield extends CpuHardware { public class CubotShield extends CpuHardware {
@ -28,8 +27,8 @@ public class CubotShield extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -50,7 +49,7 @@ public class CubotShield extends CpuHardware {
} }
} }
public static CubotShield deserialize(DBObject obj) { public static CubotShield deserialize(Document obj) {
return new CubotShield((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new CubotShield((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,17 +1,16 @@
package net.simon987.cubotplugin; package net.simon987.cubotplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.assembly.Memory; import net.simon987.server.assembly.Memory;
import net.simon987.server.io.MongoSerialisable; import net.simon987.server.io.MongoSerializable;
import org.bson.Document;
/** /**
* Represents a floppy disk that is inside a floppy drive. * Represents a floppy disk that is inside a floppy drive.
* Floppies contains 80 tracks with 18 sectors per track. * Floppies contains 80 tracks with 18 sectors per track.
* That's 1440 sectors of 512 words. (total 1,474,560 bytes / 737,280 words / 1.44Mb) * That's 1440 sectors of 512 words. (total 1,474,560 bytes / 737,280 words / 1.44Mb)
*/ */
public class FloppyDisk implements MongoSerialisable { public class FloppyDisk implements MongoSerializable {
/** /**
* Contents of the disk * Contents of the disk
@ -84,8 +83,8 @@ public class FloppyDisk implements MongoSerialisable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("rwHeadTrack", rwHeadTrack); dbObject.put("rwHeadTrack", rwHeadTrack);
dbObject.put("memory", memory.mongoSerialise()); dbObject.put("memory", memory.mongoSerialise());
@ -93,12 +92,12 @@ public class FloppyDisk implements MongoSerialisable {
return dbObject; return dbObject;
} }
public static FloppyDisk deserialise(DBObject obj) { public static FloppyDisk deserialise(Document obj) {
FloppyDisk floppyDisk = new FloppyDisk(); FloppyDisk floppyDisk = new FloppyDisk();
floppyDisk.rwHeadTrack = (int) obj.get("rwHeadTrack"); floppyDisk.rwHeadTrack = (int) obj.get("rwHeadTrack");
floppyDisk.memory = Memory.deserialize((DBObject) obj.get("memory")); floppyDisk.memory = Memory.deserialize((Document) obj.get("memory"));
return floppyDisk; return floppyDisk;
} }

View File

@ -7,6 +7,9 @@ import net.simon987.server.event.GameEvent;
import net.simon987.server.event.GameEventListener; import net.simon987.server.event.GameEventListener;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
/**
* Debug command to add shield points to a Cubot
*/
public class ChargeShieldCommandListener implements GameEventListener { public class ChargeShieldCommandListener implements GameEventListener {
@Override @Override
public Class getListenedEventType() { public Class getListenedEventType() {

View File

@ -15,7 +15,6 @@ public class CpuInitialisationListener implements GameEventListener {
@Override @Override
public void handle(GameEvent event) { public void handle(GameEvent event) {
//LogManager.LOGGER.fine("(Plugin) Handled CPU Initialisation event (Cubot Plugin)");
CPU cpu = (CPU) event.getSource(); CPU cpu = (CPU) event.getSource();
User user = ((CpuInitialisationEvent) event).getUser(); User user = ((CpuInitialisationEvent) event).getUser();

View File

@ -57,7 +57,5 @@ public class UserCreationListener implements GameEventListener {
user.setControlledUnit(cubot); user.setControlledUnit(cubot);
LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)"); LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)");
} }
} }

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" /> <output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" /> <output-test url="file://$MODULE_DIR$/target/test-classes" />
@ -12,11 +17,38 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="Server" /> <orderEntry type="module" module-name="Server" />
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" /> <orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:3.7.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.7.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.13" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.21" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" /> <orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" /> <orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" /> <orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />

View File

@ -1,11 +1,14 @@
package net.simon987.mischwplugin; package net.simon987.mischwplugin;
import com.mongodb.BasicDBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import net.simon987.server.assembly.Util; import net.simon987.server.assembly.Util;
import org.bson.Document;
/**
* Hardware to get game time
*/
public class Clock extends CpuHardware { public class Clock extends CpuHardware {
public static final char HWID = 0x0008; public static final char HWID = 0x0008;
@ -34,9 +37,9 @@ public class Clock extends CpuHardware {
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);

View File

@ -1,13 +1,16 @@
package net.simon987.mischwplugin; package net.simon987.mischwplugin;
import com.mongodb.DBObject;
import net.simon987.mischwplugin.event.CpuInitialisationListener; import net.simon987.mischwplugin.event.CpuInitialisationListener;
import net.simon987.server.ServerConfiguration; import net.simon987.server.ServerConfiguration;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.io.CpuHardwareDeserializer; import net.simon987.server.io.CpuHardwareDeserializer;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.ServerPlugin; import net.simon987.server.plugin.ServerPlugin;
import org.bson.Document;
/**
* Plugin that adds miscellaneous hardware to the game
*/
public class MiscHWPlugin extends ServerPlugin implements CpuHardwareDeserializer { public class MiscHWPlugin extends ServerPlugin implements CpuHardwareDeserializer {
@ -19,7 +22,7 @@ public class MiscHWPlugin extends ServerPlugin implements CpuHardwareDeserialize
} }
@Override @Override
public CpuHardware deserializeHardware(DBObject hwJson) { public CpuHardware deserializeHardware(Document hwJson) {
int hwid = (int) hwJson.get("hwid"); int hwid = (int) hwJson.get("hwid");
switch (hwid) { switch (hwid) {

View File

@ -1,11 +1,14 @@
package net.simon987.mischwplugin; package net.simon987.mischwplugin;
import com.mongodb.BasicDBObject;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import org.bson.Document;
import java.util.Random; import java.util.Random;
/**
* Hardware to generate random numbers
*/
public class RandomNumberGenerator extends CpuHardware { public class RandomNumberGenerator extends CpuHardware {
public static final char HWID = 0x0007; public static final char HWID = 0x0007;
@ -31,9 +34,9 @@ public class RandomNumberGenerator extends CpuHardware {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" /> <output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" /> <output-test url="file://$MODULE_DIR$/target/test-classes" />
@ -15,10 +20,37 @@
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" /> <orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" /> <orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
<orderEntry type="module" module-name="Server" /> <orderEntry type="module" module-name="Server" />
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" /> <orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:3.7.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.7.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.13" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.21" level="project" />
</component> </component>
</module> </module>

View File

@ -1,7 +1,5 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.Util; import net.simon987.server.assembly.Util;
import net.simon987.server.game.Attackable; import net.simon987.server.game.Attackable;
@ -9,28 +7,48 @@ import net.simon987.server.game.GameObject;
import net.simon987.server.game.Rechargeable; import net.simon987.server.game.Rechargeable;
import net.simon987.server.game.Updatable; import net.simon987.server.game.Updatable;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
/**
* Game object that deals damage to nearby objects and gives them energy
*/
public class ElectricBox extends GameObject implements Updatable, Attackable { public class ElectricBox extends GameObject implements Updatable, Attackable {
public static final int ID = 7; public static final int ID = 7;
/**
* Hit points
*/
private int hp;
/**
* Maximum hit points
*/
private static final int maxHp = GameServer.INSTANCE.getConfig().getInt("electric_box_hp"); private static final int maxHp = GameServer.INSTANCE.getConfig().getInt("electric_box_hp");
/**
* Number of hit points dealt to nearby objects each tick
*/
private static final int damageDealt = GameServer.INSTANCE.getConfig().getInt("electric_box_damage"); private static final int damageDealt = GameServer.INSTANCE.getConfig().getInt("electric_box_damage");
/**
* Number of energy points given to nearby objects each tick
*/
private static final int energyGiven = GameServer.INSTANCE.getConfig().getInt("electric_box_energy_given"); private static final int energyGiven = GameServer.INSTANCE.getConfig().getInt("electric_box_energy_given");
private int hp; /**
* List of nearby objects. Is updated every tick
*/
private ArrayList<Attackable> nearObjects = new ArrayList<>(); private ArrayList<Attackable> nearObjects = new ArrayList<>();
public ElectricBox() { public ElectricBox() {
this.hp = maxHp; this.hp = maxHp;
} }
/**
* Currently has no effect
*/
@Override @Override
public void setHealRate(int hp) { public void setHealRate(int hp) {
//no op //no op
@ -51,11 +69,17 @@ public class ElectricBox extends GameObject implements Updatable, Attackable {
return hp; return hp;
} }
/**
* Currently has no effect
*/
@Override @Override
public void setMaxHp(int hp) { public void setMaxHp(int hp) {
//No op //No op
} }
/**
* Currently has no effect
*/
@Override @Override
public void heal(int amount) { public void heal(int amount) {
//No op //No op
@ -77,6 +101,10 @@ public class ElectricBox extends GameObject implements Updatable, Attackable {
return Obstacle.MAP_INFO; return Obstacle.MAP_INFO;
} }
/**
* Updates the current list nearby objects
* <br>An object is considered 'nearby' if its Manhattan distance is {@literal <= @} 1 and is Attackable
*/
private void updateNearObjects() { private void updateNearObjects() {
nearObjects.clear(); nearObjects.clear();
@ -89,6 +117,9 @@ public class ElectricBox extends GameObject implements Updatable, Attackable {
} }
} }
/**
* Called every tick
*/
@Override @Override
public void update() { public void update() {
@ -118,8 +149,8 @@ public class ElectricBox extends GameObject implements Updatable, Attackable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("x", getX()); dbObject.put("x", getX());
@ -130,7 +161,7 @@ public class ElectricBox extends GameObject implements Updatable, Attackable {
return dbObject; return dbObject;
} }
public static ElectricBox deserialize(DBObject obj) { public static ElectricBox deserialize(Document obj) {
ElectricBox electricBox = new ElectricBox(); ElectricBox electricBox = new ElectricBox();
electricBox.setHp((int) obj.get("hp")); electricBox.setHp((int) obj.get("hp"));

View File

@ -1,25 +1,36 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import net.simon987.server.game.Updatable; import net.simon987.server.game.Updatable;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/**
* Game objects that regularly creates NonPlayerCharacters
*/
public class Factory extends GameObject implements Updatable { public class Factory extends GameObject implements Updatable {
private static final int MAP_INFO = 0x0200; private static final int MAP_INFO = 0x0200;
static final int ID = 3; static final int ID = 3;
/**
* Maximum number of NonPlayerCharacters assigned to this Factory
*/
private static final int MAX_NPC_COUNT = GameServer.INSTANCE.getConfig().getInt("factory_max_npc_count"); private static final int MAX_NPC_COUNT = GameServer.INSTANCE.getConfig().getInt("factory_max_npc_count");
/**
* Number of ticks to wait after creating a NonPlayerCharacter
*/
private static final int NPC_CREATION_COOLDOWN = NonPlayerCharacter.LIFETIME / MAX_NPC_COUNT; private static final int NPC_CREATION_COOLDOWN = NonPlayerCharacter.LIFETIME / MAX_NPC_COUNT;
/**
* List of associated NonPlayerCharacters
*/
private ArrayList<NonPlayerCharacter> npcs = new ArrayList<>(); private ArrayList<NonPlayerCharacter> npcs = new ArrayList<>();
/** /**
@ -43,6 +54,10 @@ public class Factory extends GameObject implements Updatable {
return MAP_INFO; return MAP_INFO;
} }
/**
* Called every tick
* <br>The fist time this is called, NPCs retrieved from the database are linked to the Factory
*/
@Override @Override
public void update() { public void update() {
@ -61,6 +76,8 @@ public class Factory extends GameObject implements Updatable {
} }
tmpNpcArray = null;
} else { } else {
if (cooldown == 0) { if (cooldown == 0) {
@ -115,15 +132,15 @@ public class Factory extends GameObject implements Updatable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("x", getX()); dbObject.put("x", getX());
dbObject.put("y", getY()); dbObject.put("y", getY());
dbObject.put("t", ID); dbObject.put("t", ID);
BasicDBList tmpNpcArray = new BasicDBList(); List<Long> tmpNpcArray = new ArrayList<>(npcs.size());
for (NonPlayerCharacter npc : npcs) { for (NonPlayerCharacter npc : npcs) {
tmpNpcArray.add(npc.getObjectId()); tmpNpcArray.add(npc.getObjectId());
@ -134,14 +151,14 @@ public class Factory extends GameObject implements Updatable {
return dbObject; return dbObject;
} }
public static Factory deserialise(DBObject obj) { public static Factory deserialise(Document obj) {
Factory factory = new Factory(); Factory factory = new Factory();
factory.setObjectId((long) obj.get("i")); factory.setObjectId((long) obj.get("i"));
factory.setX((int) obj.get("x")); factory.setX((int) obj.get("x"));
factory.setY((int) obj.get("y")); factory.setY((int) obj.get("y"));
factory.tmpNpcArray = ((BasicDBList) obj.get("n")).toArray(); factory.tmpNpcArray = ((ArrayList) obj.get("tmpNpcArray")).toArray();
return factory; return factory;
} }

View File

@ -10,19 +10,31 @@ import net.simon987.server.logging.LogManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Random; import java.util.Random;
/**
* Find Biomass, move towards it, collect it, repeat
*/
public class HarvestTask extends NPCTask { public class HarvestTask extends NPCTask {
private Random random; private Random random;
/**
* Number of ticks to wait before continuing
*/
private int pause; private int pause;
/**
* Direction of the next world to visit (randomly chosen)
*/
private Direction nextWorldDirection = null;
public HarvestTask() { public HarvestTask() {
random = new Random(); random = new Random();
pause = 0; pause = 0;
} }
private Direction nextWorldDirection = null; /**
* This task never finishes
*/
@Override @Override
public boolean checkCompleted() { public boolean checkCompleted() {
return false; return false;

View File

@ -1,10 +1,9 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.event.ObjectDeathEvent; import net.simon987.server.event.ObjectDeathEvent;
import net.simon987.server.game.Direction; import net.simon987.server.game.Direction;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
@ -12,6 +11,9 @@ public class HarvesterNPC extends NonPlayerCharacter {
public static final int ID = 10; public static final int ID = 10;
/**
*
*/
public static final int MAX_HEALTH = GameServer.INSTANCE.getConfig().getInt("harvester_hp_max"); public static final int MAX_HEALTH = GameServer.INSTANCE.getConfig().getInt("harvester_hp_max");
public static final int HEAL_RATE = GameServer.INSTANCE.getConfig().getInt("harvester_regen"); public static final int HEAL_RATE = GameServer.INSTANCE.getConfig().getInt("harvester_regen");
@ -77,22 +79,21 @@ public class HarvesterNPC extends NonPlayerCharacter {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("x", getX()); dbObject.put("x", getX());
dbObject.put("y", getY()); dbObject.put("y", getY());
dbObject.put("direction", getDirection().ordinal()); dbObject.put("direction", getDirection().ordinal());
dbObject.put("hp", getHp()); dbObject.put("hp", getHp());
// dbObject.put("energy", energy);
dbObject.put("action", getAction().ordinal()); dbObject.put("action", getAction().ordinal());
dbObject.put("t", ID); dbObject.put("t", ID);
return dbObject; return dbObject;
} }
public static HarvesterNPC deserialize(DBObject obj) { public static HarvesterNPC deserialize(Document obj) {
HarvesterNPC npc = new HarvesterNPC(); HarvesterNPC npc = new HarvesterNPC();
npc.setObjectId((long) obj.get("i")); npc.setObjectId((long) obj.get("i"));
@ -100,8 +101,6 @@ public class HarvesterNPC extends NonPlayerCharacter {
npc.setY((int) obj.get("y")); npc.setY((int) obj.get("y"));
npc.setHp((int) obj.get("hp")); npc.setHp((int) obj.get("hp"));
npc.setDirection(Direction.getDirection((int) obj.get("direction"))); npc.setDirection(Direction.getDirection((int) obj.get("direction")));
// npc.energy = (int) obj.get("energy");
// npc.maxEnergy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy");
return npc; return npc;

View File

@ -9,27 +9,40 @@ import net.simon987.server.logging.LogManager;
import java.util.ArrayList; import java.util.ArrayList;
/**
* Game object that actively interacts with the game world by doing tasks
*/
public abstract class NonPlayerCharacter extends GameObject implements Updatable, Attackable { public abstract class NonPlayerCharacter extends GameObject implements Updatable, Attackable {
private static final int MAP_INFO = 0x0040; private static final int MAP_INFO = 0x0040;
/**
* Maximum distance to travel from its factory, in Worlds
*/
private static final int MAX_FACTORY_DISTANCE = GameServer.INSTANCE.getConfig().getInt("npc_max_factory_distance"); private static final int MAX_FACTORY_DISTANCE = GameServer.INSTANCE.getConfig().getInt("npc_max_factory_distance");
/**
* Number of ticks to live
*/
public static final int LIFETIME = GameServer.INSTANCE.getConfig().getInt("npc_lifetime"); public static final int LIFETIME = GameServer.INSTANCE.getConfig().getInt("npc_lifetime");
// Set these just in case they aren't overridden in the subclass // Set these just in case they aren't overridden in the subclass
public static final int HP_MAX_DEFAULT = 100; public static final int HP_MAX_DEFAULT = 100;
public static final int HP_REGEN_RATE_DEFAULT = 0; public static final int HP_REGEN_RATE_DEFAULT = 0;
//Unused /**
* Currently unused
*/
int energy; int energy;
int maxEnergy;
/** /**
* Current task * Current task
*/ */
private NPCTask task; private NPCTask task;
/**
* Action at the end of the last tick
*/
private Action lastAction = Action.IDLE; private Action lastAction = Action.IDLE;
/** /**

View File

@ -1,10 +1,8 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.DBObject;
import net.simon987.npcplugin.event.CpuInitialisationListener; import net.simon987.npcplugin.event.CpuInitialisationListener;
import net.simon987.npcplugin.event.VaultWorldUpdateListener; import net.simon987.npcplugin.event.VaultWorldUpdateListener;
import net.simon987.npcplugin.event.WorldCreationListener; import net.simon987.npcplugin.event.WorldCreationListener;
import net.simon987.npcplugin.io.StatsDatabaseManager;
import net.simon987.server.ServerConfiguration; import net.simon987.server.ServerConfiguration;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
@ -12,6 +10,7 @@ import net.simon987.server.io.CpuHardwareDeserializer;
import net.simon987.server.io.GameObjectDeserializer; import net.simon987.server.io.GameObjectDeserializer;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.ServerPlugin; import net.simon987.server.plugin.ServerPlugin;
import org.bson.Document;
import java.util.ArrayList; import java.util.ArrayList;
@ -22,8 +21,6 @@ public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer, C
*/ */
private static ArrayList<RadioTower> radioTowers; private static ArrayList<RadioTower> radioTowers;
private static StatsDatabaseManager statsDbManager;
@Override @Override
public void init(ServerConfiguration configuration) { public void init(ServerConfiguration configuration) {
@ -33,13 +30,11 @@ public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer, C
radioTowers = new ArrayList<>(32); radioTowers = new ArrayList<>(32);
statsDbManager = new StatsDatabaseManager(configuration);
LogManager.LOGGER.info("Initialised NPC plugin"); LogManager.LOGGER.info("Initialised NPC plugin");
} }
@Override @Override
public GameObject deserializeObject(DBObject obj) { public GameObject deserializeObject(Document obj) {
int objType = (int) obj.get("t"); int objType = (int) obj.get("t");
@ -65,7 +60,7 @@ public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer, C
} }
@Override @Override
public CpuHardware deserializeHardware(DBObject obj) { public CpuHardware deserializeHardware(Document obj) {
int hwid = (int) obj.get("hwid"); int hwid = (int) obj.get("hwid");
switch (hwid) { switch (hwid) {
@ -80,7 +75,4 @@ public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer, C
return radioTowers; return radioTowers;
} }
public static StatsDatabaseManager getStatsDbManager() {
return statsDbManager;
}
} }

View File

@ -1,14 +1,12 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.game.Attackable; import net.simon987.server.game.Attackable;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
/** /**
* Generic game object that blocks the path. * Generic game object that blocks the path.
* Some types of obstacles might have some more interesting features (see ElectricBox)
*/ */
public class Obstacle extends GameObject implements Attackable { public class Obstacle extends GameObject implements Attackable {
@ -90,8 +88,8 @@ public class Obstacle extends GameObject implements Attackable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("x", getX()); dbObject.put("x", getX());
@ -117,7 +115,7 @@ public class Obstacle extends GameObject implements Attackable {
return json; return json;
} }
public static Obstacle deserialize(DBObject obj) { public static Obstacle deserialize(Document obj) {
Obstacle obstacle = new Obstacle((int) obj.get("hp")); Obstacle obstacle = new Obstacle((int) obj.get("hp"));
obstacle.setObjectId((long) obj.get("i")); obstacle.setObjectId((long) obj.get("i"));

View File

@ -1,23 +1,31 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.game.*; import net.simon987.server.game.*;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
public class Portal extends GameObject implements Enterable { public class Portal extends GameObject implements Enterable {
private Location dst; /**
* Destination location
*/
private Location destination;
public static final int MAP_INFO = 0x0020; public static final int MAP_INFO = 0x0020;
public static final int ID = 8; public static final int ID = 8;
/**
* Called when an object attempts to walk directly into a Enterable object
*
* @param object The game object that attempted to enter
* @return true if successful, false to block the object
*/
@Override @Override
public boolean enter(GameObject object) { public boolean enter(GameObject object) {
World world = GameServer.INSTANCE.getGameUniverse().getWorld(dst.worldX, dst.worldY, false, dst.dimension); World world = GameServer.INSTANCE.getGameUniverse().getWorld(destination.worldX, destination.worldY, false, destination.dimension);
if (object instanceof Updatable) { if (object instanceof Updatable) {
object.getWorld().decUpdatable(); object.getWorld().decUpdatable();
@ -27,8 +35,8 @@ public class Portal extends GameObject implements Enterable {
object.setWorld(world); object.setWorld(world);
world.addObject(object); world.addObject(object);
object.setX(dst.x); object.setX(destination.x);
object.setY(dst.y); object.setY(destination.y);
return true; return true;
} }
@ -39,27 +47,27 @@ public class Portal extends GameObject implements Enterable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("x", getX()); dbObject.put("x", getX());
dbObject.put("y", getY()); dbObject.put("y", getY());
dbObject.put("t", ID); dbObject.put("t", ID);
dbObject.put("dstWorldX", dst.worldX); dbObject.put("dstWorldX", destination.worldX);
dbObject.put("dstWorldY", dst.worldY); dbObject.put("dstWorldY", destination.worldY);
dbObject.put("dstX", dst.x); dbObject.put("dstX", destination.x);
dbObject.put("dstY", dst.y); dbObject.put("dstY", destination.y);
dbObject.put("dstDimension", dst.dimension); dbObject.put("dstDimension", destination.dimension);
return dbObject; return dbObject;
} }
public static Portal deserialize(DBObject obj) { public static Portal deserialize(Document obj) {
Portal portal = new Portal(); Portal portal = new Portal();
portal.dst = new Location( portal.destination = new Location(
(int) obj.get("dstWorldX"), (int) obj.get("dstWorldX"),
(int) obj.get("dstWorldY"), (int) obj.get("dstWorldY"),
(String) obj.get("dstDimension"), (String) obj.get("dstDimension"),
@ -83,11 +91,11 @@ public class Portal extends GameObject implements Enterable {
return json; return json;
} }
public Location getDst() { public Location getDestination() {
return dst; return destination;
} }
public void setDst(Location dst) { public void setDestination(Location destination) {
this.dst = dst; this.destination = destination;
} }
} }

View File

@ -1,13 +1,12 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import net.simon987.server.assembly.Status; import net.simon987.server.assembly.Status;
import net.simon987.server.assembly.Util; import net.simon987.server.assembly.Util;
import net.simon987.server.game.Action; import net.simon987.server.game.Action;
import net.simon987.server.game.ControllableUnit; import net.simon987.server.game.ControllableUnit;
import org.bson.Document;
import java.util.ArrayList; import java.util.ArrayList;
@ -67,9 +66,9 @@ public class RadioReceiverHardware extends CpuHardware {
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("hwid", (int) HWID); dbObject.put("hwid", (int) HWID);
dbObject.put("cubot", cubot.getObjectId()); dbObject.put("cubot", cubot.getObjectId());
@ -77,7 +76,7 @@ public class RadioReceiverHardware extends CpuHardware {
return dbObject; return dbObject;
} }
public static RadioReceiverHardware deserialize(DBObject obj) { public static RadioReceiverHardware deserialize(Document obj) {
return new RadioReceiverHardware((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot"))); return new RadioReceiverHardware((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
} }
} }

View File

@ -1,10 +1,9 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import net.simon987.server.game.Programmable; import net.simon987.server.game.Programmable;
import net.simon987.server.game.Updatable; import net.simon987.server.game.Updatable;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
@ -24,7 +23,6 @@ public class RadioTower extends GameObject implements Programmable, Updatable {
return MAP_INFO; return MAP_INFO;
} }
/** /**
* Messages from the current tick * Messages from the current tick
*/ */
@ -67,8 +65,8 @@ public class RadioTower extends GameObject implements Programmable, Updatable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("x", getX()); dbObject.put("x", getX());
@ -78,7 +76,7 @@ public class RadioTower extends GameObject implements Programmable, Updatable {
return dbObject; return dbObject;
} }
public static RadioTower deserialize(DBObject obj) { public static RadioTower deserialize(Document obj) {
RadioTower tower = new RadioTower(); RadioTower tower = new RadioTower();
tower.setObjectId((long) obj.get("i")); tower.setObjectId((long) obj.get("i"));

View File

@ -141,7 +141,7 @@ public class VaultDimension {
if (exitPortalPt != null) { if (exitPortalPt != null) {
VaultExitPortal exitPortal = new VaultExitPortal(); VaultExitPortal exitPortal = new VaultExitPortal();
exitPortal.setDst(exitLocation); exitPortal.setDestination(exitLocation);
exitPortal.setX(exitPortalPt.x); exitPortal.setX(exitPortalPt.x);
exitPortal.setY(exitPortalPt.y); exitPortal.setY(exitPortalPt.y);
exitPortal.setWorld(objectiveWorld); exitPortal.setWorld(objectiveWorld);
@ -158,7 +158,7 @@ public class VaultDimension {
if (homePortalPt != null) { if (homePortalPt != null) {
Portal homePortal = new Portal(); Portal homePortal = new Portal();
homePortal.setDst(exitLocation); homePortal.setDestination(exitLocation);
homePortal.setX(homePortalPt.x); homePortal.setX(homePortalPt.x);
homePortal.setY(homePortalPt.y); homePortal.setY(homePortalPt.y);
homePortal.setWorld(homeWorld); homePortal.setWorld(homeWorld);

View File

@ -1,11 +1,10 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.crypto.RandomStringGenerator; import net.simon987.server.crypto.RandomStringGenerator;
import net.simon987.server.game.*; import net.simon987.server.game.*;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.util.Arrays; import java.util.Arrays;
@ -124,8 +123,8 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("x", getX()); dbObject.put("x", getX());
@ -152,7 +151,7 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
return json; return json;
} }
public static VaultDoor deserialize(DBObject obj) { public static VaultDoor deserialize(Document obj) {
VaultDoor vaultDoor = new VaultDoor(0); //cypherId ? VaultDoor vaultDoor = new VaultDoor(0); //cypherId ?
vaultDoor.setX((int) obj.get("x")); vaultDoor.setX((int) obj.get("x"));
@ -160,7 +159,7 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
vaultDoor.setObjectId((long) obj.get("i")); vaultDoor.setObjectId((long) obj.get("i"));
if (obj.containsField("homeX") && obj.containsField("homeY")) { if (obj.containsKey("homeX") && obj.containsKey("homeY")) {
vaultDoor.setHomeX((int) obj.get("homeX")); vaultDoor.setHomeX((int) obj.get("homeX"));
vaultDoor.setHomeY((int) obj.get("homeY")); vaultDoor.setHomeY((int) obj.get("homeY"));
} }

View File

@ -1,11 +1,10 @@
package net.simon987.npcplugin; package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.game.ControllableUnit; import net.simon987.server.game.ControllableUnit;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import net.simon987.server.game.Location; import net.simon987.server.game.Location;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import org.bson.Document;
/** /**
* Final exit portal located in the 'last' World of a Vault dimension * Final exit portal located in the 'last' World of a Vault dimension
@ -15,18 +14,18 @@ public class VaultExitPortal extends Portal {
public static final int ID = 9; public static final int ID = 9;
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
dbObject.put("x", getX()); dbObject.put("x", getX());
dbObject.put("y", getY()); dbObject.put("y", getY());
dbObject.put("t", ID); dbObject.put("t", ID);
dbObject.put("dstWorldX", getDst().worldX); dbObject.put("dstWorldX", getDestination().worldX);
dbObject.put("dstWorldY", getDst().worldY); dbObject.put("dstWorldY", getDestination().worldY);
dbObject.put("dstX", getDst().x); dbObject.put("dstX", getDestination().x);
dbObject.put("dstY", getDst().y); dbObject.put("dstY", getDestination().y);
dbObject.put("dstDimension", getDst().dimension); dbObject.put("dstDimension", getDestination().dimension);
return dbObject; return dbObject;
} }
@ -34,20 +33,21 @@ public class VaultExitPortal extends Portal {
@Override @Override
public boolean enter(GameObject object) { public boolean enter(GameObject object) {
LogManager.LOGGER.info(((ControllableUnit) object).getParent().getUsername() + " Completed vault " + if (object instanceof ControllableUnit) {
object.getWorld().getDimension()); LogManager.LOGGER.info(((ControllableUnit) object).getParent().getUsername() + " Completed vault " +
object.getWorld().getDimension());
NpcPlugin.getStatsDbManager().saveVaultCompletion((ControllableUnit) object, object.getWorld().getDimension());
((ControllableUnit) object).getParent().getStats().addToStringSet("completedVaults", getWorld().getDimension());
}
return super.enter(object); return super.enter(object);
} }
public static Portal deserialize(DBObject obj) { public static Portal deserialize(Document obj) {
VaultExitPortal portal = new VaultExitPortal(); VaultExitPortal portal = new VaultExitPortal();
portal.setDst(new Location( portal.setDestination(new Location(
(int) obj.get("dstWorldX"), (int) obj.get("dstWorldX"),
(int) obj.get("dstWorldY"), (int) obj.get("dstWorldY"),
(String) obj.get("dstDimension"), (String) obj.get("dstDimension"),

View File

@ -14,11 +14,26 @@ import java.util.HashMap;
public class VaultWorldUpdateListener implements GameEventListener { public class VaultWorldUpdateListener implements GameEventListener {
/**
* Map of worlds and their time to wait until next respawn event
*/
private HashMap<World, Long> worldWaitMap = new HashMap<>(200); private HashMap<World, Long> worldWaitMap = new HashMap<>(200);
/**
* Lower bound of ElectricBox to be created on a respawn event
*/
private static int minElectricBoxCount; private static int minElectricBoxCount;
/**
* Upper bound of ElectricBox to be created on a respawn event
*/
private static int maxElectricBoxCount; private static int maxElectricBoxCount;
/**
* Number of game ticks to wait after the threshold has been met
*/
private static int waitTime; private static int waitTime;
/**
* Threshold before starting the
*/
private static int electricBoxThreshold; private static int electricBoxThreshold;
public VaultWorldUpdateListener(ServerConfiguration config) { public VaultWorldUpdateListener(ServerConfiguration config) {
@ -37,6 +52,7 @@ public class VaultWorldUpdateListener implements GameEventListener {
@Override @Override
public void handle(GameEvent event) { public void handle(GameEvent event) {
//TODO: Move this and the Biomass UpdateListener to a 'RespawnManager' kind of deal
World world = ((WorldUpdateEvent) event).getWorld(); World world = ((WorldUpdateEvent) event).getWorld();
if (world.getDimension().startsWith("v")) { if (world.getDimension().startsWith("v")) {
@ -66,6 +82,5 @@ public class VaultWorldUpdateListener implements GameEventListener {
} }
} }
} }
} }
} }

View File

@ -18,6 +18,7 @@ public class WorldCreationListener implements GameEventListener {
/** /**
* Spawn rate. Higher = rarer: A factory will be spawn about every FACTORY_SPAWN_RATE generated Worlds * Spawn rate. Higher = rarer: A factory will be spawn about every FACTORY_SPAWN_RATE generated Worlds
* <br>TODO: Get from config.properties
*/ */
private static final int FACTORY_SPAWN_RATE = 35; private static final int FACTORY_SPAWN_RATE = 35;

View File

@ -1,49 +0,0 @@
package net.simon987.npcplugin.io;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.game.ControllableUnit;
import net.simon987.server.io.DatabaseManager;
import net.simon987.server.logging.LogManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class StatsDatabaseManager extends DatabaseManager {
public StatsDatabaseManager(ServerConfiguration config) {
super(config);
}
public void saveVaultCompletion(ControllableUnit unit, String dimension) {
Connection connection = getConnection();
try {
PreparedStatement p = connection.prepareStatement("INSERT INTO mar_vault_clear " +
"(username, clear_time, vault_id) VALUES (?,?,?)");
p.setString(1, unit.getParent().getUsername());
p.setInt(2, 0);
p.setString(3, dimension);
int result = p.executeUpdate();
LogManager.LOGGER.fine("Saved vault clear (" + result + " rows changed)");
} catch (MySQLIntegrityConstraintViolationException e) {
LogManager.LOGGER.fine("This vault was already cleared by " + unit.getParent().getUsername());
} catch (SQLException e) {
LogManager.LOGGER.severe(e.getMessage());
e.printStackTrace();
} finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" /> <output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" /> <output-test url="file://$MODULE_DIR$/target/test-classes" />
@ -15,10 +20,37 @@
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" /> <orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" /> <orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
<orderEntry type="module" module-name="Server" /> <orderEntry type="module" module-name="Server" />
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" /> <orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:3.7.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.7.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.13" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.21" level="project" />
</component> </component>
</module> </module>

View File

@ -1,9 +1,8 @@
package net.simon987.biomassplugin; package net.simon987.biomassplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import net.simon987.server.game.InventoryHolder; import net.simon987.server.game.InventoryHolder;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
public class BiomassBlob extends GameObject implements InventoryHolder { public class BiomassBlob extends GameObject implements InventoryHolder {
@ -43,9 +42,9 @@ public class BiomassBlob extends GameObject implements InventoryHolder {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("t", ID); dbObject.put("t", ID);
dbObject.put("i", getObjectId()); dbObject.put("i", getObjectId());
@ -65,15 +64,8 @@ public class BiomassBlob extends GameObject implements InventoryHolder {
this.biomassCount = biomassCount; this.biomassCount = biomassCount;
} }
// public int getStyle() {
// return style;
// }
//
// public void setStyle(int style) {
// this.style = style;
// }
public static BiomassBlob deserialize(DBObject obj) { public static BiomassBlob deserialize(Document obj) {
BiomassBlob biomassBlob = new BiomassBlob(); BiomassBlob biomassBlob = new BiomassBlob();

View File

@ -1,6 +1,5 @@
package net.simon987.biomassplugin; package net.simon987.biomassplugin;
import com.mongodb.DBObject;
import net.simon987.biomassplugin.event.ObjectDeathListener; import net.simon987.biomassplugin.event.ObjectDeathListener;
import net.simon987.biomassplugin.event.WorldCreationListener; import net.simon987.biomassplugin.event.WorldCreationListener;
import net.simon987.biomassplugin.event.WorldUpdateListener; import net.simon987.biomassplugin.event.WorldUpdateListener;
@ -9,6 +8,8 @@ import net.simon987.server.game.GameObject;
import net.simon987.server.io.GameObjectDeserializer; import net.simon987.server.io.GameObjectDeserializer;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.ServerPlugin; import net.simon987.server.plugin.ServerPlugin;
import org.bson.Document;
public class BiomassPlugin extends ServerPlugin implements GameObjectDeserializer { public class BiomassPlugin extends ServerPlugin implements GameObjectDeserializer {
@ -23,7 +24,7 @@ public class BiomassPlugin extends ServerPlugin implements GameObjectDeserialize
} }
@Override @Override
public GameObject deserializeObject(DBObject object) { public GameObject deserializeObject(Document object) {
int objType = (int) object.get("t"); int objType = (int) object.get("t");

View File

@ -1,11 +1,11 @@
package net.simon987.pluginradioactivecloud; package net.simon987.pluginradioactivecloud;
import com.mongodb.DBObject;
import net.simon987.server.ServerConfiguration; import net.simon987.server.ServerConfiguration;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import net.simon987.server.io.GameObjectDeserializer; import net.simon987.server.io.GameObjectDeserializer;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.ServerPlugin; import net.simon987.server.plugin.ServerPlugin;
import org.bson.Document;
public class RadioactiveCloudPlugin extends ServerPlugin implements GameObjectDeserializer { public class RadioactiveCloudPlugin extends ServerPlugin implements GameObjectDeserializer {
@ -16,7 +16,7 @@ public class RadioactiveCloudPlugin extends ServerPlugin implements GameObjectDe
} }
@Override @Override
public GameObject deserializeObject(DBObject object) { public GameObject deserializeObject(Document object) {
return null; return null;
} }

View File

@ -1,4 +1,4 @@
# [Live demo](https://muchassemblyrequired.com) ### [Official website](https://muchassemblyrequired.com)
Program the 8086-like microprocessor of a robot in a grid-based multiplayer world. The game is web based so no installation is required. Program the 8086-like microprocessor of a robot in a grid-based multiplayer world. The game is web based so no installation is required.
In its current state, players can walk around the game universe and collect Biomass blobs & Iron/copper ore using the online code editor. In its current state, players can walk around the game universe and collect Biomass blobs & Iron/copper ore using the online code editor.
@ -7,19 +7,12 @@ In its current state, players can walk around the game universe and collect Biom
Wiki: [GitHub](https://github.com/simon987/Much-Assembly-Required/wiki) Wiki: [GitHub](https://github.com/simon987/Much-Assembly-Required/wiki)
Chat: [Slack](https://join.slack.com/t/muchassemblyrequired/shared_invite/enQtMjY3Mjc1OTUwNjEwLTkyOTIwOTA5OGY4MDVlMGI4NzM5YzlhMWJiMGY1OWE2NjUxODQ1NWQ1YTcxMTA1NGZkYzNjYzMyM2E1ODdmNzg) Chat: [Slack](https://join.slack.com/t/muchassemblyrequired/shared_invite/enQtMjY3Mjc1OTUwNjEwLTkyOTIwOTA5OGY4MDVlMGI4NzM5YzlhMWJiMGY1OWE2NjUxODQ1NWQ1YTcxMTA1NGZkYzNjYzMyM2E1ODdmNzg)
## VS Code Extensions
- [Much Assembly Required (Upload on Save)](https://marketplace.visualstudio.com/items?itemName=tomhodder.much-assembly-required-upload-on-save) by tomhodder
- [Much Assembly Required Language Support](https://marketplace.visualstudio.com/items?itemName=PJB3005.much-assembly-required-language-support) by PJB3005
# Deploying the server # Deploying the server
Note: You can find the frontend [here](https://github.com/simon987/Much-Assembly-Required-Frontend)
## Linux (Ubuntu 16.04) ## Linux (Ubuntu 16.04)
```bash ```bash
# Install tools # Install tools
sudo apt install git maven openjdk-8-jdk sudo apt install git maven openjdk-8-jdk mongodb
# Obtain source files # Obtain source files
git clone https://github.com/simon987/Much-Assembly-Required.git git clone https://github.com/simon987/Much-Assembly-Required.git
@ -30,7 +23,7 @@ mvn package
# Run # Run
cd target cd target
java -jar server-1.2a.jar java -jar server-1.4a.jar
``` ```
## Windows (tested on Windows 10) ## Windows (tested on Windows 10)
@ -61,10 +54,8 @@ mongod
```batch ```batch
:: Runs the MAR server :: Runs the MAR server
cd Much-Assembly-Required\target cd Much-Assembly-Required\target
java -jar server-1.2a.jar java -jar server-1.4a.jar
``` ```
3. Run the frontend, following the instructions that you can find [here](https://github.com/simon987/Much-Assembly-Required-Frontend).
## Docker ## Docker
### Requirements ### Requirements
@ -79,8 +70,12 @@ application's directory:
`docker-compose up` `docker-compose up`
This will start MySQL and then build and run this application. It will Make sure to change `mongo_address` in `config.properties` to `mongodb`.
be available via http://localhost.
Note that there is currently no frontend web application serving the # Running
WebSocket feed served by the `Server` application!
Once the server is running, you should be able to connect to `http://localhost:4567` with your browser
## VS Code Extensions
- [Much Assembly Required (Upload on Save)](https://marketplace.visualstudio.com/items?itemName=tomhodder.much-assembly-required-upload-on-save) by tomhodder
- [Much Assembly Required Language Support](https://marketplace.visualstudio.com/items?itemName=PJB3005.much-assembly-required-language-support) by PJB3005

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" /> <output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" /> <output-test url="file://$MODULE_DIR$/target/test-classes" />
@ -11,13 +16,40 @@
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" /> <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" /> <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" /> <orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" /> <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" /> <orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:3.7.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.7.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.13" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.21" level="project" />
</component> </component>
</module> </module>

View File

@ -24,10 +24,6 @@
<resources> <resources>
<resource> <resource>
<directory>../Server/src/main/resources</directory> <directory>../Server/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>config.properties</include>
</includes>
</resource> </resource>
</resources> </resources>
</configuration> </configuration>
@ -92,22 +88,12 @@
<version>1.4a</version> <version>1.4a</version>
<dependencies> <dependencies>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.6</version>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version> <version>4.12</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
</dependency>
<dependency> <dependency>
<groupId>com.googlecode.json-simple</groupId> <groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId> <artifactId>json-simple</artifactId>
@ -121,7 +107,27 @@
<dependency> <dependency>
<groupId>org.mongodb</groupId> <groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId> <artifactId>mongo-java-driver</artifactId>
<version>2.10.1</version> <version>3.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-template-velocity</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -1,8 +1,11 @@
package net.simon987.server; package net.simon987.server;
import com.mongodb.*; import com.mongodb.MongoClient;
import net.simon987.server.assembly.exception.CancelledException; import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.UpdateOptions;
import net.simon987.server.crypto.CryptoProvider; import net.simon987.server.crypto.CryptoProvider;
import net.simon987.server.event.GameEvent; import net.simon987.server.event.GameEvent;
import net.simon987.server.event.GameEventDispatcher; import net.simon987.server.event.GameEventDispatcher;
@ -14,10 +17,13 @@ import net.simon987.server.game.debug.*;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.PluginManager; import net.simon987.server.plugin.PluginManager;
import net.simon987.server.user.User; import net.simon987.server.user.User;
import net.simon987.server.webserver.SocketServer; import net.simon987.server.user.UserManager;
import net.simon987.server.user.UserStatsHelper;
import net.simon987.server.websocket.SocketServer;
import org.bson.Document;
import java.io.File; import java.io.File;
import java.net.UnknownHostException; import java.util.ArrayList;
public class GameServer implements Runnable { public class GameServer implements Runnable {
@ -39,15 +45,21 @@ public class GameServer implements Runnable {
private MongoClient mongo = null; private MongoClient mongo = null;
private UserManager userManager;
private UserStatsHelper userStatsHelper;
public GameServer() { public GameServer() {
this.config = new ServerConfiguration("config.properties"); this.config = new ServerConfiguration("config.properties");
try{ mongo = new MongoClient(config.getString("mongo_address"), config.getInt("mongo_port"));
mongo = new MongoClient("localhost", 27017); MongoDatabase db = mongo.getDatabase(config.getString("mongo_dbname"));
} catch (UnknownHostException e) {
e.printStackTrace(); MongoCollection<Document> userCollection = db.getCollection("user");
}
userManager = new UserManager(userCollection);
userStatsHelper = new UserStatsHelper(userCollection);
gameUniverse = new GameUniverse(config); gameUniverse = new GameUniverse(config);
gameUniverse.setMongo(mongo); gameUniverse.setMongo(mongo);
@ -69,7 +81,6 @@ public class GameServer implements Runnable {
if (pluginFile.getName().endsWith(".jar")) { if (pluginFile.getName().endsWith(".jar")) {
pluginManager.load(pluginFile, config); pluginManager.load(pluginFile, config);
} }
} }
} else { } else {
if (!pluginDir.mkdir()) { if (!pluginDir.mkdir()) {
@ -93,7 +104,7 @@ public class GameServer implements Runnable {
eventDispatcher.getListeners().add(new HealObjCommandListener()); eventDispatcher.getListeners().add(new HealObjCommandListener());
eventDispatcher.getListeners().add(new DamageObjCommandListener()); eventDispatcher.getListeners().add(new DamageObjCommandListener());
eventDispatcher.getListeners().add(new SetEnergyCommandListener()); eventDispatcher.getListeners().add(new SetEnergyCommandListener());
eventDispatcher.getListeners().add(new SaveGameCommandListener());
} }
public GameUniverse getGameUniverse() { public GameUniverse getGameUniverse() {
@ -127,7 +138,7 @@ public class GameServer implements Runnable {
uTime = System.currentTimeMillis() - startTime; uTime = System.currentTimeMillis() - startTime;
waitTime = config.getInt("tick_length") - uTime; waitTime = config.getInt("tick_length") - uTime;
LogManager.LOGGER.info("Wait time : " + waitTime + "ms | Update time: " + uTime + "ms | " + (int) (((double) uTime / waitTime) * 100) + "% load"); // LogManager.LOGGER.info("Wait time : " + waitTime + "ms | Update time: " + uTime + "ms | " + (int) (((double) uTime / waitTime) * 100) + "% load");
try { try {
if (waitTime >= 0) { if (waitTime >= 0) {
@ -136,10 +147,7 @@ public class GameServer implements Runnable {
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }
private void tick() { private void tick() {
@ -149,7 +157,6 @@ public class GameServer implements Runnable {
GameEvent event = new TickEvent(gameUniverse.getTime()); GameEvent event = new TickEvent(gameUniverse.getTime());
eventDispatcher.dispatch(event); //Ignore cancellation eventDispatcher.dispatch(event); //Ignore cancellation
//Process user code //Process user code
for (User user : gameUniverse.getUsers()) { for (User user : gameUniverse.getUsers()) {
@ -186,25 +193,22 @@ public class GameServer implements Runnable {
socketServer.tick(); socketServer.tick();
LogManager.LOGGER.info("Processed " + gameUniverse.getWorldCount() + " worlds (" + updatedWorlds + // LogManager.LOGGER.info("Processed " + gameUniverse.getWorldCount() + " worlds (" + updatedWorlds +
" updated)"); // " updated)");
} }
void load() { void load() {
LogManager.LOGGER.info("Loading all data from MongoDB"); LogManager.LOGGER.info("Loading all data from MongoDB");
DB db = mongo.getDB("mar"); MongoDatabase db = mongo.getDatabase(config.getString("mongo_dbname"));
DBCollection worlds = db.getCollection("world"); MongoCollection<Document> worlds = db.getCollection("world");
DBCollection users = db.getCollection("user"); MongoCollection<Document> server = db.getCollection("server");
DBCollection server = db.getCollection("server");
BasicDBObject whereQuery = new BasicDBObject(); Document whereQuery = new Document();
whereQuery.put("shouldUpdate", true); whereQuery.put("shouldUpdate", true);
DBCursor cursor = worlds.find(whereQuery); MongoCursor<Document> cursor = worlds.find(whereQuery).iterator();
GameUniverse universe = GameServer.INSTANCE.getGameUniverse(); GameUniverse universe = GameServer.INSTANCE.getGameUniverse();
while (cursor.hasNext()) { while (cursor.hasNext()) {
World w = World.deserialize(cursor.next()); World w = World.deserialize(cursor.next());
@ -212,19 +216,15 @@ public class GameServer implements Runnable {
} }
//Load users //Load users
cursor = users.find(); ArrayList<User> userList = userManager.getUsers();
while (cursor.hasNext()) { for (User user : userList) {
try { universe.addUser(user);
universe.addUser(User.deserialize(cursor.next()));
} catch (CancelledException e) {
e.printStackTrace();
}
} }
//Load misc server info //Load misc server info
cursor = server.find(); cursor = server.find().iterator();
if (cursor.hasNext()) { if (cursor.hasNext()) {
DBObject serverObj = cursor.next(); Document serverObj = cursor.next();
gameUniverse.setTime((long) serverObj.get("time")); gameUniverse.setTime((long) serverObj.get("time"));
gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId")); gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId"));
} }
@ -233,49 +233,47 @@ public class GameServer implements Runnable {
" | U:" + GameServer.INSTANCE.getGameUniverse().getUserCount()); " | U:" + GameServer.INSTANCE.getGameUniverse().getUserCount());
} }
private void save() { public void save() {
LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorldCount() + " | U:" + gameUniverse.getUserCount()); LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorldCount() + " | U:" + gameUniverse.getUserCount());
try{ try{
DB db = mongo.getDB("mar"); MongoDatabase db = mongo.getDatabase(config.getString("mongo_dbname"));
UpdateOptions updateOptions = new UpdateOptions();
updateOptions.upsert(true);
int unloaded_worlds = 0; int unloaded_worlds = 0;
DBCollection worlds = db.getCollection("world"); MongoCollection<Document> worlds = db.getCollection("world");
DBCollection users = db.getCollection("user"); MongoCollection<Document> users = db.getCollection("user");
DBCollection server = db.getCollection("server"); MongoCollection<Document> server = db.getCollection("server");
int insertedWorlds = 0; int insertedWorlds = 0;
GameUniverse universe = GameServer.INSTANCE.getGameUniverse(); GameUniverse universe = GameServer.INSTANCE.getGameUniverse();
for (World w : universe.getWorlds()) { for (World w : universe.getWorlds()) {
// LogManager.LOGGER.fine("Saving world "+w.getId()+" to mongodb");
insertedWorlds++; insertedWorlds++;
worlds.save(w.mongoSerialise()); worlds.replaceOne(new Document("_id", w.getId()), w.mongoSerialise(), updateOptions);
// If the world should unload, it is removed from the Universe after having been saved. //If the world should unload, it is removed from the Universe after having been saved.
if (w.shouldUnload()){ if (w.shouldUnload()){
unloaded_worlds++; unloaded_worlds++;
// LogManager.LOGGER.fine("Unloading world "+w.getId()+" from universe");
universe.removeWorld(w); universe.removeWorld(w);
} }
} }
for (User u : GameServer.INSTANCE.getGameUniverse().getUsers()) { for (User u : GameServer.INSTANCE.getGameUniverse().getUsers()) {
if (!u.isGuest()) { if (!u.isGuest()) {
users.save(u.mongoSerialise()); users.replaceOne(new Document("_id", u.getUsername()), u.mongoSerialise(), updateOptions);
} }
} }
BasicDBObject serverObj = new BasicDBObject(); Document serverObj = new Document();
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("time", gameUniverse.getTime());
serverObj.put("nextObjectId", gameUniverse.getNextObjectId()); serverObj.put("nextObjectId", gameUniverse.getNextObjectId());
server.save(serverObj); //A constant id ensures only one entry is kept and updated, instead of a new entry created every save.
server.replaceOne(new Document("_id", "serverinfo"), serverObj, updateOptions);
LogManager.LOGGER.info(""+insertedWorlds+" worlds saved, "+unloaded_worlds+" unloaded"); LogManager.LOGGER.info("" + insertedWorlds + " worlds saved, " + unloaded_worlds + " unloaded");
LogManager.LOGGER.info("Done!");
} catch (Exception e) { } catch (Exception e) {
LogManager.LOGGER.severe("Problem happened during save function"); LogManager.LOGGER.severe("Problem happened during save function");
e.printStackTrace(); e.printStackTrace();
@ -297,4 +295,12 @@ public class GameServer implements Runnable {
public DayNightCycle getDayNightCycle() { public DayNightCycle getDayNightCycle() {
return dayNightCycle; return dayNightCycle;
} }
public UserManager getUserManager() {
return userManager;
}
public UserStatsHelper getUserStatsHelper() {
return userStatsHelper;
}
} }

View File

@ -1,9 +1,8 @@
package net.simon987.server; package net.simon987.server;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.webserver.SocketServer; import net.simon987.server.web.WebServer;
import spark.Spark;
import java.net.InetSocketAddress;
public class Main { public class Main {
@ -12,15 +11,14 @@ public class Main {
ServerConfiguration config = new ServerConfiguration("config.properties"); ServerConfiguration config = new ServerConfiguration("config.properties");
LogManager.initialize(config); LogManager.initialize(config);
//Load
GameServer.INSTANCE.load(); GameServer.INSTANCE.load();
SocketServer socketServer = new SocketServer(new InetSocketAddress(config.getString("webSocket_host"), //Web server
config.getInt("webSocket_port")), config); WebServer webServer = new WebServer(GameServer.INSTANCE.getConfig());
GameServer.INSTANCE.setSocketServer(socketServer); Spark.awaitInitialization();
GameServer.INSTANCE.setSocketServer(webServer.getSocketServer());
(new Thread(socketServer)).start();
(new Thread(GameServer.INSTANCE)).start(); (new Thread(GameServer.INSTANCE)).start();
} }
} }

View File

@ -3,7 +3,6 @@ package net.simon987.server;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;

View File

@ -61,7 +61,7 @@ public class Assembler {
/** /**
* Check for and save the origin * Check for and save the origin
* *
* @param line Current line. Assuming that the comments & labels are removed * @param line Current line. Assuming that the comments and labels are removed
* @param result Current line number * @param result Current line number
*/ */
private static void checkForORGInstruction(String line, AssemblyResult result, int currentLine) private static void checkForORGInstruction(String line, AssemblyResult result, int currentLine)
@ -121,7 +121,7 @@ public class Assembler {
/** /**
* Parse the DW instruction (Define word). Handles DUP operator * Parse the DW instruction (Define word). Handles DUP operator
* *
* @param line Current line. assuming that comments & labels are removed * @param line Current line. assuming that comments and labels are removed
* @param currentLine Current line number * @param currentLine Current line number
* @param labels Map of labels * @param labels Map of labels
* @return Encoded instruction, null if the line is not a DW instruction * @return Encoded instruction, null if the line is not a DW instruction
@ -258,7 +258,7 @@ public class Assembler {
/** /**
* Parse the DW instruction (Define word). Handles DUP operator * Parse the DW instruction (Define word). Handles DUP operator
* *
* @param line Current line. assuming that comments & labels are removed * @param line Current line. assuming that comments and labels are removed
* @param currentLine Current line number * @param currentLine Current line number
* @return Encoded instruction, null if the line is not a DW instruction * @return Encoded instruction, null if the line is not a DW instruction
*/ */
@ -267,7 +267,7 @@ public class Assembler {
} }
/** /**
* Check for and handle section declarations (.text & .data) * Check for and handle section declarations (.text and .data)
* *
* @param line Current line * @param line Current line
*/ */

View File

@ -1,26 +1,26 @@
package net.simon987.server.assembly; package net.simon987.server.assembly;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration; import net.simon987.server.ServerConfiguration;
import net.simon987.server.assembly.exception.CancelledException; import net.simon987.server.assembly.exception.CancelledException;
import net.simon987.server.assembly.instruction.*; import net.simon987.server.assembly.instruction.*;
import net.simon987.server.event.CpuInitialisationEvent; import net.simon987.server.event.CpuInitialisationEvent;
import net.simon987.server.event.GameEvent; import net.simon987.server.event.GameEvent;
import net.simon987.server.io.MongoSerialisable; import net.simon987.server.io.MongoSerializable;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.user.User; import net.simon987.server.user.User;
import org.bson.Document;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
/** /**
* CPU: Central Processing Unit. A CPU is capable of reading bytes from * CPU: Central Processing Unit. A CPU is capable of reading bytes from
* a Memory object and execute them. A CPU object holds registers objects & * a Memory object and execute them. A CPU object holds registers objects and
* a Memory object. * a Memory object.
*/ */
public class CPU implements MongoSerialisable { public class CPU implements MongoSerializable {
/** /**
* *
@ -160,7 +160,7 @@ public class CPU implements MongoSerialisable {
} }
int elapsed = (int) (System.currentTimeMillis() - startTime); int elapsed = (int) (System.currentTimeMillis() - startTime);
LogManager.LOGGER.fine(counter + " instruction in " + elapsed + "ms : " + (double) counter / (elapsed / 1000) / 1000000 + "MHz"); // LogManager.LOGGER.fine(counter + " instruction in " + elapsed + "ms : " + (double) counter / (elapsed / 1000) / 1000000 + "MHz");
//Write execution cost and instruction count to memory //Write execution cost and instruction count to memory
@ -173,7 +173,6 @@ public class CPU implements MongoSerialisable {
public void executeInstruction(Instruction instruction, int source, int destination) { public void executeInstruction(Instruction instruction, int source, int destination) {
//Execute the instruction //Execute the instruction
if (source == 0) { if (source == 0) {
//No operand (assuming that destination is also null) //No operand (assuming that destination is also null)
@ -348,21 +347,21 @@ public class CPU implements MongoSerialisable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("memory", memory.mongoSerialise()); dbObject.put("memory", memory.mongoSerialise());
dbObject.put("registerSet", registerSet.mongoSerialise()); dbObject.put("registerSet", registerSet.mongoSerialise());
dbObject.put("codeSegmentOffset", codeSectionOffset); dbObject.put("codeSegmentOffset", codeSectionOffset);
BasicDBList hardwareList = new BasicDBList(); List<Document> hardwareList = new ArrayList<>();
for (Integer address : attachedHardware.keySet()) { for (Integer address : attachedHardware.keySet()) {
CpuHardware hardware = attachedHardware.get(address); CpuHardware hardware = attachedHardware.get(address);
BasicDBObject serialisedHw = hardware.mongoSerialise(); Document serialisedHw = hardware.mongoSerialise();
serialisedHw.put("address", address); serialisedHw.put("address", address);
hardwareList.add(serialisedHw); hardwareList.add(serialisedHw);
} }
@ -373,22 +372,22 @@ public class CPU implements MongoSerialisable {
} }
public static CPU deserialize(DBObject obj, User user) throws CancelledException { public static CPU deserialize(Document obj, User user) throws CancelledException {
CPU cpu = new CPU(GameServer.INSTANCE.getConfig(), user); CPU cpu = new CPU(GameServer.INSTANCE.getConfig(), user);
cpu.codeSectionOffset = (int) obj.get("codeSegmentOffset"); cpu.codeSectionOffset = (int) obj.get("codeSegmentOffset");
BasicDBList hardwareList = (BasicDBList) obj.get("hardware"); ArrayList hardwareList = (ArrayList) obj.get("hardware");
for (Object serialisedHw : hardwareList) { for (Object serialisedHw : hardwareList) {
CpuHardware hardware = CpuHardware.deserialize((DBObject) serialisedHw); CpuHardware hardware = CpuHardware.deserialize((Document) serialisedHw);
hardware.setCpu(cpu); hardware.setCpu(cpu);
cpu.attachHardware(hardware, (int) ((BasicDBObject) serialisedHw).get("address")); cpu.attachHardware(hardware, (int) ((Document) serialisedHw).get("address"));
} }
cpu.memory = Memory.deserialize((DBObject) obj.get("memory")); cpu.memory = Memory.deserialize((Document) obj.get("memory"));
cpu.registerSet = RegisterSet.deserialize((DBObject) obj.get("registerSet")); cpu.registerSet = RegisterSet.deserialize((Document) obj.get("registerSet"));
return cpu; return cpu;

View File

@ -1,13 +1,13 @@
package net.simon987.server.assembly; package net.simon987.server.assembly;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.io.CpuHardwareDeserializer; import net.simon987.server.io.CpuHardwareDeserializer;
import net.simon987.server.io.MongoSerialisable; import net.simon987.server.io.MongoSerializable;
import net.simon987.server.plugin.ServerPlugin; import net.simon987.server.plugin.ServerPlugin;
import org.bson.Document;
public abstract class CpuHardware implements MongoSerialisable { public abstract class CpuHardware implements MongoSerializable {
CPU cpu; CPU cpu;
@ -26,7 +26,7 @@ public abstract class CpuHardware implements MongoSerialisable {
public abstract char getId(); public abstract char getId();
public static CpuHardware deserialize(DBObject obj) { public static CpuHardware deserialize(Document obj) {
for (ServerPlugin plugin : GameServer.INSTANCE.getPluginManager().getPlugins()) { for (ServerPlugin plugin : GameServer.INSTANCE.getPluginManager().getPlugins()) {

View File

@ -1,11 +1,10 @@
package net.simon987.server.assembly; package net.simon987.server.assembly;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.io.MongoSerialisable; import net.simon987.server.io.MongoSerializable;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import org.bson.Document;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
@ -22,7 +21,7 @@ import java.util.zip.InflaterOutputStream;
/** /**
* Represents the available memory for a CPU in the game universe * Represents the available memory for a CPU in the game universe
*/ */
public class Memory implements Target, MongoSerialisable { public class Memory implements Target, MongoSerializable {
/** /**
@ -133,9 +132,9 @@ public class Memory implements Target, MongoSerialisable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
try { try {
ByteArrayOutputStream stream = new ByteArrayOutputStream(); ByteArrayOutputStream stream = new ByteArrayOutputStream();
@ -154,7 +153,7 @@ public class Memory implements Target, MongoSerialisable {
return dbObject; return dbObject;
} }
public static Memory deserialize(DBObject obj) { public static Memory deserialize(Document obj) {
Memory memory = new Memory(0); Memory memory = new Memory(0);

View File

@ -1,21 +1,20 @@
package net.simon987.server.assembly; package net.simon987.server.assembly;
import com.mongodb.BasicDBList; import net.simon987.server.io.MongoSerializable;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.io.MongoSerialisable;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import org.bson.Document;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
/** /**
* A set of registers for a CPU * A set of registers for a CPU
*/ */
public class RegisterSet implements Target, MongoSerialisable { public class RegisterSet implements Target, MongoSerializable {
/** /**
* List of registers * List of registers
@ -145,10 +144,10 @@ public class RegisterSet implements Target, MongoSerialisable {
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBList registers = new BasicDBList(); List<Document> registers = new ArrayList<>();
for (Integer index : this.registers.keySet()) { for (Integer index : this.registers.keySet()) {
JSONObject register = new JSONObject(); Document register = new Document();
register.put("index", index); register.put("index", index);
register.put("name", getRegister(index).getName()); register.put("name", getRegister(index).getName());
@ -157,24 +156,24 @@ public class RegisterSet implements Target, MongoSerialisable {
registers.add(register); registers.add(register);
} }
BasicDBObject obj = new BasicDBObject(); Document obj = new Document();
obj.put("registers", registers); obj.put("registers", registers);
return obj; return obj;
} }
public static RegisterSet deserialize(DBObject obj) { public static RegisterSet deserialize(Document obj) {
RegisterSet registerSet = new RegisterSet(); RegisterSet registerSet = new RegisterSet();
BasicDBList registers = (BasicDBList) obj.get("registers"); List registers = (ArrayList) obj.get("registers");
for (Object sRegister : registers) { for (Object sRegister : registers) {
Register register = new Register((String) ((DBObject) sRegister).get("name")); Register register = new Register((String) ((Document) sRegister).get("name"));
register.setValue((int) ((DBObject) sRegister).get("value")); register.setValue((int) ((Document) sRegister).get("value"));
registerSet.registers.put((int) ((DBObject) sRegister).get("index"), register); registerSet.registers.put((int) ((Document) sRegister).get("index"), register);
} }

View File

@ -7,10 +7,11 @@ import net.simon987.server.assembly.Util;
/** /**
* AND two numbers together, the result is stored in the destination operand * AND two numbers together, the result is stored in the destination operand
* <p> * <br>
* AND A, B * AND A, B
* A = A & B * <br>
* </p> * {@literal A = A & B @}
* <br>
* FLAGS: OF=0 S=* Z=* X=0 * FLAGS: OF=0 S=* Z=* X=0
*/ */
public class AndInstruction extends Instruction { public class AndInstruction extends Instruction {

View File

@ -6,9 +6,9 @@ import net.simon987.server.assembly.Status;
import net.simon987.server.assembly.Target; import net.simon987.server.assembly.Target;
/** /**
* Send hardware interupt * Send hardware interrupt
* Used to interact with the World using hardware * <br>Used to interact with the World using hardware
* </p> *
*/ */
public class HwiInstruction extends Instruction { public class HwiInstruction extends Instruction {

View File

@ -6,9 +6,9 @@ import net.simon987.server.assembly.Status;
import net.simon987.server.assembly.Target; import net.simon987.server.assembly.Target;
/** /**
* +---------------------+ *<br> +---------------------+
* | | *<br> | |
* CF < 0<0<0<0<0<0<0<0 <-+ *<br> {@literal CF < 0<0<0<0<0<0<0<0 <-+ @}
*/ */
public class RclInstruction extends Instruction { public class RclInstruction extends Instruction {

View File

@ -5,9 +5,9 @@ import net.simon987.server.assembly.Status;
import net.simon987.server.assembly.Target; import net.simon987.server.assembly.Target;
/** /**
* +---------------------+ * <br> +---------------------+
* | | * <br> | |
* CF < 0<0<0<0<0<0<0<0 <-+ * <br> {@literal CF < 0<0<0<0<0<0<0<0 <-+ @}
*/ */
public class RcrInstruction extends Instruction { public class RcrInstruction extends Instruction {

View File

@ -5,9 +5,9 @@ import net.simon987.server.assembly.Status;
import net.simon987.server.assembly.Target; import net.simon987.server.assembly.Target;
/** /**
* +-----------------+ * <br> +-----------------+
* | | * <br> | |
* CF < 0<0<0<0<0<0<0<0 <-+ * <br> {@literal CF < 0<0<0<0<0<0<0<0 <-+ @}
*/ */
public class RolInstruction extends Instruction { public class RolInstruction extends Instruction {

View File

@ -5,9 +5,9 @@ import net.simon987.server.assembly.Status;
import net.simon987.server.assembly.Target; import net.simon987.server.assembly.Target;
/** /**
* +-----------------+ * <br> +-----------------+
* | | * <br> | |
* +-> 0>0>0>0>0>0>0>0 > CF * <br> {@literal +-> 0>0>0>0>0>0>0>0 > CF @}
*/ */
public class RorInstruction extends Instruction { public class RorInstruction extends Instruction {

View File

@ -23,10 +23,10 @@ public class RandomStringGenerator {
return new String(buf); return new String(buf);
} }
public static final String UPPER_ALPHA_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static final String UPPER_ALPHA_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String LOWER_ALPHA_CHARSET = UPPER_ALPHA_CHARSET.toLowerCase(Locale.ROOT); static final String LOWER_ALPHA_CHARSET = UPPER_ALPHA_CHARSET.toLowerCase(Locale.ROOT);
public static final String NUMERIC_CHARSET = "0123456789"; static final String NUMERIC_CHARSET = "0123456789";
public static final String ALPHANUMERIC_CHARSET = UPPER_ALPHA_CHARSET + LOWER_ALPHA_CHARSET + NUMERIC_CHARSET; static final String ALPHANUMERIC_CHARSET = UPPER_ALPHA_CHARSET + LOWER_ALPHA_CHARSET + NUMERIC_CHARSET;
private final Random random; private final Random random;

View File

@ -1,8 +1,10 @@
package net.simon987.server.event; package net.simon987.server.event;
import net.simon987.server.webserver.OnlineUser; import net.simon987.server.websocket.OnlineUser;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.io.IOException;
public class DebugCommandEvent extends GameEvent { public class DebugCommandEvent extends GameEvent {
private JSONObject command; private JSONObject command;
@ -37,7 +39,11 @@ public class DebugCommandEvent extends GameEvent {
response.put("t", "debug"); response.put("t", "debug");
response.put("message", message); response.put("message", message);
((OnlineUser) getSource()).getWebSocket().send(response.toJSONString()); try {
((OnlineUser) getSource()).getWebSocket().getRemote().sendString(response.toJSONString());
} catch (IOException e) {
e.printStackTrace();
}
} }
} }

View File

@ -6,7 +6,7 @@ public interface Enterable {
* Called when an object attempts to walk directly into a Enterable object * Called when an object attempts to walk directly into a Enterable object
* *
* @param object The game object that attempted to enter * @param object The game object that attempted to enter
* @return true if successful, * @return true if successful, false to block the object
*/ */
boolean enter(GameObject object); boolean enter(GameObject object);

View File

@ -1,11 +1,11 @@
package net.simon987.server.game; package net.simon987.server.game;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.io.GameObjectDeserializer; import net.simon987.server.io.GameObjectDeserializer;
import net.simon987.server.io.JSONSerialisable; import net.simon987.server.io.JSONSerialisable;
import net.simon987.server.io.MongoSerialisable; import net.simon987.server.io.MongoSerializable;
import net.simon987.server.plugin.ServerPlugin; import net.simon987.server.plugin.ServerPlugin;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.awt.*; import java.awt.*;
@ -15,7 +15,7 @@ import java.util.ArrayList;
* An INSTANCE of an object (e.g. a Tree, a character ...) inside the * An INSTANCE of an object (e.g. a Tree, a character ...) inside the
* game universe * game universe
*/ */
public abstract class GameObject implements JSONSerialisable, MongoSerialisable { public abstract class GameObject implements JSONSerialisable, MongoSerializable {
private boolean dead; private boolean dead;
/** /**
@ -223,8 +223,8 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable
return new JSONObject(); return new JSONObject();
} }
public static GameObject deserialize(DBObject obj) { public static GameObject deserialize(Document obj) {
//
for (ServerPlugin plugin : GameServer.INSTANCE.getPluginManager().getPlugins()) { for (ServerPlugin plugin : GameServer.INSTANCE.getPluginManager().getPlugins()) {
if (plugin instanceof GameObjectDeserializer) { if (plugin instanceof GameObjectDeserializer) {

View File

@ -1,6 +1,9 @@
package net.simon987.server.game; package net.simon987.server.game;
import com.mongodb.*; import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration; import net.simon987.server.ServerConfiguration;
import net.simon987.server.assembly.Assembler; import net.simon987.server.assembly.Assembler;
@ -9,6 +12,7 @@ import net.simon987.server.assembly.CPU;
import net.simon987.server.assembly.exception.CancelledException; import net.simon987.server.assembly.exception.CancelledException;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import net.simon987.server.user.User; import net.simon987.server.user.User;
import org.bson.Document;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -56,12 +60,12 @@ public class GameUniverse {
*/ */
private World loadWorld(int x, int y, String dimension) { private World loadWorld(int x, int y, String dimension) {
DB db = mongo.getDB("mar"); MongoDatabase db = mongo.getDatabase(GameServer.INSTANCE.getConfig().getString("mongo_dbname"));
DBCollection worlds = db.getCollection("world"); MongoCollection<Document> worlds = db.getCollection("world");
BasicDBObject whereQuery = new BasicDBObject(); Document whereQuery = new Document();
whereQuery.put("_id", World.idFromCoordinates(x, y, dimension)); whereQuery.put("_id", World.idFromCoordinates(x, y, dimension));
DBCursor cursor = worlds.find(whereQuery); MongoCursor<Document> cursor = worlds.find(whereQuery).iterator();
if (cursor.hasNext()) { if (cursor.hasNext()) {
return World.deserialize(cursor.next()); return World.deserialize(cursor.next());
} }

View File

@ -0,0 +1,10 @@
package net.simon987.server.game;
//Alpha: ±5cm
//Beta: 10-20 feet
//Gamma: 100+ feet
public interface Radioactive {
}

View File

@ -1,16 +1,15 @@
package net.simon987.server.game; package net.simon987.server.game;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.io.JSONSerialisable; import net.simon987.server.io.JSONSerialisable;
import net.simon987.server.io.MongoSerialisable; import net.simon987.server.io.MongoSerializable;
import org.bson.Document;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.awt.*; import java.awt.*;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64; import java.util.Base64;
import java.util.Random; import java.util.Random;
import java.util.zip.Deflater; import java.util.zip.Deflater;
@ -19,7 +18,7 @@ import java.util.zip.DeflaterOutputStream;
/** /**
* A 2D map of Tile objects of size width*height * A 2D map of Tile objects of size width*height
*/ */
public class TileMap implements JSONSerialisable, MongoSerialisable { public class TileMap implements JSONSerialisable, MongoSerializable {
public static final int VOID = -1; public static final int VOID = -1;
public static final int PLAIN_TILE = 0; public static final int PLAIN_TILE = 0;
@ -141,25 +140,34 @@ public class TileMap implements JSONSerialisable, MongoSerialisable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
dbObject.put("tiles", tiles); //Flatten multi-dimensional array
ArrayList<Integer> bsonTiles = new ArrayList<>();
for (int x = 0; x < this.width; x++) {
for (int y = 0; y < this.height; y++) {
bsonTiles.add(tiles[x][y]);
}
}
dbObject.put("tiles", bsonTiles);
return dbObject; return dbObject;
} }
public static TileMap deserialize(DBObject object, int size) { public static TileMap deserialize(Document object, int size) {
BasicDBList terrain = (BasicDBList) object.get("tiles"); ArrayList<Integer> terrain = (ArrayList<Integer>) object.get("tiles");
int[][] tiles = new int[size][size]; int[][] tiles = new int[size][size];
for (int x = 0; x < size; x++) { for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) { for (int y = 0; y < size; y++) {
tiles[x][y] = (int) ((BasicDBList) terrain.get(x)).get(y); tiles[x][y] = terrain.get(x * size + y);
} }
} }

View File

@ -1,21 +1,20 @@
package net.simon987.server.game; package net.simon987.server.game;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.event.GameEvent; import net.simon987.server.event.GameEvent;
import net.simon987.server.event.WorldUpdateEvent; import net.simon987.server.event.WorldUpdateEvent;
import net.simon987.server.game.pathfinding.Pathfinder; import net.simon987.server.game.pathfinding.Pathfinder;
import net.simon987.server.io.MongoSerialisable; import net.simon987.server.io.MongoSerializable;
import org.bson.Document;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class World implements MongoSerialisable { public class World implements MongoSerializable {
/** /**
* Size of the side of this world * Size of the side of this world
@ -171,17 +170,15 @@ public class World implements MongoSerialisable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
BasicDBList objects = new BasicDBList(); List<Document> objects = new ArrayList<>();
for (GameObject obj : gameObjects.values()) { for (GameObject obj : gameObjects.values()) {
objects.add(obj.mongoSerialise()); objects.add(obj.mongoSerialise());
} }
dbObject.put("_id", getId());
dbObject.put("dimension", getDimension()); dbObject.put("dimension", getDimension());
dbObject.put("objects", objects); dbObject.put("objects", objects);
@ -214,7 +211,7 @@ public class World implements MongoSerialisable {
} }
public static World deserialize(DBObject dbObject) { public static World deserialize(Document dbObject) {
World world = new World((int) dbObject.get("size")); World world = new World((int) dbObject.get("size"));
world.x = (int) dbObject.get("x"); world.x = (int) dbObject.get("x");
@ -222,13 +219,13 @@ public class World implements MongoSerialisable {
world.dimension = (String) dbObject.get("dimension"); world.dimension = (String) dbObject.get("dimension");
world.updatable = (int) dbObject.get("updatable"); world.updatable = (int) dbObject.get("updatable");
world.tileMap = TileMap.deserialize((BasicDBObject) dbObject.get("terrain"), world.getWorldSize()); world.tileMap = TileMap.deserialize((Document) dbObject.get("terrain"), world.getWorldSize());
BasicDBList objects = (BasicDBList) dbObject.get("objects"); ArrayList<Document> objects = (ArrayList<Document>) dbObject.get("objects");
for (Object obj : objects) { for (Object obj : objects) {
GameObject object = GameObject.deserialize((DBObject) obj); GameObject object = GameObject.deserialize((Document) obj);
object.setWorld(world); object.setWorld(world);
world.addObject(object); world.addObject(object);

View File

@ -42,5 +42,4 @@ public class HealObjCommandListener implements GameEventListener {
} }
} }
} }
} }

View File

@ -0,0 +1,27 @@
package net.simon987.server.game.debug;
import net.simon987.server.GameServer;
import net.simon987.server.event.DebugCommandEvent;
import net.simon987.server.event.GameEvent;
import net.simon987.server.event.GameEventListener;
public class SaveGameCommandListener implements GameEventListener {
@Override
public Class getListenedEventType() {
return DebugCommandEvent.class;
}
@Override
public void handle(GameEvent event) {
DebugCommandEvent e = (DebugCommandEvent) event;
if (e.getName().equals("saveGame")) {
GameServer.INSTANCE.save();
e.reply("Saved the game");
}
}
}

View File

@ -1,13 +1,12 @@
package net.simon987.server.game.debug; package net.simon987.server.game.debug;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.event.DebugCommandEvent; import net.simon987.server.event.DebugCommandEvent;
import net.simon987.server.event.GameEvent; import net.simon987.server.event.GameEvent;
import net.simon987.server.event.GameEventListener; import net.simon987.server.event.GameEventListener;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import net.simon987.server.game.World; import net.simon987.server.game.World;
import org.bson.Document;
import java.util.Arrays; import java.util.Arrays;
@ -28,7 +27,7 @@ public class SpawnObjCommandListener implements GameEventListener {
World world = GameServer.INSTANCE.getGameUniverse().getWorld(e.getInt("worldX"), e.getInt("worldY"), World world = GameServer.INSTANCE.getGameUniverse().getWorld(e.getInt("worldX"), e.getInt("worldY"),
false, e.getString("dimension")); false, e.getString("dimension"));
DBObject dbObj = (DBObject) JSON.parse(e.getString("data")); Document dbObj = Document.parse(e.getString("data"));
dbObj.put("i", GameServer.INSTANCE.getGameUniverse().getNextObjectId()); dbObj.put("i", GameServer.INSTANCE.getGameUniverse().getNextObjectId());
GameObject object = GameObject.deserialize(dbObj); GameObject object = GameObject.deserialize(dbObj);

View File

@ -1,10 +1,10 @@
package net.simon987.server.io; package net.simon987.server.io;
import com.mongodb.DBObject;
import net.simon987.server.assembly.CpuHardware; import net.simon987.server.assembly.CpuHardware;
import org.bson.Document;
public interface CpuHardwareDeserializer { public interface CpuHardwareDeserializer {
CpuHardware deserializeHardware(DBObject hwJson); CpuHardware deserializeHardware(Document hwJson);
} }

View File

@ -1,10 +1,10 @@
package net.simon987.server.io; package net.simon987.server.io;
import com.mongodb.DBObject;
import net.simon987.server.game.GameObject; import net.simon987.server.game.GameObject;
import org.bson.Document;
public interface GameObjectDeserializer { public interface GameObjectDeserializer {
GameObject deserializeObject(DBObject object); GameObject deserializeObject(Document object);
} }

View File

@ -1,9 +0,0 @@
package net.simon987.server.io;
import com.mongodb.BasicDBObject;
public interface MongoSerialisable {
BasicDBObject mongoSerialise();
}

View File

@ -0,0 +1,9 @@
package net.simon987.server.io;
import org.bson.Document;
public interface MongoSerializable {
Document mongoSerialise();
}

View File

@ -0,0 +1,9 @@
package net.simon987.server.user;
public class RegistrationException extends Exception {
public RegistrationException(String message) {
super(message);
}
}

View File

@ -1,29 +1,33 @@
package net.simon987.server.user; package net.simon987.server.user;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer; import net.simon987.server.GameServer;
import net.simon987.server.assembly.CPU; import net.simon987.server.assembly.CPU;
import net.simon987.server.assembly.exception.CancelledException; import net.simon987.server.assembly.exception.CancelledException;
import net.simon987.server.event.GameEvent; import net.simon987.server.event.GameEvent;
import net.simon987.server.event.UserCreationEvent; import net.simon987.server.event.UserCreationEvent;
import net.simon987.server.game.ControllableUnit; import net.simon987.server.game.ControllableUnit;
import net.simon987.server.io.MongoSerialisable; import net.simon987.server.io.MongoSerializable;
import org.bson.Document;
/** /**
* Represents a User (or player) of the game * Represents a User (or player) of the game
*/ */
public class User implements MongoSerialisable { public class User implements MongoSerializable {
private String username; private String username;
private String userCode; private String userCode;
private String password;
private String accessToken;
private CPU cpu; private CPU cpu;
private ControllableUnit controlledUnit; private ControllableUnit controlledUnit;
private boolean guest; private boolean guest = false;
private boolean moderator = false;
private UserStats stats;
public User() throws CancelledException { public User() throws CancelledException {
GameEvent event = new UserCreationEvent(this); GameEvent event = new UserCreationEvent(this);
@ -32,7 +36,7 @@ public class User implements MongoSerialisable {
throw new CancelledException(); throw new CancelledException();
} }
this.stats = new UserStats();
} }
public User(ControllableUnit unit) { public User(ControllableUnit unit) {
@ -40,33 +44,38 @@ public class User implements MongoSerialisable {
} }
@Override @Override
public BasicDBObject mongoSerialise() { public Document mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject(); Document dbObject = new Document();
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("_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("username", username);
dbObject.put("code", userCode); dbObject.put("code", userCode);
dbObject.put("controlledUnit", controlledUnit.getObjectId()); dbObject.put("controlledUnit", controlledUnit.getObjectId());
dbObject.put("cpu", cpu.mongoSerialise()); dbObject.put("cpu", cpu.mongoSerialise());
dbObject.put("password", password);
dbObject.put("moderator", moderator);
dbObject.put("stats", stats.mongoSerialise());
return dbObject; return dbObject;
} }
public static User deserialize(DBObject obj) throws CancelledException { public static User deserialize(Document obj) throws CancelledException {
User user = new User((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("controlledUnit"))); User user = new User((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("controlledUnit")));
user.username = (String) obj.get("username"); user.username = (String) obj.get("username");
user.userCode = (String) obj.get("code"); user.userCode = (String) obj.get("code");
user.password = (String) obj.get("password");
user.moderator = (boolean) obj.get("moderator");
user.stats = new UserStats((Document) obj.get("stats"));
user.getControlledUnit().setParent(user); user.getControlledUnit().setParent(user);
user.cpu = CPU.deserialize((DBObject) obj.get("cpu"), user); user.cpu = CPU.deserialize((Document) obj.get("cpu"), user);
return user; return user;
} }
//----
public String getUserCode() { public String getUserCode() {
return userCode; return userCode;
@ -107,4 +116,28 @@ public class User implements MongoSerialisable {
public void setGuest(boolean guest) { public void setGuest(boolean guest) {
this.guest = guest; this.guest = guest;
} }
public void setPassword(String password) {
this.password = password;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public boolean isModerator() {
return moderator;
}
public void setModerator(boolean moderator) {
this.moderator = moderator;
}
public UserStats getStats() {
return stats;
}
} }

View File

@ -0,0 +1,161 @@
package net.simon987.server.user;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import net.simon987.server.GameServer;
import net.simon987.server.assembly.exception.CancelledException;
import net.simon987.server.crypto.RandomStringGenerator;
import net.simon987.server.logging.LogManager;
import org.bson.Document;
import org.springframework.security.crypto.bcrypt.BCrypt;
import java.util.ArrayList;
public class UserManager {
private MongoCollection<Document> userCollection;
public UserManager(MongoCollection<Document> userCollection) {
this.userCollection = userCollection;
}
/**
* Get and deserialise all users from mongo
*
* @return list of de-serialized users
*/
public ArrayList<User> getUsers() {
ArrayList<User> userList = new ArrayList<>();
MongoCursor<Document> cursor = userCollection.find().iterator();
while (cursor.hasNext()) {
try {
userList.add(User.deserialize(cursor.next()));
} catch (CancelledException e) {
e.printStackTrace();
}
}
return userList;
}
/**
* Register an user and initialises its controlled unit
* @param username username
* @param password plain password
* @throws RegistrationException is username/password length is invalid
*/
public void registerUser(String username, String password) throws RegistrationException {
if (username.length() < 5 || username.length() > 20) {
throw new RegistrationException("Username must be 5-20 characters");
}
if (password.length() < 8 || password.length() > 96) {
throw new RegistrationException("Password must be 8-96 characters");
}
//Check if exists
Document where = new Document();
where.put("_id", username);
if (userCollection.find(where).first() != null) {
throw new RegistrationException("Username is already in use");
}
try {
User user = GameServer.INSTANCE.getGameUniverse().getOrCreateUser(username, true);
user.setUsername(username);
String salt = BCrypt.gensalt();
String hashedPassword = BCrypt.hashpw(password, salt);
user.setPassword(hashedPassword);
Document dbUser = user.mongoSerialise();
userCollection.insertOne(dbUser);
} catch (Exception e) {
throw new RegistrationException("An exception occurred while trying to create user: " + e.getMessage());
}
}
/**
* Validate a username/password combo
* @param username username
* @param password plain password
* @return true if combo is valid
*/
public boolean validateUser(String username, String password) {
Document where = new Document();
where.put("_id", username);
Document user = userCollection.find(where).first();
return user != null && BCrypt.checkpw(password, (String) user.get("password"));
}
/**
* Change the password of an user and immediately save it
* @param username Username
* @param newPassword New plain password
* @throws RegistrationException When password length is invalid
*/
public void changePassword(String username, String newPassword) throws RegistrationException {
if (newPassword.length() < 8 || newPassword.length() > 96) {
throw new RegistrationException("Password must be 8-96 characters");
}
User user = GameServer.INSTANCE.getGameUniverse().getUser(username);
String salt = BCrypt.gensalt();
String hashedPassword = BCrypt.hashpw(newPassword, salt);
user.setPassword(hashedPassword);
userCollection.replaceOne(new Document("_id", username), user.mongoSerialise()); //Save new password immediately
}
/**
* Generate and save a access token for websocket auth
*
* @param username Username
* @return The generated token
*/
public String generateAndGetToken(String username) {
User user = GameServer.INSTANCE.getGameUniverse().getUser(username);
if (user == null) {
return null;
}
RandomStringGenerator generator = new RandomStringGenerator(128);
String token = generator.nextString();
user.setAccessToken(token); //Token is not saved in DB, and is erased when used
LogManager.LOGGER.fine("(Web) Generated access token for " + username);
return token;
}
/**
* Validate an access token sent by the client
* @param token 128-char accesss token
* @return username of the corresponding user, null if not found
*/
public User validateAuthToken(String token) {
for (User user : GameServer.INSTANCE.getGameUniverse().getUsers()) {
if (user.getAccessToken() != null && user.getAccessToken().equals(token)) {
user.setAccessToken(""); //Token is erased when used
return user;
}
}
return null;
}
}

View File

@ -0,0 +1,102 @@
package net.simon987.server.user;
import net.simon987.server.io.MongoSerializable;
import net.simon987.server.logging.LogManager;
import org.bson.Document;
import java.util.ArrayList;
public class UserStats implements MongoSerializable {
private Document stats;
UserStats() {
this.stats = new Document();
}
UserStats(Document stats) {
if (stats != null) {
this.stats = stats;
} else {
this.stats = new Document();
}
}
@Override
public Document mongoSerialise() {
return stats;
}
/**
* Increment a stat n times
*
* @param name Name of the stat to increment
* @param count Number of time to increment
*/
public void incrementStat(String name, int count) {
stats.putIfAbsent(name, 0);
stats.put(name, stats.getInteger(name) + count);
}
/**
* Set the value of a stat
*
* @param name Name of the stat
* @param value new value
*/
public void setInt(String name, int value) {
stats.put(name, value);
}
/**
* Get the value of at stat
*
* @param name Name of the value
* @return The value of the stat. Returns 0 if not found
*/
public int getInt(String name) {
return stats.getInteger(name, 0);
}
/**
* Add an string item to a set
*
* @param name Name of the stat
* @param value Value to add to the set
*/
public void addToStringSet(String name, String value) {
stats.putIfAbsent(name, new ArrayList<>());
try {
((ArrayList<String>) stats.get(name)).add(value);
} catch (ClassCastException e) {
LogManager.LOGGER.severe("UserStats: cannot add to list because stat already exists and is not a list");
}
}
/**
* Remove an item from a set
*
* @param name Name of the stat
* @param value Value to remove from the set
* @return true if the list contained the item
*/
public boolean removeFromSet(String name, String value) {
if (stats.putIfAbsent(name, new ArrayList()) != null) {
return ((ArrayList) stats.get(name)).remove(value);
}
return false;
}
public ArrayList getSet(String name) {
stats.putIfAbsent(name, new ArrayList());
return (ArrayList) stats.get(name);
}
}

View File

@ -0,0 +1,83 @@
package net.simon987.server.user;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import net.simon987.server.GameServer;
import org.bson.Document;
import java.util.*;
/**
* Retrieve user stats in a structured fashion
*/
public class UserStatsHelper {
/**
* Database collection of users
*/
private MongoCollection<Document> users;
/**
* @param users Database collection of users
*/
public UserStatsHelper(MongoCollection<Document> users) {
this.users = users;
}
/**
* Get top n players along with their stat value, in descending order
*
* @param statName Name of the stat
* @param n Maximum number of players
* @return Top n players, in User,value format, in descending order
*/
public ArrayList<Map.Entry<User, Integer>> getTopN(String statName, int n) {
ArrayList<Map.Entry<User, Integer>> rows = new ArrayList<>();
Document orderBy = new Document("$stats." + statName, -1);
MongoCursor<Document> cursor = users.find().sort(orderBy).limit(n).iterator();
while (cursor.hasNext()) {
Document dbUser = cursor.next();
User user = GameServer.INSTANCE.getGameUniverse().getUser((String) dbUser.get("username"));
rows.add(new AbstractMap.SimpleEntry<>(user, user.getStats().getInt(statName)));
}
return rows;
}
/**
* Get top n players along with the stat set, in descending order
*
* @param statName Name of the stat
* @param n Maximum number of players
* @return Top n players, in User,set format, in descending order
*/
public ArrayList<Map.Entry<User, ArrayList>> getTopNSetLength(String statName, int n) {
ArrayList<Map.Entry<User, ArrayList>> rows = new ArrayList<>();
List<Object> ifNullList = new ArrayList<>(2);
ifNullList.add("$stats." + statName);
ifNullList.add(new ArrayList());
Document project = new Document();
project.put("setLength", new Document("$size", new Document("$ifNull", ifNullList)));
project.put("username", 1);
Iterator<Document> results = users.aggregate(Arrays.asList(
new Document("$project", project),
new Document("$sort", new Document("setLength", -1)),
new Document("$limit", n))
).iterator();
while (results.hasNext()) {
User user = GameServer.INSTANCE.getGameUniverse().getUser((String) results.next().get("username"));
rows.add(new AbstractMap.SimpleEntry<>(user, user.getStats().getSet(statName)));
}
return rows;
}
}

View File

@ -0,0 +1,25 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.TemplateViewRoute;
import java.util.HashMap;
import java.util.Map;
public class AccountPage implements TemplateViewRoute {
@Override
public ModelAndView handle(Request request, Response response) {
Map<String, Object> model = new HashMap<>();
model.put("session", request.session());
if (request.session().attribute("username") != null) {
model.put("user", GameServer.INSTANCE.getGameUniverse().getUser(request.session().attribute("username")));
}
return new ModelAndView(model, "account.vm");
}
}

View File

@ -0,0 +1,20 @@
package net.simon987.server.web;
public class AlertMessage {
private String message;
private AlertType type;
public AlertMessage(String message, AlertType type) {
this.message = message;
this.type = type;
}
public String getMessage() {
return message;
}
public AlertType getType() {
return type;
}
}

View File

@ -0,0 +1,23 @@
package net.simon987.server.web;
public enum AlertType {
SUCCESS("alert-success"),
INFO("alert-info"),
WARNING("alert-info"),
DANGER("alert-danger"),
PRIMARY("alert-primary"),
SECONDARY("alert-secondary"),
DARK("alert-dark");
public String name;
AlertType(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}

View File

@ -0,0 +1,44 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import net.simon987.server.user.RegistrationException;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.Route;
public class ChangePasswordRoute implements Route {
@Override
public ModelAndView handle(Request request, Response response) {
String username = request.session().attribute("username");
String currentPassword = request.queryParams("password");
String newPassword = request.queryParams("new_password");
String newPasswordRepeat = request.queryParams("new_password_repeat");
if (newPassword.equals(newPasswordRepeat)) {
if (username != null && GameServer.INSTANCE.getUserManager().validateUser(username, currentPassword)) {
try {
GameServer.INSTANCE.getUserManager().changePassword(username, newPassword);
AlertMessage[] messages = {new AlertMessage("Changed password", AlertType.SUCCESS)};
request.session().attribute("messages", messages);
} catch (RegistrationException e) {
AlertMessage[] messages = {new AlertMessage(e.getMessage(), AlertType.DANGER)};
request.session().attribute("messages", messages);
}
} else {
AlertMessage[] messages = {new AlertMessage("Invalid password", AlertType.DANGER)};
request.session().attribute("messages", messages);
}
} else {
AlertMessage[] messages = {new AlertMessage("Passwords did not match", AlertType.DANGER)};
request.session().attribute("messages", messages);
}
response.redirect("/account");
return null;
}
}

View File

@ -0,0 +1,36 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import net.simon987.server.logging.LogManager;
import spark.Request;
import spark.Response;
import spark.Route;
public class FloppyDownloadRoute implements Route {
@Override
public Object handle(Request request, Response response) {
String username = request.session().attribute("username");
if (username != null) {
response.header("Content-Type", "application/octet-stream");
response.header("Content-Disposition", "filename=\"floppy.bin\"");
try {
return GameServer.INSTANCE.getGameUniverse().getUser(username).getControlledUnit().getFloppyData().getBytes();
} catch (Exception e) {
String message = "Encountered exception while reading floppy data: " + e.getMessage();
LogManager.LOGGER.severe(message);
return message;
}
} else {
response.status(403);
return "Not logged in";
}
}
}

View File

@ -0,0 +1,67 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import net.simon987.server.logging.LogManager;
import spark.Request;
import spark.Response;
import spark.Route;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.InputStream;
public class FloppyUploadRoute implements Route {
@Override
public Object handle(Request request, Response response) {
String username = request.session().attribute("username");
if (username != null) {
try {
request.attribute("org.eclipse.jetty.multipartConfig",
new MultipartConfigElement("/tmp_floppy", 1474560L, -1L, 0));
try (InputStream is = request.raw().getPart("floppyData").getInputStream()) {
if (is.available() == 1474560) {
byte[] bytes = new byte[1474560];
int bytesRead = is.read(bytes);
if (bytesRead == 1474560) {
try {
GameServer.INSTANCE.getGameUniverse().getUser(username).getControlledUnit().getFloppyData().setBytes(bytes);
return "ok";
} catch (Exception e) {
String message = "Encountered exception while writing floppy data: " + e.getMessage();
LogManager.LOGGER.severe(message);
return message;
}
} else {
return "Couldn't read floppy file";
}
} else {
return "File size must be 1474560 bytes";
}
} catch (IOException | ServletException e) {
e.printStackTrace();
return "Error reading floppy file: " + e.getMessage();
}
} catch (IllegalStateException e) {
return "File exceeds maximum size";
}
} else {
response.status(403);
return "Not logged in";
}
}
}

View File

@ -0,0 +1,21 @@
package net.simon987.server.web;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.TemplateViewRoute;
import java.util.HashMap;
import java.util.Map;
public class HomePage implements TemplateViewRoute {
@Override
public ModelAndView handle(Request request, Response response) throws Exception {
Map<String, Object> model = new HashMap<>(1);
model.put("session", request.session());
return new ModelAndView(model, "home.vm");
}
}

View File

@ -0,0 +1,21 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.TemplateViewRoute;
import java.util.HashMap;
import java.util.Map;
public class LeaderBoardPage implements TemplateViewRoute {
@Override
public ModelAndView handle(Request request, Response response) {
Map<String, Object> model = new HashMap<>(2);
model.put("session", request.session());
model.put("stats", GameServer.INSTANCE.getUserStatsHelper().getTopNSetLength("completedVaults", 25));
return new ModelAndView(model, "leaderboard.vm");
}
}

View File

@ -0,0 +1,32 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import net.simon987.server.logging.LogManager;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.Route;
public class LoginRoute implements Route {
@Override
public ModelAndView handle(Request request, Response response) {
String username = request.queryParams("username");
String password = request.queryParams("password");
if (username != null && password != null) {
if (GameServer.INSTANCE.getUserManager().validateUser(username, password)) {
AlertMessage[] messages = {new AlertMessage("Logged in as " + username, AlertType.SUCCESS)};
request.session().attribute("messages", messages);
request.session().attribute("username", username);
LogManager.LOGGER.fine("(Web) " + username + " logged in");
} else {
AlertMessage[] messages = {new AlertMessage("Invalid username or password", AlertType.DANGER)};
request.session().attribute("messages", messages);
}
}
response.redirect("/account");
return null;
}
}

View File

@ -0,0 +1,18 @@
package net.simon987.server.web;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.Route;
public class LogoutRoute implements Route {
@Override
public ModelAndView handle(Request request, Response response) {
AlertMessage[] messages = {new AlertMessage("Logged out", AlertType.INFO)};
request.session().attribute("messages", messages);
request.session().removeAttribute("username");
response.redirect("/account");
return null;
}
}

View File

@ -0,0 +1,20 @@
package net.simon987.server.web;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.TemplateViewRoute;
import java.util.HashMap;
import java.util.Map;
public class PlayPage implements TemplateViewRoute {
@Override
public ModelAndView handle(Request request, Response response) {
Map<String, Object> model = new HashMap<>(1);
model.put("session", request.session());
return new ModelAndView(model, "play.vm");
}
}

View File

@ -0,0 +1,36 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import net.simon987.server.logging.LogManager;
import net.simon987.server.user.RegistrationException;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
import spark.Route;
public class RegisterRoute implements Route {
@Override
public ModelAndView handle(Request request, Response response) {
String username = request.queryParams("username");
String password = request.queryParams("password");
if (username != null && password != null) {
try {
GameServer.INSTANCE.getUserManager().registerUser(username, password);
AlertMessage[] messages = {new AlertMessage("Successfully registered", AlertType.SUCCESS)};
request.session().attribute("messages", messages);
request.session().attribute("username", username);
LogManager.LOGGER.fine("(Web) " + username + " registered " + request.ip());
} catch (RegistrationException e) {
AlertMessage[] messages = {new AlertMessage(e.getMessage(), AlertType.DANGER)};
request.session().attribute("messages", messages);
}
}
response.redirect("/account");
return null;
}
}

View File

@ -0,0 +1,64 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import org.json.simple.JSONObject;
import spark.Request;
import spark.Response;
import spark.Route;
public class ServerInfoRoute implements Route {
private String address;
private String serverName;
private int tickLength;
public ServerInfoRoute() {
//Info variables that don't change
if (GameServer.INSTANCE.getConfig().getInt("use_ssl") == 0) {
address = "ws://" +
GameServer.INSTANCE.getConfig().getString("mar_address") + ":" +
GameServer.INSTANCE.getConfig().getString("mar_port") + "/socket";
} else {
address = "wss://" +
GameServer.INSTANCE.getConfig().getString("mar_address") + ":" +
GameServer.INSTANCE.getConfig().getString("mar_port") + "/socket";
}
serverName = GameServer.INSTANCE.getConfig().getString("server_name");
tickLength = GameServer.INSTANCE.getConfig().getInt("tick_length");
}
@Override
public Object handle(Request request, Response response) {
JSONObject json = new JSONObject();
String username = request.session().attribute("username");
if (username != null) {
String token = GameServer.INSTANCE.getUserManager().generateAndGetToken(username);
json.put("token", token);
json.put("username", username);
} else {
json.put("token",
"00000000000000000000000000000000" +
"00000000000000000000000000000000" +
"00000000000000000000000000000000" +
"00000000000000000000000000000000");
json.put("username", "guest");
}
json.put("address", address);
json.put("serverName", serverName);
json.put("tickLength", tickLength);
response.header("Content-Type", "application/json");
return json.toJSONString();
}
}

View File

@ -0,0 +1,63 @@
package net.simon987.server.web;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.logging.LogManager;
import net.simon987.server.websocket.SocketServer;
import org.apache.velocity.app.VelocityEngine;
import spark.Spark;
import spark.template.velocity.VelocityTemplateEngine;
import java.util.Properties;
public class WebServer {
private SocketServer socketServer;
public WebServer(ServerConfiguration config) {
//Velocity config
Properties properties = new Properties();
properties.setProperty("file.resource.loader.path", "templates/");
VelocityTemplateEngine templateEngine = new VelocityTemplateEngine(new VelocityEngine(properties));
Spark.staticFiles.externalLocation("static");
//Spark config
if (config.getInt("use_ssl") != 0) {
/*
* Generate keystore from Let's Encrypt with command:
* openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.jks -name muchassemblyrequired -CAfile chain.pem -caname root -password file:password.txt
*
* Certificates generated from Let's Encrypt are usually in /etc/letsencrypt/live/www.site.com
*/
Spark.secure(
config.getString("keyStore_path"),
config.getString("keyStore_password"), null, null);
LogManager.LOGGER.info("(Web) Enabled ssl");
}
socketServer = new SocketServer();
Spark.webSocket("/socket", socketServer);
Spark.get("/", new HomePage(), templateEngine);
Spark.get("/leaderboard", new LeaderBoardPage(), templateEngine);
Spark.get("/play", new PlayPage(), templateEngine);
Spark.get("/account", new AccountPage(), templateEngine);
Spark.post("/register", new RegisterRoute());
Spark.post("/login", new LoginRoute());
Spark.get("/logout", new LogoutRoute());
Spark.post("/change_password", new ChangePasswordRoute());
Spark.get("/server_info", new ServerInfoRoute());
Spark.post("/floppy_upload", new FloppyUploadRoute());
Spark.get("/floppy_download", new FloppyDownloadRoute());
Spark.after((request, response) -> response.header("Content-Encoding", "gzip"));
}
public SocketServer getSocketServer() {
return socketServer;
}
}

View File

@ -1,40 +0,0 @@
package net.simon987.server.webserver;
import net.simon987.server.GameServer;
import net.simon987.server.logging.LogManager;
import org.json.simple.JSONObject;
public class FloppyHandler implements MessageHandler {
SocketServerDatabase db = new SocketServerDatabase(GameServer.INSTANCE.getConfig());
@Override
public void handle(OnlineUser user, JSONObject json) {
if (json.get("t").equals("floppyDown")) {
LogManager.LOGGER.fine("(WS) Floppy download request from " + user.getUser().getUsername());
if (user.isGuest()) {
return;
}
if (user.getUser().getControlledUnit().getFloppyData() != null) {
byte[] bytes = user.getUser().getControlledUnit().getFloppyData().getBytes();
user.getWebSocket().send(bytes);
}
} else if (json.get("t").equals("floppyUp")) {
LogManager.LOGGER.fine("(WS) Floppy upload request from " + user.getUser().getUsername());
//Check newly uploaded file on the database
byte[] bytes = db.getFloppy(user.getUser().getUsername());
if (bytes != null) {
user.getUser().getControlledUnit().getFloppyData().setBytes(bytes);
}
}
}
}

View File

@ -1,10 +0,0 @@
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) throws WebsocketNotConnectedException;
}

View File

@ -1,323 +0,0 @@
package net.simon987.server.webserver;
import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.game.ControllableUnit;
import net.simon987.server.logging.LogManager;
import net.simon987.server.user.User;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.DefaultSSLWebSocketServerFactory;
import org.java_websocket.server.WebSocketServer;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
public class SocketServer extends WebSocketServer {
private OnlineUserManager userManager = new OnlineUserManager();
private SocketServerDatabase database;
private MessageDispatcher messageDispatcher = new MessageDispatcher();
public SocketServer(InetSocketAddress address, ServerConfiguration config) {
super(address);
if (config.getInt("use_secure_webSocket") != 0) {
SSLContext context = getContext(config.getString("cert_path"));
if (context != null) {
setWebSocketFactory(new DefaultSSLWebSocketServerFactory(context));
LogManager.LOGGER.info("(WS) Enabled secure webSocket");
} else {
LogManager.LOGGER.severe("(WS) Failed to create SSL context");
}
}
setConnectionLostTimeout(120);
setReuseAddr(true); //To avoid BindException
database = new SocketServerDatabase(config);
messageDispatcher.addHandler(new UserInfoRequestHandler());
messageDispatcher.addHandler(new TerrainRequestHandler());
messageDispatcher.addHandler(new ObjectsRequestHandler());
messageDispatcher.addHandler(new CodeUploadHandler());
messageDispatcher.addHandler(new CodeRequestHandler());
messageDispatcher.addHandler(new KeypressHandler());
messageDispatcher.addHandler(new FloppyHandler());
messageDispatcher.addHandler(new DebugCommandHandler());
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
LogManager.LOGGER.info("(WS) New Websocket connection " + conn.getRemoteSocketAddress());
userManager.add(new OnlineUser(conn));
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
LogManager.LOGGER.info("(WS) Closed " + conn.getRemoteSocketAddress() + " with exit code " + code + " additional info: " + reason);
userManager.remove(userManager.getUser(conn));
}
@Override
public void onMessage(WebSocket conn, String message) {
OnlineUser onlineUser = userManager.getUser(conn);
if (onlineUser != null) {
if (onlineUser.isAuthenticated()) {
messageDispatcher.dispatch(onlineUser, message);
} else {
LogManager.LOGGER.info("(WS) Received message from unauthenticated user " + conn.getRemoteSocketAddress());
//We expect a 128 characters long token
if (message.length() == 128) {
String username = database.validateAuthToken(message);
if (username != null) {
User user = GameServer.INSTANCE.getGameUniverse().getOrCreateUser(username, true);
onlineUser.setModerator(database.isModerator(username));
LogManager.LOGGER.info("(WS) User was successfully authenticated: " + user.getUsername() +
" moderator: " + onlineUser.isModerator());
onlineUser.setUser(user);
onlineUser.setAuthenticated(true);
conn.send("{\"t\":\"auth\", \"m\":\"ok\"}");
} else {
User user = GameServer.INSTANCE.getGameUniverse().getOrCreateUser(GameServer.INSTANCE.getGameUniverse().getGuestUsername(), false);
onlineUser.setUser(user);
onlineUser.setAuthenticated(true);
onlineUser.setGuest(true);
LogManager.LOGGER.info("(WS) Created guest user " +
onlineUser.getUser().getUsername() + conn.getRemoteSocketAddress());
conn.send("{\"t\":\"auth\", \"m\":\"ok\"}");
}
}
}
} else {
LogManager.LOGGER.severe("(WS) FIXME: SocketServer:onMessage");
}
}
@Override
public void onMessage(WebSocket conn, ByteBuffer message) {
//System.out.println("received ByteBuffer from " + conn.getRemoteSocketAddress());
}
@Override
public void onError(WebSocket conn, Exception ex) {
if (ex instanceof BindException) {
LogManager.LOGGER.severe("Address already in use");
System.exit(-1);
} else {
LogManager.LOGGER.severe("an error occurred on connection " + conn + ": " + ex);
userManager.remove(userManager.getUser(conn));
ex.printStackTrace();
}
}
@Override
public void onStart() {
LogManager.LOGGER.info("(WS) Server started successfully");
}
/**
* Called every tick
*/
public void tick() {
JSONObject json = new JSONObject();
json.put("t", "tick");
// LogManager.LOGGER.info("Notified " + userManager.getOnlineUsers().size() + " users");
ArrayList<OnlineUser> onlineUsers = new ArrayList<>(userManager.getOnlineUsers()); //Avoid ConcurrentModificationException
for (OnlineUser user : onlineUsers) {
if (user.getWebSocket().isOpen()) {
if (user.isGuest()) {
json.remove("c");
user.getWebSocket().send(json.toJSONString());
} else {
try {
ControllableUnit unit = user.getUser().getControlledUnit();
//Send keyboard updated buffer
ArrayList<Integer> kbBuffer = unit.getKeyboardBuffer();
JSONArray keys = new JSONArray();
keys.addAll(kbBuffer);
json.put("keys", keys);
//Send console buffer
if (unit.getConsoleMessagesBuffer().size() > 0) {
JSONArray buff = new JSONArray();
for (char[] message : unit.getConsoleMessagesBuffer()) {
buff.add(new String(message));
}
json.put("c", buff);
} else {
json.remove("c");
}
json.put("cm", unit.getConsoleMode());
//Send tick message
user.getWebSocket().send(json.toJSONString());
} catch (NullPointerException e) {
//User is online but not completely initialised
}
}
}
}
}
public OnlineUserManager getUserManager() {
return userManager;
}
/**
* See https://github.com/TooTallNate/Java-WebSocket/blob/master/src/main/example/SSLServerLetsEncryptExample.java
*/
/*
* * Copyright (c) 2010-2017 Nathan Rajlich
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
private static SSLContext getContext(String pathTo) {
SSLContext context;
String password = "MAR";
try {
context = SSLContext.getInstance("TLS");
byte[] certBytes = parseDERFromPEM(getBytes(new File(pathTo + File.separator + "cert.pem")),
"-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
byte[] keyBytes = parseDERFromPEM(getBytes(new File(pathTo + File.separator + "privkey.pem")),
"-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----");
X509Certificate cert = generateCertificateFromDER(certBytes);
RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null);
keystore.setCertificateEntry("cert-alias", cert);
keystore.setKeyEntry("key-alias", key, password.toCharArray(), new Certificate[]{cert});
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keystore, password.toCharArray());
KeyManager[] km = kmf.getKeyManagers();
context.init(km, null, null);
} catch (Exception e) {
context = null;
}
return context;
}
private static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
String data = new String(pem);
String[] tokens = data.split(beginDelimiter);
tokens = tokens[1].split(endDelimiter);
return DatatypeConverter.parseBase64Binary(tokens[0]);
}
private static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) factory.generatePrivate(spec);
}
private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
}
private static byte[] getBytes(File file) {
byte[] bytesArray = new byte[(int) file.length()];
FileInputStream fis;
try {
fis = new FileInputStream(file);
fis.read(bytesArray); //read file into bytes[]
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return bytesArray;
}
}

View File

@ -1,24 +1,26 @@
package net.simon987.server.webserver; package net.simon987.server.websocket;
import net.simon987.server.logging.LogManager; import net.simon987.server.logging.LogManager;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import java.io.IOException;
public class CodeRequestHandler implements MessageHandler { public class CodeRequestHandler implements MessageHandler {
@Override @Override
public void handle(OnlineUser user, JSONObject json) { public void handle(OnlineUser user, JSONObject json) throws IOException {
if (json.get("t").equals("codeRequest")) { if (json.get("t").equals("codeRequest")) {
LogManager.LOGGER.fine("(WS) Code request from " + user.getUser().getUsername()); LogManager.LOGGER.fine("(WS) Code request from " + user.getUser().getUsername());
if (user.isGuest()) { if (user.getUser().isGuest()) {
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
response.put("t", "code"); response.put("t", "code");
response.put("code", "; Create a free account to control your own Cubot with assembly language!"); //todo load from config response.put("code", "; Create a free account to control your own Cubot with assembly language!"); //todo load from config
user.getWebSocket().send(response.toJSONString()); user.getWebSocket().getRemote().sendString(response.toJSONString());
} else { } else {
@ -27,7 +29,7 @@ public class CodeRequestHandler implements MessageHandler {
response.put("t", "code"); response.put("t", "code");
response.put("code", user.getUser().getUserCode()); response.put("code", user.getUser().getUserCode());
user.getWebSocket().send(response.toJSONString()); user.getWebSocket().getRemote().sendString(response.toJSONString());
} }

Some files were not shown because too many files have changed in this diff Show More