diff --git a/Plugin Cubot/Plugin Cubot.iml b/Plugin Cubot/Plugin Cubot.iml index 6304740..811f55d 100644 --- a/Plugin Cubot/Plugin Cubot.iml +++ b/Plugin Cubot/Plugin Cubot.iml @@ -18,8 +18,6 @@ - - diff --git a/Plugin Misc HW/Plugin Misc HW.iml b/Plugin Misc HW/Plugin Misc HW.iml index bb581da..dda82b5 100644 --- a/Plugin Misc HW/Plugin Misc HW.iml +++ b/Plugin Misc HW/Plugin Misc HW.iml @@ -17,8 +17,6 @@ - - diff --git a/Plugin NPC/Plugin NPC.iml b/Plugin NPC/Plugin NPC.iml index 8bcf827..7cddba0 100644 --- a/Plugin NPC/Plugin NPC.iml +++ b/Plugin NPC/Plugin NPC.iml @@ -20,8 +20,6 @@ - - diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/io/StatsDatabaseManager.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/io/StatsDatabaseManager.java index 1990d18..4b62d8e 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/io/StatsDatabaseManager.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/io/StatsDatabaseManager.java @@ -1,14 +1,8 @@ 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 { @@ -18,32 +12,7 @@ public class StatsDatabaseManager extends DatabaseManager { 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(); - } - } } } diff --git a/Plugin Plant/Plugin Plant.iml b/Plugin Plant/Plugin Plant.iml index 8bcf827..7cddba0 100644 --- a/Plugin Plant/Plugin Plant.iml +++ b/Plugin Plant/Plugin Plant.iml @@ -20,8 +20,6 @@ - - diff --git a/Server/Server.iml b/Server/Server.iml index 0a3aeb7..39ed77c 100644 --- a/Server/Server.iml +++ b/Server/Server.iml @@ -16,10 +16,8 @@ - - diff --git a/Server/pom.xml b/Server/pom.xml index 4378d55..2145284 100644 --- a/Server/pom.xml +++ b/Server/pom.xml @@ -88,22 +88,12 @@ 1.4a - - org.java-websocket - Java-WebSocket - 1.3.6 - junit junit 4.12 test - - mysql - mysql-connector-java - 5.1.42 - com.googlecode.json-simple json-simple diff --git a/Server/src/main/java/net/simon987/server/GameServer.java b/Server/src/main/java/net/simon987/server/GameServer.java index 98d85fd..d651b70 100644 --- a/Server/src/main/java/net/simon987/server/GameServer.java +++ b/Server/src/main/java/net/simon987/server/GameServer.java @@ -14,7 +14,8 @@ import net.simon987.server.game.debug.*; import net.simon987.server.logging.LogManager; import net.simon987.server.plugin.PluginManager; import net.simon987.server.user.User; -import net.simon987.server.webserver.SocketServer; +import net.simon987.server.user.UserManager; +import net.simon987.server.websocket.SocketServer; import java.io.File; import java.net.UnknownHostException; @@ -39,12 +40,16 @@ public class GameServer implements Runnable { private MongoClient mongo = null; + private UserManager userManager; + public GameServer() { this.config = new ServerConfiguration("config.properties"); try{ mongo = new MongoClient("localhost", 27017); + userManager = new UserManager(mongo); + } catch (UnknownHostException e) { e.printStackTrace(); } @@ -127,7 +132,7 @@ public class GameServer implements Runnable { uTime = System.currentTimeMillis() - startTime; 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 { if (waitTime >= 0) { @@ -184,14 +189,12 @@ public class GameServer implements Runnable { save(); } - socketServer.tick(); +// socketServer.tick(); - LogManager.LOGGER.info("Processed " + gameUniverse.getWorldCount() + " worlds (" + updatedWorlds + - " updated)"); +// LogManager.LOGGER.info("Processed " + gameUniverse.getWorldCount() + " worlds (" + updatedWorlds + +// " updated)"); } - - void load() { LogManager.LOGGER.info("Loading all data from MongoDB"); @@ -248,14 +251,12 @@ public class GameServer implements Runnable { int insertedWorlds = 0; GameUniverse universe = GameServer.INSTANCE.getGameUniverse(); for (World w : universe.getWorlds()) { -// LogManager.LOGGER.fine("Saving world "+w.getId()+" to mongodb"); insertedWorlds++; worlds.save(w.mongoSerialise()); - // 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()){ unloaded_worlds++; -// LogManager.LOGGER.fine("Unloading world "+w.getId()+" from universe"); universe.removeWorld(w); } } @@ -265,17 +266,15 @@ public class GameServer implements Runnable { if (!u.isGuest()) { users.save(u.mongoSerialise()); } - } BasicDBObject serverObj = new BasicDBObject(); - 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("_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("nextObjectId", gameUniverse.getNextObjectId()); server.save(serverObj); - LogManager.LOGGER.info(""+insertedWorlds+" worlds saved, "+unloaded_worlds+" unloaded"); - LogManager.LOGGER.info("Done!"); + LogManager.LOGGER.info("" + insertedWorlds + " worlds saved, " + unloaded_worlds + " unloaded"); } catch (Exception e) { LogManager.LOGGER.severe("Problem happened during save function"); e.printStackTrace(); @@ -297,4 +296,8 @@ public class GameServer implements Runnable { public DayNightCycle getDayNightCycle() { return dayNightCycle; } + + public UserManager getUserManager() { + return userManager; + } } diff --git a/Server/src/main/java/net/simon987/server/Main.java b/Server/src/main/java/net/simon987/server/Main.java index 1f452f2..6f4f910 100644 --- a/Server/src/main/java/net/simon987/server/Main.java +++ b/Server/src/main/java/net/simon987/server/Main.java @@ -1,13 +1,15 @@ package net.simon987.server; import net.simon987.server.logging.LogManager; -import net.simon987.server.webserver.SocketServer; +import net.simon987.server.user.RegistrationException; +import net.simon987.server.web.AlertMessage; +import net.simon987.server.web.AlertType; +import net.simon987.server.websocket.SocketServer; import org.apache.velocity.app.VelocityEngine; import spark.ModelAndView; import spark.Spark; import spark.template.velocity.VelocityTemplateEngine; -import java.net.InetSocketAddress; import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -22,12 +24,6 @@ public class Main { //Load GameServer.INSTANCE.load(); - SocketServer socketServer = new SocketServer(new InetSocketAddress(config.getString("webSocket_host"), - config.getInt("webSocket_port")), config); - - GameServer.INSTANCE.setSocketServer(socketServer); - - (new Thread(socketServer)).start(); (new Thread(GameServer.INSTANCE)).start(); //TEST --------------------------- @@ -36,29 +32,100 @@ public class Main { VelocityTemplateEngine templateEngine = new VelocityTemplateEngine(new VelocityEngine(properties)); //-- + //Websocket + Spark.webSocket("/socket", SocketServer.class); + Spark.staticFiles.externalLocation("static"); Spark.get("/", (request, response) -> { Map model = new HashMap<>(); - System.out.println((String) request.session().attribute("user")); + model.put("session", request.session()); return new ModelAndView(model, "home.vm"); }, templateEngine); Spark.get("/leaderboard", (request, response) -> { + Map model = new HashMap<>(); + model.put("session", request.session()); + return new ModelAndView(new HashMap<>(), "leaderboard.vm"); }, templateEngine); Spark.get("/play", (request, response) -> { Map model = new HashMap<>(); + model.put("session", request.session()); + return new ModelAndView(model, "play.vm"); }, templateEngine); Spark.get("/account", (request, response) -> { Map 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"); }, templateEngine); + Spark.post("/register", (request, 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; + }); + + Spark.post("/login", (request, 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.INFO)}; + 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; + }); + + Spark.get("logout", (request, response) -> { + + AlertMessage[] messages = {new AlertMessage("Logged out", AlertType.INFO)}; + request.session().attribute("messages", messages); + request.session().removeAttribute("username"); + + response.redirect("/account"); + return null; + }); + Spark.after((request, response) -> response.header("Content-Encoding", "gzip")); } + + } diff --git a/Server/src/main/java/net/simon987/server/assembly/CPU.java b/Server/src/main/java/net/simon987/server/assembly/CPU.java index e9dfeff..67eeaf8 100755 --- a/Server/src/main/java/net/simon987/server/assembly/CPU.java +++ b/Server/src/main/java/net/simon987/server/assembly/CPU.java @@ -160,7 +160,7 @@ public class CPU implements MongoSerialisable { } 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 @@ -173,7 +173,6 @@ public class CPU implements MongoSerialisable { public void executeInstruction(Instruction instruction, int source, int destination) { - //Execute the instruction if (source == 0) { //No operand (assuming that destination is also null) diff --git a/Server/src/main/java/net/simon987/server/event/DebugCommandEvent.java b/Server/src/main/java/net/simon987/server/event/DebugCommandEvent.java index f9395f3..6fe804f 100644 --- a/Server/src/main/java/net/simon987/server/event/DebugCommandEvent.java +++ b/Server/src/main/java/net/simon987/server/event/DebugCommandEvent.java @@ -1,8 +1,10 @@ package net.simon987.server.event; -import net.simon987.server.webserver.OnlineUser; +import net.simon987.server.websocket.OnlineUser; import org.json.simple.JSONObject; +import java.io.IOException; + public class DebugCommandEvent extends GameEvent { private JSONObject command; @@ -37,7 +39,11 @@ public class DebugCommandEvent extends GameEvent { response.put("t", "debug"); response.put("message", message); - ((OnlineUser) getSource()).getWebSocket().send(response.toJSONString()); + try { + ((OnlineUser) getSource()).getWebSocket().getRemote().sendString(response.toJSONString()); + } catch (IOException e) { + e.printStackTrace(); + } } } diff --git a/Server/src/main/java/net/simon987/server/user/RegistrationException.java b/Server/src/main/java/net/simon987/server/user/RegistrationException.java new file mode 100644 index 0000000..7c5cbb1 --- /dev/null +++ b/Server/src/main/java/net/simon987/server/user/RegistrationException.java @@ -0,0 +1,9 @@ +package net.simon987.server.user; + +public class RegistrationException extends Exception { + + public RegistrationException(String message) { + super(message); + } + +} diff --git a/Server/src/main/java/net/simon987/server/user/User.java b/Server/src/main/java/net/simon987/server/user/User.java index 0da9acc..2470605 100755 --- a/Server/src/main/java/net/simon987/server/user/User.java +++ b/Server/src/main/java/net/simon987/server/user/User.java @@ -18,6 +18,7 @@ public class User implements MongoSerialisable { private String username; private String userCode; + private String password; private CPU cpu; @@ -49,6 +50,7 @@ public class User implements MongoSerialisable { dbObject.put("code", userCode); dbObject.put("controlledUnit", controlledUnit.getObjectId()); dbObject.put("cpu", cpu.mongoSerialise()); + dbObject.put("password", password); return dbObject; @@ -59,6 +61,7 @@ public class User implements MongoSerialisable { 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.password = (String) obj.get("password"); user.getControlledUnit().setParent(user); @@ -107,4 +110,8 @@ public class User implements MongoSerialisable { public void setGuest(boolean guest) { this.guest = guest; } + + public void setPassword(String password) { + this.password = password; + } } diff --git a/Server/src/main/java/net/simon987/server/user/UserManager.java b/Server/src/main/java/net/simon987/server/user/UserManager.java index 8c68672..7f0d442 100644 --- a/Server/src/main/java/net/simon987/server/user/UserManager.java +++ b/Server/src/main/java/net/simon987/server/user/UserManager.java @@ -1,6 +1,7 @@ package net.simon987.server.user; import com.mongodb.*; +import net.simon987.server.GameServer; import net.simon987.server.assembly.exception.CancelledException; import org.springframework.security.crypto.bcrypt.BCrypt; @@ -34,16 +35,37 @@ public class UserManager { return userList; } - public void registerUser(User user, String password) { + public void registerUser(String username, String password) throws RegistrationException { - DBObject dbUser = user.mongoSerialise(); + 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"); + } - String salt = BCrypt.gensalt(12); - String hashedPassword = BCrypt.hashpw(password, salt); + //Check if exists + DBObject where = new BasicDBObject(); + where.put("_id", username); - dbUser.put("password", hashedPassword); + if (userCollection.findOne(where) != null) { + throw new RegistrationException("Username is already in use"); + } - userCollection.save(dbUser); + 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); + + DBObject dbUser = user.mongoSerialise(); + + userCollection.save(dbUser); + } catch (Exception e) { + throw new RegistrationException("An exception occurred while trying to create user: " + e.getMessage()); + } } public boolean validateUser(String username, String password) { @@ -52,7 +74,6 @@ public class UserManager { where.put("_id", username); DBObject user = userCollection.findOne(where); - return user != null && BCrypt.checkpw(password, (String) user.get("password")); } } diff --git a/Server/src/main/java/net/simon987/server/web/AlertMessage.java b/Server/src/main/java/net/simon987/server/web/AlertMessage.java new file mode 100644 index 0000000..1df5581 --- /dev/null +++ b/Server/src/main/java/net/simon987/server/web/AlertMessage.java @@ -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; + } +} diff --git a/Server/src/main/java/net/simon987/server/web/AlertType.java b/Server/src/main/java/net/simon987/server/web/AlertType.java new file mode 100644 index 0000000..c4706be --- /dev/null +++ b/Server/src/main/java/net/simon987/server/web/AlertType.java @@ -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; + } +} diff --git a/Server/src/main/java/net/simon987/server/webserver/MessageHandler.java b/Server/src/main/java/net/simon987/server/webserver/MessageHandler.java deleted file mode 100644 index dae4eb5..0000000 --- a/Server/src/main/java/net/simon987/server/webserver/MessageHandler.java +++ /dev/null @@ -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; - -} diff --git a/Server/src/main/java/net/simon987/server/webserver/SocketServer.java b/Server/src/main/java/net/simon987/server/webserver/SocketServer.java deleted file mode 100644 index 4166ebb..0000000 --- a/Server/src/main/java/net/simon987/server/webserver/SocketServer.java +++ /dev/null @@ -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 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 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; - } -} \ No newline at end of file diff --git a/Server/src/main/java/net/simon987/server/webserver/CodeRequestHandler.java b/Server/src/main/java/net/simon987/server/websocket/CodeRequestHandler.java similarity index 71% rename from Server/src/main/java/net/simon987/server/webserver/CodeRequestHandler.java rename to Server/src/main/java/net/simon987/server/websocket/CodeRequestHandler.java index dfa4272..ed4eacf 100644 --- a/Server/src/main/java/net/simon987/server/webserver/CodeRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/websocket/CodeRequestHandler.java @@ -1,11 +1,13 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.logging.LogManager; import org.json.simple.JSONObject; +import java.io.IOException; + public class CodeRequestHandler implements MessageHandler { @Override - public void handle(OnlineUser user, JSONObject json) { + public void handle(OnlineUser user, JSONObject json) throws IOException { if (json.get("t").equals("codeRequest")) { @@ -18,7 +20,7 @@ public class CodeRequestHandler implements MessageHandler { response.put("t", "code"); 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 { @@ -27,7 +29,7 @@ public class CodeRequestHandler implements MessageHandler { response.put("t", "code"); response.put("code", user.getUser().getUserCode()); - user.getWebSocket().send(response.toJSONString()); + user.getWebSocket().getRemote().sendString(response.toJSONString()); } diff --git a/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java b/Server/src/main/java/net/simon987/server/websocket/CodeUploadHandler.java similarity index 90% rename from Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java rename to Server/src/main/java/net/simon987/server/websocket/CodeUploadHandler.java index f552ca0..7aeaeb9 100644 --- a/Server/src/main/java/net/simon987/server/webserver/CodeUploadHandler.java +++ b/Server/src/main/java/net/simon987/server/websocket/CodeUploadHandler.java @@ -1,4 +1,4 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.GameServer; import net.simon987.server.assembly.Assembler; @@ -6,10 +6,12 @@ import net.simon987.server.assembly.AssemblyResult; import net.simon987.server.logging.LogManager; import org.json.simple.JSONObject; +import java.io.IOException; + public class CodeUploadHandler implements MessageHandler { @Override - public void handle(OnlineUser user, JSONObject json) { + public void handle(OnlineUser user, JSONObject json) throws IOException { if (json.get("t").equals("uploadCode")) { LogManager.LOGGER.fine("(WS) Code upload from " + user.getUser().getUsername()); @@ -48,11 +50,9 @@ public class CodeUploadHandler implements MessageHandler { response.put("bytes", ar.bytes.length); response.put("exceptions", ar.exceptions.size()); - user.getWebSocket().send(response.toJSONString()); + user.getWebSocket().getRemote().sendString(response.toJSONString()); } } - - } } } diff --git a/Server/src/main/java/net/simon987/server/webserver/DebugCommandHandler.java b/Server/src/main/java/net/simon987/server/websocket/DebugCommandHandler.java similarity index 68% rename from Server/src/main/java/net/simon987/server/webserver/DebugCommandHandler.java rename to Server/src/main/java/net/simon987/server/websocket/DebugCommandHandler.java index a9b6a91..0dd1ba6 100644 --- a/Server/src/main/java/net/simon987/server/webserver/DebugCommandHandler.java +++ b/Server/src/main/java/net/simon987/server/websocket/DebugCommandHandler.java @@ -1,14 +1,13 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.GameServer; import net.simon987.server.event.DebugCommandEvent; -import org.java_websocket.exceptions.WebsocketNotConnectedException; import org.json.simple.JSONObject; public class DebugCommandHandler implements MessageHandler { @Override - public void handle(OnlineUser user, JSONObject json) throws WebsocketNotConnectedException { + public void handle(OnlineUser user, JSONObject json) { if (json.get("t").equals("debug") && user.isModerator()) { diff --git a/Server/src/main/java/net/simon987/server/webserver/FloppyHandler.java b/Server/src/main/java/net/simon987/server/websocket/FloppyHandler.java similarity index 91% rename from Server/src/main/java/net/simon987/server/webserver/FloppyHandler.java rename to Server/src/main/java/net/simon987/server/websocket/FloppyHandler.java index a66f418..651d582 100644 --- a/Server/src/main/java/net/simon987/server/webserver/FloppyHandler.java +++ b/Server/src/main/java/net/simon987/server/websocket/FloppyHandler.java @@ -1,4 +1,4 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.GameServer; import net.simon987.server.logging.LogManager; @@ -21,7 +21,7 @@ public class FloppyHandler implements MessageHandler { if (user.getUser().getControlledUnit().getFloppyData() != null) { byte[] bytes = user.getUser().getControlledUnit().getFloppyData().getBytes(); - user.getWebSocket().send(bytes); + LogManager.LOGGER.severe("TODO FloppyHandler.handle()"); } diff --git a/Server/src/main/java/net/simon987/server/webserver/KeypressHandler.java b/Server/src/main/java/net/simon987/server/websocket/KeypressHandler.java similarity index 94% rename from Server/src/main/java/net/simon987/server/webserver/KeypressHandler.java rename to Server/src/main/java/net/simon987/server/websocket/KeypressHandler.java index a0cbd95..390f6be 100644 --- a/Server/src/main/java/net/simon987/server/webserver/KeypressHandler.java +++ b/Server/src/main/java/net/simon987/server/websocket/KeypressHandler.java @@ -1,4 +1,4 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import org.json.simple.JSONObject; diff --git a/Server/src/main/java/net/simon987/server/webserver/MessageDispatcher.java b/Server/src/main/java/net/simon987/server/websocket/MessageDispatcher.java similarity index 73% rename from Server/src/main/java/net/simon987/server/webserver/MessageDispatcher.java rename to Server/src/main/java/net/simon987/server/websocket/MessageDispatcher.java index d289424..aacc3e0 100644 --- a/Server/src/main/java/net/simon987/server/webserver/MessageDispatcher.java +++ b/Server/src/main/java/net/simon987/server/websocket/MessageDispatcher.java @@ -1,12 +1,12 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.logging.LogManager; -import org.java_websocket.exceptions.WebsocketNotConnectedException; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import java.io.IOException; import java.util.ArrayList; public class MessageDispatcher { @@ -32,11 +32,8 @@ public class MessageDispatcher { for (MessageHandler handler : handlers) { try { handler.handle(user, json); - } catch (WebsocketNotConnectedException e) { - LogManager.LOGGER.fine("Catched WebsocketNotConnectedException"); - } catch (Exception e1) { - LogManager.LOGGER.severe(e1.getMessage()); - e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); } } } else { diff --git a/Server/src/main/java/net/simon987/server/websocket/MessageHandler.java b/Server/src/main/java/net/simon987/server/websocket/MessageHandler.java new file mode 100644 index 0000000..b492b85 --- /dev/null +++ b/Server/src/main/java/net/simon987/server/websocket/MessageHandler.java @@ -0,0 +1,11 @@ +package net.simon987.server.websocket; + +import org.json.simple.JSONObject; + +import java.io.IOException; + +public interface MessageHandler { + + void handle(OnlineUser user, JSONObject json) throws IOException; + +} diff --git a/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java b/Server/src/main/java/net/simon987/server/websocket/ObjectsRequestHandler.java similarity index 86% rename from Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java rename to Server/src/main/java/net/simon987/server/websocket/ObjectsRequestHandler.java index 6c01c02..0179cc3 100644 --- a/Server/src/main/java/net/simon987/server/webserver/ObjectsRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/websocket/ObjectsRequestHandler.java @@ -1,4 +1,4 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.GameServer; import net.simon987.server.game.GameObject; @@ -7,11 +7,13 @@ import net.simon987.server.logging.LogManager; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import java.io.IOException; + public class ObjectsRequestHandler implements MessageHandler { @Override - public void handle(OnlineUser user, JSONObject json) { + public void handle(OnlineUser user, JSONObject json) throws IOException { if (json.get("t").equals("object")) { // LogManager.LOGGER.fine("(WS) Objects request from " + user.getUser().getUsername()); @@ -43,7 +45,7 @@ public class ObjectsRequestHandler implements MessageHandler { if (user.getWebSocket().isOpen()) { - user.getWebSocket().send(response.toJSONString()); + user.getWebSocket().getRemote().sendString(response.toJSONString()); } } } diff --git a/Server/src/main/java/net/simon987/server/webserver/OnlineUser.java b/Server/src/main/java/net/simon987/server/websocket/OnlineUser.java similarity index 83% rename from Server/src/main/java/net/simon987/server/webserver/OnlineUser.java rename to Server/src/main/java/net/simon987/server/websocket/OnlineUser.java index bed7a99..0c2d762 100644 --- a/Server/src/main/java/net/simon987/server/webserver/OnlineUser.java +++ b/Server/src/main/java/net/simon987/server/websocket/OnlineUser.java @@ -1,14 +1,14 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.user.User; -import org.java_websocket.WebSocket; +import org.eclipse.jetty.websocket.api.Session; public class OnlineUser { private boolean authenticated = false; - private WebSocket webSocket; + private Session webSocket; private boolean guest; @@ -19,12 +19,12 @@ public class OnlineUser { */ private User user; - public OnlineUser(WebSocket webSocket) { + public OnlineUser(Session webSocket) { this.webSocket = webSocket; } - public WebSocket getWebSocket() { + public Session getWebSocket() { return webSocket; } diff --git a/Server/src/main/java/net/simon987/server/webserver/OnlineUserManager.java b/Server/src/main/java/net/simon987/server/websocket/OnlineUserManager.java similarity index 86% rename from Server/src/main/java/net/simon987/server/webserver/OnlineUserManager.java rename to Server/src/main/java/net/simon987/server/websocket/OnlineUserManager.java index c58f8c6..a7798a5 100644 --- a/Server/src/main/java/net/simon987/server/webserver/OnlineUserManager.java +++ b/Server/src/main/java/net/simon987/server/websocket/OnlineUserManager.java @@ -1,6 +1,6 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; -import org.java_websocket.WebSocket; +import org.eclipse.jetty.websocket.api.Session; import java.util.ArrayList; @@ -12,7 +12,7 @@ public class OnlineUserManager { private ArrayList onlineUsers = new ArrayList<>(10); - public OnlineUser getUser(WebSocket socket) { + public OnlineUser getUser(Session socket) { ArrayList _onlineUsers = new ArrayList<>(onlineUsers); diff --git a/Server/src/main/java/net/simon987/server/websocket/SocketServer.java b/Server/src/main/java/net/simon987/server/websocket/SocketServer.java new file mode 100644 index 0000000..01f4edb --- /dev/null +++ b/Server/src/main/java/net/simon987/server/websocket/SocketServer.java @@ -0,0 +1,129 @@ +package net.simon987.server.websocket; + +import net.simon987.server.game.ControllableUnit; +import net.simon987.server.logging.LogManager; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; + +@WebSocket +public class SocketServer { + + private OnlineUserManager onlineUserManager = new OnlineUserManager(); + + private MessageDispatcher messageDispatcher = new MessageDispatcher(); + + public SocketServer() { + + 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()); + } + + @OnWebSocketConnect + public void onOpen(Session session) { + LogManager.LOGGER.info("(WS) New Websocket connection " + session.getRemoteAddress()); + onlineUserManager.add(new OnlineUser(session)); + } + + @OnWebSocketClose + public void onClose(Session session, int code, String reason) { + LogManager.LOGGER.info("(WS) Closed " + session.getRemoteAddress() + " with exit code " + code + " additional info: " + reason); + onlineUserManager.remove(onlineUserManager.getUser(session)); + } + + @OnWebSocketMessage + public void onMessage(Session session, String message) { + OnlineUser onlineUser = onlineUserManager.getUser(session); + + if (onlineUser != null) { + + if (onlineUser.isAuthenticated()) { + + messageDispatcher.dispatch(onlineUser, message); + + } else { + + LogManager.LOGGER.info("(WS) Received message from unauthenticated user " + session.getRemoteAddress()); + //todo + + } + + } else { + + LogManager.LOGGER.severe("(WS) FIXME: SocketServer:onMessage"); + + } + } + + /** + * Called every tick + */ + public void tick() { + + JSONObject json = new JSONObject(); + json.put("t", "tick"); + + ArrayList onlineUsers = new ArrayList<>(onlineUserManager.getOnlineUsers()); //Avoid ConcurrentModificationException + for (OnlineUser user : onlineUsers) { + + if (user.getWebSocket().isOpen()) { + + if (user.isGuest()) { + + json.remove("c"); + try { + user.getWebSocket().getRemote().sendString((json.toJSONString())); + } catch (IOException e) { + e.printStackTrace(); + } + + } else { + try { + ControllableUnit unit = user.getUser().getControlledUnit(); + + //Send keyboard updated buffer + ArrayList 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().getRemote().sendString(json.toJSONString()); + } catch (NullPointerException | IOException e) { + e.printStackTrace(); + } + } + } + } + + } +} \ No newline at end of file diff --git a/Server/src/main/java/net/simon987/server/webserver/SocketServerDatabase.java b/Server/src/main/java/net/simon987/server/websocket/SocketServerDatabase.java similarity index 98% rename from Server/src/main/java/net/simon987/server/webserver/SocketServerDatabase.java rename to Server/src/main/java/net/simon987/server/websocket/SocketServerDatabase.java index 2e5a4da..e675e25 100644 --- a/Server/src/main/java/net/simon987/server/webserver/SocketServerDatabase.java +++ b/Server/src/main/java/net/simon987/server/websocket/SocketServerDatabase.java @@ -1,4 +1,4 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.ServerConfiguration; import net.simon987.server.io.DatabaseManager; diff --git a/Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java b/Server/src/main/java/net/simon987/server/websocket/TerrainRequestHandler.java similarity index 85% rename from Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java rename to Server/src/main/java/net/simon987/server/websocket/TerrainRequestHandler.java index 01e144f..42ce475 100644 --- a/Server/src/main/java/net/simon987/server/webserver/TerrainRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/websocket/TerrainRequestHandler.java @@ -1,4 +1,4 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.GameServer; import net.simon987.server.game.World; @@ -6,10 +6,12 @@ import net.simon987.server.logging.LogManager; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import java.io.IOException; + public class TerrainRequestHandler implements MessageHandler { @Override - public void handle(OnlineUser user, JSONObject json) { + public void handle(OnlineUser user, JSONObject json) throws IOException { if (json.get("t").equals("terrain") && json.containsKey("x") && json.containsKey("y") && json.containsKey("dimension")) { @@ -44,14 +46,14 @@ public class TerrainRequestHandler implements MessageHandler { response.put("terrain", terrain); response.put("size", world.getWorldSize()); - user.getWebSocket().send(response.toJSONString()); + user.getWebSocket().getRemote().sendString(response.toJSONString()); } else { //Uncharted World JSONObject response = new JSONObject(); response.put("t", "terrain"); response.put("ok", false); - user.getWebSocket().send(response.toJSONString()); + user.getWebSocket().getRemote().sendString((response.toJSONString())); } } } diff --git a/Server/src/main/java/net/simon987/server/webserver/UserInfoRequestHandler.java b/Server/src/main/java/net/simon987/server/websocket/UserInfoRequestHandler.java similarity index 84% rename from Server/src/main/java/net/simon987/server/webserver/UserInfoRequestHandler.java rename to Server/src/main/java/net/simon987/server/websocket/UserInfoRequestHandler.java index 178fe0b..c6dba4a 100644 --- a/Server/src/main/java/net/simon987/server/webserver/UserInfoRequestHandler.java +++ b/Server/src/main/java/net/simon987/server/websocket/UserInfoRequestHandler.java @@ -1,15 +1,17 @@ -package net.simon987.server.webserver; +package net.simon987.server.websocket; import net.simon987.server.GameServer; import net.simon987.server.game.GameObject; import net.simon987.server.logging.LogManager; import org.json.simple.JSONObject; +import java.io.IOException; + public class UserInfoRequestHandler implements MessageHandler { @Override - public void handle(OnlineUser user, JSONObject message) { + public void handle(OnlineUser user, JSONObject message) throws IOException { if (message.get("t").equals("userInfo")) { @@ -31,8 +33,7 @@ public class UserInfoRequestHandler implements MessageHandler { json.put("t", "userInfo"); json.put("maxWidth", GameServer.INSTANCE.getGameUniverse().getMaxWidth()); - user.getWebSocket().send(json.toJSONString()); - + user.getWebSocket().getRemote().sendString(json.toJSONString()); } } diff --git a/Server/src/main/resources/templates/account.vm b/Server/src/main/resources/templates/account.vm index 11cec16..9bbdbfd 100644 --- a/Server/src/main/resources/templates/account.vm +++ b/Server/src/main/resources/templates/account.vm @@ -9,47 +9,103 @@
-
Account - login & register
+
Account
-
Login
-
-
-
- + #if($session.attribute("username")) + ## ALREADY LOGGED IN +

Logged in as $session.attribute("username")

+ +
+ +
Change password
+ +
+ +
+ +
-
- +
+
+
+ +
+
+
+
+ +
+
+ + + + +
+ +
Debug information
+
+
CPU
+
$user.getCpu()
+ +
Code
+
$user.getUserCode()
+ +
Controlled unit
+

id: $user.getControlledUnit().getObjectId()

+

energy: $user.getControlledUnit().getEnergy()

+

x: $user.getControlledUnit().getX()

+

y: $user.getControlledUnit().getY()

+

console mode: $user.getControlledUnit().getConsoleMode()

+

kbBuffer size: $user.getControlledUnit().getKeyboardBuffer().size()

+
World
+
$user.getControlledUnit().getWorld()
+ #else + ## NOT LOGGED IN +
Login
+
+
+
+ +
- - - - -
- -
Register
-
-
- -
- +
+ +
-
- + + + + + +
+ +
Register
+
+
+ +
+ +
+ +
+ +
-
- - - - + + + #end
diff --git a/Server/src/main/resources/templates/header.vm b/Server/src/main/resources/templates/header.vm index d1b6d1f..e04a734 100644 --- a/Server/src/main/resources/templates/header.vm +++ b/Server/src/main/resources/templates/header.vm @@ -29,3 +29,12 @@
+ +
+ #foreach($msg in $session.attribute("messages")) +
×$msg.getMessage()
+ #end + $session.removeAttribute("messages") +
+