mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-12-13 22:59:02 +00:00
Loading & Saving support for MongoDB
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package net.simon987.server;
|
||||
|
||||
|
||||
import com.mongodb.*;
|
||||
import net.simon987.server.assembly.exception.CancelledException;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.GameEventDispatcher;
|
||||
import net.simon987.server.event.TickEvent;
|
||||
@@ -10,23 +12,19 @@ import net.simon987.server.game.World;
|
||||
import net.simon987.server.io.FileUtils;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.plugin.PluginManager;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
import net.simon987.server.user.User;
|
||||
import net.simon987.server.webserver.SocketServer;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GameServer implements Runnable {
|
||||
|
||||
public final static GameServer INSTANCE = new GameServer();
|
||||
private final static String SAVE_JSON = "save.json";
|
||||
|
||||
private GameUniverse gameUniverse;
|
||||
|
||||
private GameUniverse gameUniverse;
|
||||
private GameEventDispatcher eventDispatcher;
|
||||
private PluginManager pluginManager;
|
||||
|
||||
@@ -157,13 +155,13 @@ public class GameServer implements Runnable {
|
||||
|
||||
//Save
|
||||
if (gameUniverse.getTime() % config.getInt("save_interval") == 0) {
|
||||
save(new File("save.json"));
|
||||
save();
|
||||
}
|
||||
|
||||
// Clean up history files
|
||||
if (gameUniverse.getTime() % config.getInt("clean_interval") == 0) {
|
||||
FileUtils.cleanHistory(config.getInt("history_size"));
|
||||
}
|
||||
|
||||
// Clean up history files
|
||||
if(gameUniverse.getTime() % config.getInt("clean_interval") == 0) {
|
||||
FileUtils.cleanHistory(config.getInt("history_size"));
|
||||
}
|
||||
|
||||
socketServer.tick();
|
||||
|
||||
@@ -171,47 +169,106 @@ public class GameServer implements Runnable {
|
||||
") updated");
|
||||
}
|
||||
|
||||
/**
|
||||
* Save game universe to file in JSON format
|
||||
*
|
||||
* @param file JSON file to save
|
||||
*/
|
||||
public void save(File file) {
|
||||
void load() {
|
||||
|
||||
boolean dirExists = FileUtils.prepDirectory(FileUtils.DIR_PATH);
|
||||
|
||||
if (new File(new File(SAVE_JSON).getAbsolutePath()).exists() && dirExists) {
|
||||
byte[] data = FileUtils.bytifyFile(new File(SAVE_JSON).toPath());
|
||||
try {
|
||||
FileUtils.writeSaveToZip(SAVE_JSON, data);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Failed to write " + SAVE_JSON + " to zip file");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.LOGGER.info("Loading from MongoDB");
|
||||
MongoClient mongo;
|
||||
try {
|
||||
FileWriter fileWriter = new FileWriter(file);
|
||||
mongo = new MongoClient("localhost", 27017);
|
||||
|
||||
JSONObject universe = gameUniverse.serialise();
|
||||
DB db = mongo.getDB("mar");
|
||||
|
||||
JSONArray plugins = new JSONArray();
|
||||
DBCollection worlds = db.getCollection("world");
|
||||
DBCollection users = db.getCollection("user");
|
||||
DBCollection server = db.getCollection("server");
|
||||
|
||||
for (ServerPlugin plugin : pluginManager.getPlugins()) {
|
||||
plugins.add(plugin.serialise());
|
||||
//Load worlds
|
||||
DBCursor cursor = worlds.find();
|
||||
while (cursor.hasNext()) {
|
||||
GameServer.INSTANCE.getGameUniverse().getWorlds().add(World.deserialize(cursor.next()));
|
||||
}
|
||||
|
||||
universe.put("plugins", plugins);
|
||||
//Load users
|
||||
cursor = users.find();
|
||||
while (cursor.hasNext()) {
|
||||
try {
|
||||
GameServer.INSTANCE.getGameUniverse().getUsers().add(User.deserialize(cursor.next()));
|
||||
} catch (CancelledException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
fileWriter.write(universe.toJSONString());
|
||||
fileWriter.close();
|
||||
//Load misc server info
|
||||
cursor = server.find();
|
||||
if (cursor.hasNext()) {
|
||||
DBObject serverObj = cursor.next();
|
||||
gameUniverse.setTime((long) serverObj.get("time"));
|
||||
gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId"));
|
||||
}
|
||||
|
||||
LogManager.LOGGER.info("Saved to file " + file.getName());
|
||||
|
||||
} catch (IOException e) {
|
||||
LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorlds().size() +
|
||||
" | U:" + GameServer.INSTANCE.getGameUniverse().getUsers().size());
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void save() {
|
||||
|
||||
LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorlds().size() + " | U:" + gameUniverse.getUsers().size());
|
||||
|
||||
MongoClient mongo;
|
||||
try {
|
||||
mongo = new MongoClient("localhost", 27017);
|
||||
|
||||
DB db = mongo.getDB("mar");
|
||||
|
||||
db.dropDatabase(); //Todo: Update database / keep history instead of overwriting
|
||||
|
||||
DBCollection worlds = db.getCollection("world");
|
||||
DBCollection users = db.getCollection("user");
|
||||
DBCollection server = db.getCollection("server");
|
||||
|
||||
List<DBObject> worldDocuments = new ArrayList<>();
|
||||
int perBatch = 35;
|
||||
int insertedWorlds = 0;
|
||||
ArrayList<World> worlds_ = new ArrayList<>(GameServer.INSTANCE.getGameUniverse().getWorlds());
|
||||
for (World w : worlds_) {
|
||||
worldDocuments.add(w.mongoSerialise());
|
||||
insertedWorlds++;
|
||||
|
||||
if (worldDocuments.size() >= perBatch || insertedWorlds >= GameServer.INSTANCE.getGameUniverse().getWorlds().size()) {
|
||||
worlds.insert(worldDocuments);
|
||||
worldDocuments.clear();
|
||||
}
|
||||
}
|
||||
|
||||
List<DBObject> userDocuments = new ArrayList<>();
|
||||
int insertedUsers = 0;
|
||||
ArrayList<User> users_ = new ArrayList<>(GameServer.INSTANCE.getGameUniverse().getUsers());
|
||||
for (User u : users_) {
|
||||
|
||||
insertedUsers++;
|
||||
|
||||
if (!u.isGuest()) {
|
||||
userDocuments.add(u.mongoSerialise());
|
||||
}
|
||||
|
||||
if (userDocuments.size() >= perBatch || insertedUsers >= GameServer.INSTANCE.getGameUniverse().getUsers().size()) {
|
||||
users.insert(userDocuments);
|
||||
userDocuments.clear();
|
||||
}
|
||||
}
|
||||
|
||||
BasicDBObject serverObj = new BasicDBObject();
|
||||
serverObj.put("time", gameUniverse.getTime());
|
||||
serverObj.put("nextObjectId", gameUniverse.getNextObjectId());
|
||||
server.insert(serverObj);
|
||||
|
||||
LogManager.LOGGER.info("Done!");
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ServerConfiguration getConfig() {
|
||||
|
||||
@@ -3,7 +3,6 @@ package net.simon987.server;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.webserver.SocketServer;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
|
||||
@@ -14,16 +13,13 @@ public class Main {
|
||||
LogManager.initialize();
|
||||
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||
//Load
|
||||
GameServer.INSTANCE.getGameUniverse().load(new File("save.json"));
|
||||
|
||||
GameServer.INSTANCE.load();
|
||||
|
||||
SocketServer socketServer = new SocketServer(new InetSocketAddress(config.getString("webSocket_host"),
|
||||
config.getInt("webSocket_port")), config);
|
||||
|
||||
GameServer.INSTANCE.setSocketServer(socketServer);
|
||||
|
||||
System.out.println(GameServer.INSTANCE.getGameUniverse().getWorld(0x7fff, 0x7fff));
|
||||
|
||||
(new Thread(socketServer)).start();
|
||||
(new Thread(GameServer.INSTANCE)).start();
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
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.ServerConfiguration;
|
||||
import net.simon987.server.assembly.exception.CancelledException;
|
||||
import net.simon987.server.assembly.instruction.*;
|
||||
import net.simon987.server.event.CpuInitialisationEvent;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import net.simon987.server.io.MongoSerialisable;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.user.User;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
@@ -20,7 +20,7 @@ import java.util.HashMap;
|
||||
* a Memory object and execute them. A CPU object holds registers objects &
|
||||
* a Memory object.
|
||||
*/
|
||||
public class CPU implements JSONSerialisable {
|
||||
public class CPU implements MongoSerialisable {
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -346,47 +346,47 @@ public class CPU implements JSONSerialisable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
public BasicDBObject mongoSerialise() {
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
dbObject.put("memory", memory.mongoSerialise());
|
||||
|
||||
json.put("memory", memory.serialise());
|
||||
dbObject.put("registerSet", registerSet.mongoSerialise());
|
||||
dbObject.put("codeSegmentOffset", codeSegmentOffset);
|
||||
|
||||
json.put("registerSet", registerSet.serialise());
|
||||
json.put("codeSegmentOffset", codeSegmentOffset);
|
||||
|
||||
JSONArray hardwareList = new JSONArray();
|
||||
BasicDBList hardwareList = new BasicDBList();
|
||||
|
||||
for (Integer address : attachedHardware.keySet()) {
|
||||
|
||||
CpuHardware hardware = attachedHardware.get(address);
|
||||
|
||||
JSONObject serialisedHw = hardware.serialise();
|
||||
BasicDBObject serialisedHw = hardware.mongoSerialise();
|
||||
serialisedHw.put("address", address);
|
||||
hardwareList.add(serialisedHw);
|
||||
}
|
||||
|
||||
json.put("hardware", hardwareList);
|
||||
dbObject.put("hardware", hardwareList);
|
||||
|
||||
return dbObject;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static CPU deserialize(JSONObject json, User user) throws CancelledException {
|
||||
public static CPU deserialize(DBObject obj, User user) throws CancelledException {
|
||||
|
||||
CPU cpu = new CPU(GameServer.INSTANCE.getConfig(), user);
|
||||
|
||||
cpu.codeSegmentOffset = (int) (long) json.get("codeSegmentOffset");
|
||||
cpu.codeSegmentOffset = (int) obj.get("codeSegmentOffset");
|
||||
|
||||
JSONArray hardwareList = (JSONArray) json.get("hardware");
|
||||
BasicDBList hardwareList = (BasicDBList) obj.get("hardware");
|
||||
|
||||
for (JSONObject serialisedHw : (ArrayList<JSONObject>) hardwareList) {
|
||||
CpuHardware hw = CpuHardware.deserialize(serialisedHw);
|
||||
hw.setCpu(cpu);
|
||||
cpu.attachHardware(hw, (int) (long) serialisedHw.get("address"));
|
||||
for (Object serialisedHw : hardwareList) {
|
||||
CpuHardware hardware = CpuHardware.deserialize((DBObject) serialisedHw);
|
||||
hardware.setCpu(cpu);
|
||||
cpu.attachHardware(hardware, (int) ((BasicDBObject) serialisedHw).get("address"));
|
||||
}
|
||||
|
||||
cpu.memory = Memory.deserialize((JSONObject) json.get("memory"));
|
||||
cpu.registerSet = RegisterSet.deserialize((JSONObject) json.get("registerSet"));
|
||||
cpu.memory = Memory.deserialize((DBObject) obj.get("memory"));
|
||||
cpu.registerSet = RegisterSet.deserialize((DBObject) obj.get("registerSet"));
|
||||
|
||||
return cpu;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package net.simon987.server.assembly;
|
||||
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.io.CpuHardwareDeserializer;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import net.simon987.server.io.MongoSerialisable;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public abstract class CpuHardware implements JSONSerialisable {
|
||||
public abstract class CpuHardware implements MongoSerialisable {
|
||||
|
||||
CPU cpu;
|
||||
|
||||
@@ -26,12 +26,12 @@ public abstract class CpuHardware implements JSONSerialisable {
|
||||
|
||||
public abstract char getId();
|
||||
|
||||
public static CpuHardware deserialize(JSONObject hwJson) {
|
||||
public static CpuHardware deserialize(DBObject obj) {
|
||||
|
||||
for (ServerPlugin plugin : GameServer.INSTANCE.getPluginManager().getPlugins()) {
|
||||
|
||||
if (plugin instanceof CpuHardwareDeserializer) {
|
||||
CpuHardware hw = ((CpuHardwareDeserializer) plugin).deserializeHardware(hwJson);
|
||||
CpuHardware hw = ((CpuHardwareDeserializer) plugin).deserializeHardware(obj);
|
||||
|
||||
if (hw != null) {
|
||||
return hw;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package net.simon987.server.assembly;
|
||||
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import net.simon987.server.io.MongoSerialisable;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
@@ -20,7 +22,7 @@ import java.util.zip.InflaterOutputStream;
|
||||
/**
|
||||
* Represents the available memory for a CPU in the game universe
|
||||
*/
|
||||
public class Memory implements Target, JSONSerialisable {
|
||||
public class Memory implements Target, MongoSerialisable {
|
||||
|
||||
|
||||
/**
|
||||
@@ -105,25 +107,54 @@ public class Memory implements Target, JSONSerialisable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
public BasicDBObject mongoSerialise() {
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
||||
try {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
Deflater compressor = new Deflater(Deflater.BEST_COMPRESSION, true);
|
||||
Deflater compressor = new Deflater(Deflater.BEST_SPEED, true);
|
||||
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(stream, compressor);
|
||||
deflaterOutputStream.write(getBytes());
|
||||
deflaterOutputStream.close();
|
||||
byte[] compressedBytes = stream.toByteArray();
|
||||
|
||||
json.put("zipBytes", new String(Base64.getEncoder().encode(compressedBytes)));
|
||||
dbObject.put("zipBytes", new String(Base64.getEncoder().encode(compressedBytes)));
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return json;
|
||||
return dbObject;
|
||||
}
|
||||
|
||||
public static Memory deserialize(DBObject obj) {
|
||||
|
||||
Memory memory = new Memory(0);
|
||||
|
||||
String zipBytesStr = (String) obj.get("zipBytes");
|
||||
|
||||
if (zipBytesStr != null) {
|
||||
byte[] compressedBytes = Base64.getDecoder().decode((String) obj.get("zipBytes"));
|
||||
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
Inflater decompressor = new Inflater(true);
|
||||
InflaterOutputStream inflaterOutputStream = new InflaterOutputStream(baos, decompressor);
|
||||
inflaterOutputStream.write(compressedBytes);
|
||||
inflaterOutputStream.close();
|
||||
|
||||
memory.setBytes(baos.toByteArray());
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
LogManager.LOGGER.severe("Memory was manually deleted");
|
||||
memory = new Memory(GameServer.INSTANCE.getConfig().getInt("memory_size"));
|
||||
}
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
public static Memory deserialize(JSONObject json) {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package net.simon987.server.assembly;
|
||||
|
||||
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import net.simon987.server.io.MongoSerialisable;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
@@ -12,7 +15,7 @@ import java.util.HashMap;
|
||||
/**
|
||||
* A set of registers for a CPU
|
||||
*/
|
||||
public class RegisterSet implements Target, JSONSerialisable {
|
||||
public class RegisterSet implements Target, MongoSerialisable {
|
||||
|
||||
/**
|
||||
* List of registers
|
||||
@@ -142,8 +145,8 @@ public class RegisterSet implements Target, JSONSerialisable {
|
||||
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
JSONArray registers = new JSONArray();
|
||||
public BasicDBObject mongoSerialise() {
|
||||
BasicDBList registers = new BasicDBList();
|
||||
for (Integer index : this.registers.keySet()) {
|
||||
JSONObject register = new JSONObject();
|
||||
|
||||
@@ -154,10 +157,28 @@ public class RegisterSet implements Target, JSONSerialisable {
|
||||
registers.add(register);
|
||||
}
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("registers", registers);
|
||||
BasicDBObject obj = new BasicDBObject();
|
||||
obj.put("registers", registers);
|
||||
|
||||
return json;
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static RegisterSet deserialize(DBObject obj) {
|
||||
|
||||
RegisterSet registerSet = new RegisterSet();
|
||||
|
||||
BasicDBList registers = (BasicDBList) obj.get("registers");
|
||||
|
||||
for (Object sRegister : registers) {
|
||||
|
||||
Register register = new Register((String) ((DBObject) sRegister).get("name"));
|
||||
register.setValue((int) ((DBObject) sRegister).get("value"));
|
||||
|
||||
registerSet.registers.put((int) ((DBObject) sRegister).get("index"), register);
|
||||
|
||||
}
|
||||
|
||||
return registerSet;
|
||||
}
|
||||
|
||||
public static RegisterSet deserialize(JSONObject json) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package net.simon987.server.game;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.io.GameObjectDeserializer;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import net.simon987.server.io.MongoSerialisable;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
@@ -12,7 +14,7 @@ import java.awt.*;
|
||||
* An INSTANCE of an object (e.g. a Tree, a character ...) inside the
|
||||
* game universe
|
||||
*/
|
||||
public abstract class GameObject implements JSONSerialisable {
|
||||
public abstract class GameObject implements JSONSerialisable, MongoSerialisable {
|
||||
|
||||
private boolean dead;
|
||||
/**
|
||||
@@ -76,9 +78,9 @@ public abstract class GameObject implements JSONSerialisable {
|
||||
if (world.getX() == 0) {
|
||||
//Warp around
|
||||
leftWorld = GameServer.INSTANCE.getGameUniverse().getWorld(
|
||||
GameServer.INSTANCE.getGameUniverse().getMaxWidth(), world.getY());
|
||||
GameServer.INSTANCE.getGameUniverse().getMaxWidth(), world.getY(), true);
|
||||
} else {
|
||||
leftWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX() - 1, world.getY());
|
||||
leftWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX() - 1, world.getY(), true);
|
||||
}
|
||||
|
||||
if (leftWorld != null) {
|
||||
@@ -95,9 +97,9 @@ public abstract class GameObject implements JSONSerialisable {
|
||||
World rightWorld;
|
||||
if (world.getX() == GameServer.INSTANCE.getGameUniverse().getMaxWidth()) {
|
||||
//Warp around
|
||||
rightWorld = GameServer.INSTANCE.getGameUniverse().getWorld(0, world.getY());
|
||||
rightWorld = GameServer.INSTANCE.getGameUniverse().getWorld(0, world.getY(), true);
|
||||
} else {
|
||||
rightWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX() + 1, world.getY());
|
||||
rightWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX() + 1, world.getY(), true);
|
||||
}
|
||||
|
||||
if (rightWorld != null) {
|
||||
@@ -115,9 +117,9 @@ public abstract class GameObject implements JSONSerialisable {
|
||||
if (world.getY() == 0) {
|
||||
//Warp around
|
||||
upWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX(),
|
||||
GameServer.INSTANCE.getGameUniverse().getMaxWidth());
|
||||
GameServer.INSTANCE.getGameUniverse().getMaxWidth(), true);
|
||||
} else {
|
||||
upWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX(), world.getY() - 1);
|
||||
upWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX(), world.getY() - 1, true);
|
||||
}
|
||||
|
||||
if (upWorld != null) {
|
||||
@@ -134,9 +136,9 @@ public abstract class GameObject implements JSONSerialisable {
|
||||
World downWorld;
|
||||
if (world.getY() == GameServer.INSTANCE.getGameUniverse().getMaxWidth()) {
|
||||
//Warp around
|
||||
downWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX(), 0);
|
||||
downWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX(), 0, true);
|
||||
} else {
|
||||
downWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX(), world.getY() + 1);
|
||||
downWorld = GameServer.INSTANCE.getGameUniverse().getWorld(world.getX(), world.getY() + 1, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -224,12 +226,12 @@ public abstract class GameObject implements JSONSerialisable {
|
||||
return new JSONObject();
|
||||
}
|
||||
|
||||
public static GameObject deserialize(JSONObject objJson) {
|
||||
|
||||
public static GameObject deserialize(DBObject obj) {
|
||||
//
|
||||
for (ServerPlugin plugin : GameServer.INSTANCE.getPluginManager().getPlugins()) {
|
||||
|
||||
if (plugin instanceof GameObjectDeserializer) {
|
||||
GameObject object = ((GameObjectDeserializer) plugin).deserializeObject(objJson);
|
||||
GameObject object = ((GameObjectDeserializer) plugin).deserializeObject(obj);
|
||||
|
||||
if (object != null) {
|
||||
return object;
|
||||
|
||||
@@ -6,20 +6,12 @@ import net.simon987.server.assembly.Assembler;
|
||||
import net.simon987.server.assembly.AssemblyResult;
|
||||
import net.simon987.server.assembly.CPU;
|
||||
import net.simon987.server.assembly.exception.CancelledException;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.user.User;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GameUniverse implements JSONSerialisable {
|
||||
public class GameUniverse {
|
||||
|
||||
private ArrayList<World> worlds;
|
||||
private ArrayList<User> users;
|
||||
@@ -27,7 +19,7 @@ public class GameUniverse implements JSONSerialisable {
|
||||
|
||||
private long time;
|
||||
|
||||
private int nextObjectId = 0;
|
||||
private long nextObjectId = 0;
|
||||
|
||||
private int maxWidth = 0xFFFF;
|
||||
|
||||
@@ -44,7 +36,7 @@ public class GameUniverse implements JSONSerialisable {
|
||||
return time;
|
||||
}
|
||||
|
||||
public World getWorld(int x, int y) {
|
||||
public World getWorld(int x, int y, boolean createNew) {
|
||||
|
||||
for (World world : worlds) {
|
||||
if (world.getX() == x && world.getY() == y) {
|
||||
@@ -53,14 +45,16 @@ public class GameUniverse implements JSONSerialisable {
|
||||
}
|
||||
|
||||
if (x >= 0 && x <= maxWidth && y >= 0 && y <= maxWidth) {
|
||||
//World does not exist
|
||||
LogManager.LOGGER.severe("Trying to read a World that does not exist!");
|
||||
if (createNew) {
|
||||
//World does not exist
|
||||
World world = createWorld(x, y);
|
||||
worlds.add(world);
|
||||
|
||||
World world = createWorld(x, y);
|
||||
return world;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
worlds.add(world);
|
||||
|
||||
return world;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -145,7 +139,7 @@ public class GameUniverse implements JSONSerialisable {
|
||||
* @param id id of the game object
|
||||
* @return GameObject, null if not found
|
||||
*/
|
||||
public GameObject getObject(int id) {
|
||||
public GameObject getObject(long id) {
|
||||
|
||||
//
|
||||
for (World world : worlds) {
|
||||
@@ -156,6 +150,7 @@ public class GameUniverse implements JSONSerialisable {
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.LOGGER.severe("Couldn't find object: " + id);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -172,75 +167,6 @@ public class GameUniverse implements JSONSerialisable {
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
JSONArray worlds = new JSONArray();
|
||||
|
||||
ArrayList<World> worlds_ = new ArrayList<>(this.worlds);
|
||||
for (World world : worlds_) {
|
||||
worlds.add(world.serialise());
|
||||
}
|
||||
|
||||
JSONArray users = new JSONArray();
|
||||
ArrayList<User> users_ = new ArrayList<User>(this.users);
|
||||
for (User user : users_) {
|
||||
if (!user.isGuest()) {
|
||||
users.add(user.serialise());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
json.put("users", users);
|
||||
json.put("worlds", worlds);
|
||||
json.put("time", time);
|
||||
json.put("nextObjectId", nextObjectId);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load game universe from JSON save file
|
||||
*
|
||||
* @param file JSON save file
|
||||
*/
|
||||
public void load(File file) {
|
||||
|
||||
JSONParser parser = new JSONParser();
|
||||
|
||||
if (file.isFile()) {
|
||||
try {
|
||||
|
||||
FileReader reader = new FileReader(file);
|
||||
JSONObject universeJson = (JSONObject) parser.parse(reader);
|
||||
|
||||
time = (long) universeJson.get("time");
|
||||
nextObjectId = (int) (long) universeJson.get("nextObjectId");
|
||||
|
||||
for (JSONObject worldJson : (ArrayList<JSONObject>) universeJson.get("worlds")) {
|
||||
worlds.add(World.deserialize(worldJson));
|
||||
}
|
||||
|
||||
for (JSONObject userJson : (ArrayList<JSONObject>) universeJson.get("users")) {
|
||||
users.add(User.deserialize(userJson));
|
||||
}
|
||||
|
||||
LogManager.LOGGER.info("Loaded " + worlds.size() + " worlds from file");
|
||||
|
||||
reader.close();
|
||||
|
||||
} catch (IOException | ParseException | CancelledException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
LogManager.LOGGER.severe("Couldn't load save file save.json, creating empty game universe.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public long getNextObjectId() {
|
||||
return ++nextObjectId;
|
||||
}
|
||||
@@ -263,10 +189,17 @@ public class GameUniverse implements JSONSerialisable {
|
||||
|
||||
public void removeUser(User user) {
|
||||
users.remove(user);
|
||||
|
||||
}
|
||||
|
||||
public int getMaxWidth() {
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public void setNextObjectId(long nextObjectId) {
|
||||
this.nextObjectId = nextObjectId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
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.MongoSerialisable;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -17,7 +21,7 @@ import java.util.zip.InflaterOutputStream;
|
||||
/**
|
||||
* A 2D map of Tile objects of size width*height
|
||||
*/
|
||||
public class TileMap implements JSONSerialisable {
|
||||
public class TileMap implements JSONSerialisable, MongoSerialisable {
|
||||
|
||||
public static final int PLAIN_TILE = 0;
|
||||
public static final int WALL_TILE = 1;
|
||||
@@ -52,6 +56,13 @@ public class TileMap implements JSONSerialisable {
|
||||
tiles = new int[width][height];
|
||||
}
|
||||
|
||||
public TileMap(int[][] tiles) {
|
||||
this.width = World.WORLD_SIZE;
|
||||
this.height = World.WORLD_SIZE;
|
||||
|
||||
this.tiles = tiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the tile at a specified position
|
||||
* Sets the modified flag
|
||||
@@ -128,11 +139,37 @@ public class TileMap implements JSONSerialisable {
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicDBObject mongoSerialise() {
|
||||
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
||||
dbObject.put("tiles", tiles);
|
||||
|
||||
return dbObject;
|
||||
|
||||
}
|
||||
|
||||
public static TileMap deserialize(DBObject object) {
|
||||
|
||||
BasicDBList terrain = (BasicDBList) object.get("tiles");
|
||||
|
||||
int[][] tiles = new int[World.WORLD_SIZE][World.WORLD_SIZE];
|
||||
|
||||
for (int x = 0; x < World.WORLD_SIZE; x++) {
|
||||
for (int y = 0; y < World.WORLD_SIZE; y++) {
|
||||
tiles[x][y] = (int) ((BasicDBList) terrain.get(x)).get(y);
|
||||
}
|
||||
}
|
||||
|
||||
return new TileMap(tiles);
|
||||
|
||||
}
|
||||
|
||||
public static TileMap deserialize(JSONObject object) {
|
||||
|
||||
TileMap tileMap = new TileMap(World.WORLD_SIZE, World.WORLD_SIZE);
|
||||
|
||||
|
||||
byte[] compressedBytes = Base64.getDecoder().decode((String) object.get("z"));
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
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.event.GameEvent;
|
||||
import net.simon987.server.event.WorldUpdateEvent;
|
||||
import net.simon987.server.game.pathfinding.Pathfinder;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import org.json.simple.JSONArray;
|
||||
import net.simon987.server.io.MongoSerialisable;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
public class World implements JSONSerialisable {
|
||||
public class World implements MongoSerialisable {
|
||||
|
||||
/**
|
||||
* Size of the side of a world
|
||||
@@ -111,24 +113,26 @@ public class World implements JSONSerialisable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
JSONObject json = new JSONObject();
|
||||
public BasicDBObject mongoSerialise() {
|
||||
|
||||
JSONArray objects = new JSONArray();
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
||||
BasicDBList objects = new BasicDBList();
|
||||
ArrayList<GameObject> gameObjects_ = new ArrayList<>(gameObjects);
|
||||
for (GameObject obj : gameObjects_) {
|
||||
objects.add(obj.serialise());
|
||||
objects.add(obj.mongoSerialise());
|
||||
}
|
||||
json.put("o", objects);
|
||||
|
||||
json.put("t", tileMap.serialise());
|
||||
dbObject.put("objects", objects);
|
||||
dbObject.put("terrain", tileMap.mongoSerialise());
|
||||
|
||||
json.put("x", x);
|
||||
json.put("y", y);
|
||||
dbObject.put("x", x);
|
||||
dbObject.put("y", y);
|
||||
|
||||
json.put("u", updatable);
|
||||
dbObject.put("updatable", updatable);
|
||||
|
||||
return json;
|
||||
|
||||
return dbObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,21 +154,45 @@ public class World implements JSONSerialisable {
|
||||
|
||||
public static World deserialize(JSONObject json) {
|
||||
World world = new World();
|
||||
world.x = (int) (long) json.get("x");
|
||||
world.y = (int) (long) json.get("y");
|
||||
world.updatable = (int) (long) json.get("u");
|
||||
// world.x = (int) (long) json.get("x");
|
||||
// world.y = (int) (long) json.get("y");
|
||||
// world.updatable = (int) (long) json.get("u");
|
||||
//
|
||||
// world.tileMap = TileMap.deserialize((JSONObject) json.get("t"));
|
||||
//
|
||||
//
|
||||
// for (JSONObject objJson : (ArrayList<JSONObject>) json.get("o")) {
|
||||
//
|
||||
// GameObject object = GameObject.deserialize(objJson);
|
||||
//
|
||||
// object.setWorld(world);
|
||||
// world.gameObjects.add(object);
|
||||
// }
|
||||
|
||||
world.tileMap = TileMap.deserialize((JSONObject) json.get("t"));
|
||||
return world;
|
||||
}
|
||||
|
||||
for (JSONObject objJson : (ArrayList<JSONObject>) json.get("o")) {
|
||||
public static World deserialize(DBObject dbObject) {
|
||||
|
||||
GameObject object = GameObject.deserialize(objJson);
|
||||
World world = new World();
|
||||
world.x = (int) dbObject.get("x");
|
||||
world.y = (int) dbObject.get("y");
|
||||
world.updatable = (int) dbObject.get("updatable");
|
||||
|
||||
world.tileMap = TileMap.deserialize((BasicDBObject) dbObject.get("terrain"));
|
||||
|
||||
BasicDBList objects = (BasicDBList) dbObject.get("objects");
|
||||
|
||||
for (Object obj : objects) {
|
||||
|
||||
GameObject object = GameObject.deserialize((DBObject) obj);
|
||||
|
||||
object.setWorld(world);
|
||||
world.gameObjects.add(object);
|
||||
}
|
||||
|
||||
return world;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,6 @@ import net.simon987.server.ServerConfiguration;
|
||||
import net.simon987.server.assembly.exception.CancelledException;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.WorldGenerationEvent;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
@@ -93,7 +92,6 @@ public class WorldGenerator {
|
||||
* Create a randomly generated World
|
||||
*/
|
||||
public World generateWorld(int locX, int locY) throws CancelledException {
|
||||
LogManager.LOGGER.info("Generating random world");
|
||||
Random random = new Random();
|
||||
|
||||
World world = generateEmptyWorld(locX, locY);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package net.simon987.server.io;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import net.simon987.server.assembly.CpuHardware;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public interface CpuHardwareDeserializer {
|
||||
|
||||
|
||||
CpuHardware deserializeHardware(JSONObject hwJson);
|
||||
CpuHardware deserializeHardware(DBObject hwJson);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package net.simon987.server.io;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import net.simon987.server.game.GameObject;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public interface GameObjectDeserializer {
|
||||
|
||||
GameObject deserializeObject(JSONObject object);
|
||||
GameObject deserializeObject(DBObject object);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.simon987.server.io;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
|
||||
public interface MongoSerialisable {
|
||||
|
||||
BasicDBObject mongoSerialise();
|
||||
|
||||
}
|
||||
@@ -1,18 +1,19 @@
|
||||
package net.simon987.server.user;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.CPU;
|
||||
import net.simon987.server.assembly.exception.CancelledException;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.UserCreationEvent;
|
||||
import net.simon987.server.game.ControllableUnit;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import org.json.simple.JSONObject;
|
||||
import net.simon987.server.io.MongoSerialisable;
|
||||
|
||||
/**
|
||||
* Represents a User (or player) of the game
|
||||
*/
|
||||
public class User implements JSONSerialisable {
|
||||
public class User implements MongoSerialisable {
|
||||
|
||||
private String username;
|
||||
|
||||
@@ -39,33 +40,31 @@ public class User implements JSONSerialisable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
public BasicDBObject mongoSerialise() {
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
||||
json.put("username", username);
|
||||
json.put("code", userCode);
|
||||
json.put("controlledUnit", controlledUnit.getObjectId());
|
||||
json.put("cpu", cpu.serialise());
|
||||
|
||||
return json;
|
||||
dbObject.put("username", username);
|
||||
dbObject.put("code", userCode);
|
||||
dbObject.put("controlledUnit", controlledUnit.getObjectId());
|
||||
dbObject.put("cpu", cpu.mongoSerialise());
|
||||
|
||||
return dbObject;
|
||||
|
||||
}
|
||||
|
||||
public static User deserialize(JSONObject userJson) throws CancelledException {
|
||||
public static User deserialize(DBObject obj) throws CancelledException {
|
||||
|
||||
User user = new User((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((int) (long) userJson.get("controlledUnit")));
|
||||
user.username = (String) userJson.get("username");
|
||||
user.userCode = (String) userJson.get("code");
|
||||
User user = new User((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("controlledUnit")));
|
||||
user.username = (String) obj.get("username");
|
||||
user.userCode = (String) obj.get("code");
|
||||
|
||||
user.getControlledUnit().setParent(user);
|
||||
|
||||
user.cpu = CPU.deserialize((JSONObject) userJson.get("cpu"), user);
|
||||
user.cpu = CPU.deserialize((DBObject) obj.get("cpu"), user);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
//----
|
||||
|
||||
public String getUserCode() {
|
||||
|
||||
@@ -15,7 +15,7 @@ public class ObjectsRequestHandler implements MessageHandler {
|
||||
@Override
|
||||
public void handle(OnlineUser user, JSONObject json) {
|
||||
if (json.get("t").equals("object")) {
|
||||
LogManager.LOGGER.fine("(WS) Objects request from " + user.getUser().getUsername());
|
||||
// LogManager.LOGGER.fine("(WS) Objects request from " + user.getUser().getUsername());
|
||||
|
||||
int x, y;
|
||||
try {
|
||||
@@ -26,7 +26,7 @@ public class ObjectsRequestHandler implements MessageHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
World world = GameServer.INSTANCE.getGameUniverse().getWorld(x, y);
|
||||
World world = GameServer.INSTANCE.getGameUniverse().getWorld(x, y, false);
|
||||
|
||||
if (world != null) {
|
||||
ArrayList<GameObject> gameObjects = world.getGameObjects();
|
||||
|
||||
@@ -20,6 +20,7 @@ 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;
|
||||
@@ -59,6 +60,7 @@ public class SocketServer extends WebSocketServer {
|
||||
}
|
||||
|
||||
setConnectionLostTimeout(120);
|
||||
setReuseAddr(true); //To avoid BindException
|
||||
|
||||
database = new SocketServerDatabase(config);
|
||||
|
||||
@@ -145,10 +147,19 @@ public class SocketServer extends WebSocketServer {
|
||||
@Override
|
||||
public void onError(WebSocket conn, Exception ex) {
|
||||
|
||||
LogManager.LOGGER.severe("an error occurred on connection " + conn + ": " + ex);
|
||||
userManager.remove(userManager.getUser(conn));
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,12 +12,12 @@ public class TerrainRequestHandler implements MessageHandler {
|
||||
public void handle(OnlineUser user, JSONObject json) {
|
||||
if (json.get("t").equals("terrain") && json.containsKey("x") && json.containsKey("y")) {
|
||||
|
||||
LogManager.LOGGER.fine("Terrain request from " + user.getUser().getUsername());
|
||||
// LogManager.LOGGER.fine("Terrain request from " + user.getUser().getUsername());
|
||||
World world;
|
||||
try {
|
||||
world = GameServer.INSTANCE.getGameUniverse().getWorld(
|
||||
Long.valueOf((long) json.get("x")).intValue(),
|
||||
Long.valueOf((long) json.get("y")).intValue());
|
||||
Long.valueOf((long) json.get("y")).intValue(), false);
|
||||
} catch (NullPointerException e) {
|
||||
LogManager.LOGGER.severe("FIXME: handle TerrainRequestHandler");
|
||||
return;
|
||||
@@ -38,11 +38,17 @@ public class TerrainRequestHandler implements MessageHandler {
|
||||
}
|
||||
|
||||
response.put("t", "terrain");
|
||||
response.put("ok", true);
|
||||
response.put("terrain", terrain);
|
||||
|
||||
user.getWebSocket().send(response.toJSONString());
|
||||
} else {
|
||||
LogManager.LOGGER.severe("FIXME handle:TerrainRequestHandler");
|
||||
//Uncharted World
|
||||
JSONObject response = new JSONObject();
|
||||
response.put("t", "terrain");
|
||||
response.put("ok", false);
|
||||
|
||||
user.getWebSocket().send(response.toJSONString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user