database work + serialization work + save pos
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
c085e34dbb
commit
58dc5333e6
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
--main table
|
-- main table
|
||||||
CREATE TABLE mainTable (propName VARCHAR PRIMARY KEY, propValue VARCHAR);
|
CREATE TABLE mainTable (propName VARCHAR PRIMARY KEY, propValue VARCHAR);
|
||||||
INSERT INTO mainTable (propName, propValue) VALUES ("ver","1");
|
INSERT INTO mainTable (propName, propValue) VALUES ("ver","1");
|
||||||
|
|
||||||
@ -7,3 +7,40 @@ INSERT INTO mainTable (propName, propValue) VALUES ("ver","1");
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- CHARACTERS
|
||||||
|
-- positions
|
||||||
|
CREATE TABLE charaWorldPositions (playerId INTEGER PRIMARY KEY, id INTEGER, posX INTEGER, posY INTEGER);
|
||||||
|
CREATE INDEX charaWorldPositionsIDIndex ON charaWorldPositions (id);
|
||||||
|
CREATE INDEX charaWorldPositionsPosIndex ON charaWorldPositions (posX, posY);
|
||||||
|
|
||||||
|
-- real positions of characters (ie player's characters)
|
||||||
|
CREATE TABLE charaRealPos (id INTEGER PRIMARY KEY NOT NULL, x REAL NOT NULL, y REAL NOT NULL, z REAL NOT NULL);
|
||||||
|
|
||||||
|
-- data
|
||||||
|
CREATE TABLE charaData (id INTEGER PRIMARY KEY AUTOINCREMENT, playerId INTEGER, dataVal VARCHAR);
|
||||||
|
CREATE INDEX charaDataIDIndex ON charaData (id);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- AUTH
|
||||||
|
-- accounts definition
|
||||||
|
CREATE TABLE accounts (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
username TEXT NOT NULL,
|
||||||
|
pwdhash TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
--positions
|
|
||||||
INSERT INTO structWorldPositions (structID,posX,posY) VALUES (0,10,10);
|
|
||||||
|
|
||||||
--data
|
|
||||||
INSERT INTO structData(structID,dataVal) VALUES(0,'{"localX"=10,"localY"=10}');
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
--structures
|
|
||||||
--positions
|
|
||||||
CREATE TABLE structWorldPositions (id INTEGER PRIMARY KEY, structID INTEGER, posX INTEGER, posY INTEGER);
|
|
||||||
CREATE INDEX structWorldPositionsIDIndex ON structWorldPositions (structID);
|
|
||||||
CREATE INDEX structWorldPositionsPosIndex ON structWorldPositions (posX, posY);
|
|
||||||
|
|
||||||
--data
|
|
||||||
CREATE TABLE structData (id INTEGER PRIMARY KEY, structID INTEGER, dataVal VARCHAR);
|
|
||||||
CREATE INDEX structDataIDIndex ON structData (structID);
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
--positions
|
|
||||||
DELETE FROM structWorldPositions WHERE structID=0;
|
|
||||||
|
|
||||||
--data
|
|
||||||
DELETE FROM structData WHERE structID=0;
|
|
||||||
@ -1 +0,0 @@
|
|||||||
SELECT * FROM structData WHERE structID IN (1, 2);
|
|
||||||
@ -1 +0,0 @@
|
|||||||
SELECT * FROM structData WHERE structID=0;
|
|
||||||
@ -1 +0,0 @@
|
|||||||
SELECT * FROM structWorldPositions WHERE posX = 10 AND posY = 10;
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
--positions
|
|
||||||
INSERT INTO townWorldPositions (townID,posX,posY) VALUES (0,10,10);
|
|
||||||
|
|
||||||
--data
|
|
||||||
INSERT INTO townData(townID,propName,propValue) VALUES(0,"name","someTown");
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
--towns
|
|
||||||
--positions
|
|
||||||
CREATE TABLE townWorldPositions (id INTEGER PRIMARY KEY, townID INTEGER, posX INTEGER, posY INTEGER);
|
|
||||||
CREATE INDEX townWorldPositionsIDIndex ON townWorldPositions (townID);
|
|
||||||
CREATE INDEX townWorldPositionsPosIndex ON townWorldPositions (posX, posY);
|
|
||||||
|
|
||||||
--data
|
|
||||||
CREATE TABLE townData (id INTEGER PRIMARY KEY, townID INTEGER, dataVal VARCHAR);
|
|
||||||
CREATE INDEX townDataIDIndex ON townData (townID);
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
--positions
|
|
||||||
DELETE FROM townWorldPositions WHERE townID=0;
|
|
||||||
|
|
||||||
--data
|
|
||||||
DELETE FROM townData WHERE townID=0;
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
--given x=10, y=11
|
|
||||||
SELECT townID FROM townWorldPositions WHERE posX = 10 AND posY = 11;
|
|
||||||
@ -1493,6 +1493,14 @@ Fix yoga not applying on item drop window creation
|
|||||||
Fix client not destroying item on remove from inventory
|
Fix client not destroying item on remove from inventory
|
||||||
Tests for above bugs
|
Tests for above bugs
|
||||||
Fix rendering 3rd person model-attached entities drawing when in first person
|
Fix rendering 3rd person model-attached entities drawing when in first person
|
||||||
|
fix database handling REAL type
|
||||||
|
CharacterService first implementation (abstracts away database calls from functions)
|
||||||
|
Store player entity position on save
|
||||||
|
Cull old SQL
|
||||||
|
Clarify content serialization pipelines for character vs non-character entities
|
||||||
|
Server send disconnect packet on disconnection
|
||||||
|
Associate each server connection with a character ID
|
||||||
|
Code cleanup
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -106,8 +106,9 @@ public class MenuGeneratorsInGame {
|
|||||||
|
|
||||||
//Save
|
//Save
|
||||||
{
|
{
|
||||||
Button button = Button.createButton("Save", () -> {
|
Button button = Button.createButton("Save and Quit", () -> {
|
||||||
SaveUtils.overwriteSave(Globals.currentSave.getName());
|
SaveUtils.overwriteSave(Globals.currentSave.getName());
|
||||||
|
Globals.signalSystem.post(SignalType.ENGINE_RETURN_TO_TITLE);
|
||||||
});
|
});
|
||||||
button.setMarginTop(BUTTON_MARGIN);
|
button.setMarginTop(BUTTON_MARGIN);
|
||||||
button.setMarginLeft(BUTTON_MARGIN);
|
button.setMarginLeft(BUTTON_MARGIN);
|
||||||
@ -116,7 +117,7 @@ public class MenuGeneratorsInGame {
|
|||||||
|
|
||||||
//Quit
|
//Quit
|
||||||
{
|
{
|
||||||
Button button = Button.createButton("Quit", () -> {
|
Button button = Button.createButton("Shutdown", () -> {
|
||||||
Main.running = false;
|
Main.running = false;
|
||||||
});
|
});
|
||||||
button.setMarginTop(BUTTON_MARGIN);
|
button.setMarginTop(BUTTON_MARGIN);
|
||||||
|
|||||||
@ -326,6 +326,7 @@ public class EntityDataStrings {
|
|||||||
* Server-specific btrees
|
* Server-specific btrees
|
||||||
*/
|
*/
|
||||||
public static final String TREE_SERVERPLAYERVIEWDIR = "treeServerPlayerViewDir";
|
public static final String TREE_SERVERPLAYERVIEWDIR = "treeServerPlayerViewDir";
|
||||||
|
public static final String TREE_SERVERCHARACTERDATA = "treeServerCharacterData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Physics synchronization
|
* Physics synchronization
|
||||||
|
|||||||
@ -0,0 +1,74 @@
|
|||||||
|
package electrosphere.entity.state.server;
|
||||||
|
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.EntityDataStrings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores data that associated an entity to a character in the character database
|
||||||
|
*/
|
||||||
|
public class ServerCharacterData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The character id
|
||||||
|
*/
|
||||||
|
private int characterId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The associated entity
|
||||||
|
*/
|
||||||
|
private Entity parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param parent
|
||||||
|
* @param characterId
|
||||||
|
*/
|
||||||
|
private ServerCharacterData(Entity parent, int characterId){
|
||||||
|
this.parent = parent;
|
||||||
|
this.characterId = characterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches a ServerPlayerViewDirTree to a given entity
|
||||||
|
* @param entity The entity to add to
|
||||||
|
*/
|
||||||
|
public static void attachServerPlayerViewDirTree(Entity entity, int characterId){
|
||||||
|
ServerCharacterData tree = new ServerCharacterData(entity, characterId);
|
||||||
|
entity.putData(EntityDataStrings.TREE_SERVERCHARACTERDATA, tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the entity has associated character data
|
||||||
|
* @param entity The entity
|
||||||
|
* @return true if the entity contains character data, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean hasServerPlayerCharacterDataTree(Entity entity){
|
||||||
|
return entity.containsKey(EntityDataStrings.TREE_SERVERCHARACTERDATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the character data on the entity
|
||||||
|
* @param entity The entity
|
||||||
|
* @return The ServerCharacterData
|
||||||
|
*/
|
||||||
|
public static ServerCharacterData getServerCharacterData(Entity entity){
|
||||||
|
return (ServerCharacterData)entity.getData(EntityDataStrings.TREE_SERVERCHARACTERDATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the associated character id for this entity
|
||||||
|
* @return The id
|
||||||
|
*/
|
||||||
|
public int getCharacterId() {
|
||||||
|
return characterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the parent entity of this data
|
||||||
|
* @return The parent entity
|
||||||
|
*/
|
||||||
|
public Entity getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -835,6 +835,9 @@ public class CommonEntityUtils {
|
|||||||
* @param type The type
|
* @param type The type
|
||||||
*/
|
*/
|
||||||
private static void setTyping(Entity entity, CommonEntityType type){
|
private static void setTyping(Entity entity, CommonEntityType type){
|
||||||
|
if(type == null){
|
||||||
|
throw new Error("Provided null typing!");
|
||||||
|
}
|
||||||
if(type instanceof CreatureData){
|
if(type instanceof CreatureData){
|
||||||
CommonEntityUtils.setEntityType(entity, EntityType.CREATURE);
|
CommonEntityUtils.setEntityType(entity, EntityType.CREATURE);
|
||||||
CommonEntityUtils.setEntitySubtype(entity, type.getId());
|
CommonEntityUtils.setEntitySubtype(entity, type.getId());
|
||||||
|
|||||||
@ -482,14 +482,29 @@ public class CreatureUtils {
|
|||||||
return (String)CommonEntityUtils.getEntitySubtype(e);
|
return (String)CommonEntityUtils.getEntitySubtype(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the associated player ID that controls this entity
|
||||||
|
* @param e The entity
|
||||||
|
* @return The player ID
|
||||||
|
*/
|
||||||
public static int getControllerPlayerId(Entity e){
|
public static int getControllerPlayerId(Entity e){
|
||||||
return (int)e.getData(EntityDataStrings.DATA_STRING_CREATURE_CONTROLLER_PLAYER_ID);
|
return (int)e.getData(EntityDataStrings.DATA_STRING_CREATURE_CONTROLLER_PLAYER_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the associated player ID that controls this creature
|
||||||
|
* @param e The entity
|
||||||
|
* @param id The id
|
||||||
|
*/
|
||||||
public static void setControllerPlayerId(Entity e, int id){
|
public static void setControllerPlayerId(Entity e, int id){
|
||||||
e.putData(EntityDataStrings.DATA_STRING_CREATURE_CONTROLLER_PLAYER_ID, id);
|
e.putData(EntityDataStrings.DATA_STRING_CREATURE_CONTROLLER_PLAYER_ID, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this entity has a player that controls it
|
||||||
|
* @param e The entity
|
||||||
|
* @return true if a player controls it, false otherwise
|
||||||
|
*/
|
||||||
public static boolean hasControllerPlayerId(Entity e){
|
public static boolean hasControllerPlayerId(Entity e){
|
||||||
return e.containsKey(EntityDataStrings.DATA_STRING_CREATURE_CONTROLLER_PLAYER_ID);
|
return e.containsKey(EntityDataStrings.DATA_STRING_CREATURE_CONTROLLER_PLAYER_ID);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package electrosphere.net.client.protocol;
|
package electrosphere.net.client.protocol;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.net.parser.net.message.ServerMessage;
|
import electrosphere.net.parser.net.message.ServerMessage;
|
||||||
import electrosphere.net.template.ClientProtocolTemplate;
|
import electrosphere.net.template.ClientProtocolTemplate;
|
||||||
|
|
||||||
@ -24,6 +25,9 @@ public class ServerProtocol implements ClientProtocolTemplate<ServerMessage> {
|
|||||||
//let the networking loop know we received a pong message
|
//let the networking loop know we received a pong message
|
||||||
Globals.clientConnection.markReceivedPongMessage();
|
Globals.clientConnection.markReceivedPongMessage();
|
||||||
break;
|
break;
|
||||||
|
case DISCONNECT: {
|
||||||
|
LoggerInterface.loggerNetworking.WARNING("Server sent signal to disconnect!");
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -255,6 +255,11 @@ public abstract class NetworkMessage {
|
|||||||
rVal = ServerMessage.parsePongMessage(byteBuffer,pool);
|
rVal = ServerMessage.parsePongMessage(byteBuffer,pool);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TypeBytes.SERVER_MESSAGE_TYPE_DISCONNECT:
|
||||||
|
if(ServerMessage.canParseMessage(byteBuffer,secondByte)){
|
||||||
|
rVal = ServerMessage.parseDisconnectMessage(byteBuffer,pool);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TypeBytes.MESSAGE_TYPE_AUTH:
|
case TypeBytes.MESSAGE_TYPE_AUTH:
|
||||||
|
|||||||
@ -9,6 +9,7 @@ public class ServerMessage extends NetworkMessage {
|
|||||||
public enum ServerMessageType {
|
public enum ServerMessageType {
|
||||||
PING,
|
PING,
|
||||||
PONG,
|
PONG,
|
||||||
|
DISCONNECT,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,6 +65,12 @@ public class ServerMessage extends NetworkMessage {
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
case TypeBytes.SERVER_MESSAGE_TYPE_DISCONNECT:
|
||||||
|
if(byteBuffer.getRemaining() >= TypeBytes.SERVER_MESSAGE_TYPE_DISCONNECT_SIZE){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -106,6 +113,25 @@ public class ServerMessage extends NetworkMessage {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a message of type Disconnect
|
||||||
|
*/
|
||||||
|
public static ServerMessage parseDisconnectMessage(CircularByteBuffer byteBuffer, MessagePool pool){
|
||||||
|
ServerMessage rVal = (ServerMessage)pool.get(MessageType.SERVER_MESSAGE);
|
||||||
|
rVal.messageType = ServerMessageType.DISCONNECT;
|
||||||
|
ServerMessage.stripPacketHeader(byteBuffer);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a message of type Disconnect
|
||||||
|
*/
|
||||||
|
public static ServerMessage constructDisconnectMessage(){
|
||||||
|
ServerMessage rVal = new ServerMessage(ServerMessageType.DISCONNECT);
|
||||||
|
rVal.serialize();
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void serialize(){
|
void serialize(){
|
||||||
switch(this.messageType){
|
switch(this.messageType){
|
||||||
@ -123,6 +149,13 @@ public class ServerMessage extends NetworkMessage {
|
|||||||
//entity messaage header
|
//entity messaage header
|
||||||
rawBytes[1] = TypeBytes.SERVER_MESSAGE_TYPE_PONG;
|
rawBytes[1] = TypeBytes.SERVER_MESSAGE_TYPE_PONG;
|
||||||
break;
|
break;
|
||||||
|
case DISCONNECT:
|
||||||
|
rawBytes = new byte[2];
|
||||||
|
//message header
|
||||||
|
rawBytes[0] = TypeBytes.MESSAGE_TYPE_SERVER;
|
||||||
|
//entity messaage header
|
||||||
|
rawBytes[1] = TypeBytes.SERVER_MESSAGE_TYPE_DISCONNECT;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
serialized = true;
|
serialized = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,11 +103,13 @@ public class TypeBytes {
|
|||||||
*/
|
*/
|
||||||
public static final byte SERVER_MESSAGE_TYPE_PING = 0;
|
public static final byte SERVER_MESSAGE_TYPE_PING = 0;
|
||||||
public static final byte SERVER_MESSAGE_TYPE_PONG = 1;
|
public static final byte SERVER_MESSAGE_TYPE_PONG = 1;
|
||||||
|
public static final byte SERVER_MESSAGE_TYPE_DISCONNECT = 2;
|
||||||
/*
|
/*
|
||||||
Server packet sizes
|
Server packet sizes
|
||||||
*/
|
*/
|
||||||
public static final byte SERVER_MESSAGE_TYPE_PING_SIZE = 2;
|
public static final byte SERVER_MESSAGE_TYPE_PING_SIZE = 2;
|
||||||
public static final byte SERVER_MESSAGE_TYPE_PONG_SIZE = 2;
|
public static final byte SERVER_MESSAGE_TYPE_PONG_SIZE = 2;
|
||||||
|
public static final byte SERVER_MESSAGE_TYPE_DISCONNECT_SIZE = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Auth subcategories
|
Auth subcategories
|
||||||
|
|||||||
@ -28,32 +28,46 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
public class Server implements Runnable {
|
public class Server implements Runnable {
|
||||||
|
|
||||||
//tracks whether the server is open or not
|
/**
|
||||||
|
* tracks whether the server is open or not
|
||||||
|
*/
|
||||||
private boolean isOpen = false;
|
private boolean isOpen = false;
|
||||||
|
|
||||||
//the port the server is running on
|
/**
|
||||||
int port;
|
* the port the server is running on
|
||||||
|
*/
|
||||||
|
private int port;
|
||||||
|
|
||||||
//the socket for the server
|
/**
|
||||||
ServerSocket serverSocket;
|
* the socket for the server
|
||||||
|
*/
|
||||||
|
private ServerSocket serverSocket;
|
||||||
|
|
||||||
//Used to synchronize additions/subtractions to the connections stored by this server
|
/**
|
||||||
Semaphore connectListLock = new Semaphore(1);
|
* Used to synchronize additions/subtractions to the connections stored by this server
|
||||||
|
*/
|
||||||
|
private Semaphore connectListLock = new Semaphore(1);
|
||||||
|
|
||||||
//map of socket->connection
|
/**
|
||||||
Map<Socket,ServerConnectionHandler> socketConnectionMap = new HashMap<Socket,ServerConnectionHandler>();
|
* map of socket->connection
|
||||||
|
*/
|
||||||
|
private Map<Socket,ServerConnectionHandler> socketConnectionMap = new HashMap<Socket,ServerConnectionHandler>();
|
||||||
|
|
||||||
//the list of active connections
|
/**
|
||||||
List<ServerConnectionHandler> activeConnections = new LinkedList<ServerConnectionHandler>();
|
* the list of active connections
|
||||||
|
*/
|
||||||
|
private List<ServerConnectionHandler> activeConnections = new LinkedList<ServerConnectionHandler>();
|
||||||
|
|
||||||
//The list of connections to clean up
|
/**
|
||||||
List<ServerConnectionHandler> connectionsToCleanup = new CopyOnWriteArrayList<ServerConnectionHandler>();
|
* The list of connections to clean up
|
||||||
|
*/
|
||||||
|
private List<ServerConnectionHandler> connectionsToCleanup = new CopyOnWriteArrayList<ServerConnectionHandler>();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inits the server
|
* Inits the server
|
||||||
*/
|
*/
|
||||||
void initServer(){
|
private void initServer(){
|
||||||
// clientMap = new HashMap<String,ServerConnectionHandler>();
|
// clientMap = new HashMap<String,ServerConnectionHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +81,7 @@ public class Server implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
initServer();
|
this.initServer();
|
||||||
try {
|
try {
|
||||||
serverSocket = new ServerSocket(port);
|
serverSocket = new ServerSocket(port);
|
||||||
//if we set port to 0, java searches for any available port to open
|
//if we set port to 0, java searches for any available port to open
|
||||||
@ -204,6 +218,24 @@ public class Server implements Runnable {
|
|||||||
this.connectListLock.release();
|
this.connectListLock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves state from the server connections and shuts down the connections
|
||||||
|
*/
|
||||||
|
public void saveAndClose(){
|
||||||
|
this.connectListLock.acquireUninterruptibly();
|
||||||
|
//store each player's character
|
||||||
|
for(ServerConnectionHandler connection : this.activeConnections){
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
//close the server
|
||||||
|
try {
|
||||||
|
this.serverSocket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LoggerInterface.loggerNetworking.ERROR(e);
|
||||||
|
}
|
||||||
|
this.connectListLock.release();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether the server is open or not
|
* Gets whether the server is open or not
|
||||||
* @return true if is open, false otherwise
|
* @return true if is open, false otherwise
|
||||||
|
|||||||
@ -25,66 +25,112 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*/
|
*/
|
||||||
public class ServerConnectionHandler implements Runnable {
|
public class ServerConnectionHandler implements Runnable {
|
||||||
|
|
||||||
//local carrier variables
|
//thresholds for determining when to send pings and when a client has disconnected
|
||||||
|
static final long SEND_PING_THRESHOLD = 3000;
|
||||||
|
static final long PING_DISCONNECT_THRESHOLD = 60 * 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* local carrier variables
|
||||||
|
*/
|
||||||
boolean local = false;
|
boolean local = false;
|
||||||
|
|
||||||
//socket carrier variables
|
/**
|
||||||
|
* socket carrier variables
|
||||||
|
*/
|
||||||
Socket socket;
|
Socket socket;
|
||||||
|
|
||||||
//the streams for the connection
|
//the streams for the connection
|
||||||
// CryptoInputStream inputStream;
|
// CryptoInputStream inputStream;
|
||||||
// CryptoOutputStream outputStream;
|
// CryptoOutputStream outputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The input stream for packets
|
* The input stream for packets
|
||||||
*/
|
*/
|
||||||
InputStream inputStream;
|
InputStream inputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The output stream for packets
|
* The output stream for packets
|
||||||
*/
|
*/
|
||||||
OutputStream outputStream;
|
OutputStream outputStream;
|
||||||
|
|
||||||
//the network parser for the streams
|
/**
|
||||||
|
* the network parser for the streams
|
||||||
|
*/
|
||||||
NetworkParser networkParser;
|
NetworkParser networkParser;
|
||||||
|
|
||||||
//initialized status
|
/**
|
||||||
|
* initialized status
|
||||||
|
*/
|
||||||
boolean initialized;
|
boolean initialized;
|
||||||
//authentication status
|
|
||||||
|
/**
|
||||||
|
* authentication status
|
||||||
|
*/
|
||||||
boolean isAuthenticated = false;
|
boolean isAuthenticated = false;
|
||||||
|
|
||||||
//the player id
|
/**
|
||||||
|
* the player id
|
||||||
|
*/
|
||||||
int playerID;
|
int playerID;
|
||||||
//the player's entity id
|
|
||||||
|
/**
|
||||||
|
* the player's entity id
|
||||||
|
*/
|
||||||
int playerEntityID;
|
int playerEntityID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the character that is associated with the player's entity
|
||||||
|
*/
|
||||||
|
int characterId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks whether this connection is still communicating with the client
|
* Tracks whether this connection is still communicating with the client
|
||||||
*/
|
*/
|
||||||
boolean isConnected = true;
|
boolean isConnected = true;
|
||||||
|
|
||||||
//the creature template associated with this player
|
/**
|
||||||
|
* the creature template associated with this player
|
||||||
|
*/
|
||||||
CreatureTemplate currentCreatureTemplate;
|
CreatureTemplate currentCreatureTemplate;
|
||||||
|
|
||||||
//the server protocol object associated with this player
|
/**
|
||||||
|
* the server protocol object associated with this player
|
||||||
|
*/
|
||||||
MessageProtocol messageProtocol;
|
MessageProtocol messageProtocol;
|
||||||
|
|
||||||
//thresholds for determining when to send pings and when a client has disconnected
|
/**
|
||||||
static final long SEND_PING_THRESHOLD = 3000;
|
* Keeps track of the last time this connection received a ping from the client
|
||||||
static final long PING_DISCONNECT_THRESHOLD = 60 * 1000;
|
*/
|
||||||
//used to keep track of ping/pong messages with client
|
|
||||||
long lastPingTime = 0;
|
long lastPingTime = 0;
|
||||||
|
/**
|
||||||
|
* Keeps track of the last time this connection received a pong from the client
|
||||||
|
*/
|
||||||
long lastPongTime = 0;
|
long lastPongTime = 0;
|
||||||
//flag to disconnect due to pipe break
|
|
||||||
|
/**
|
||||||
|
* flag to disconnect due to pipe break
|
||||||
|
*/
|
||||||
boolean socketException = false;
|
boolean socketException = false;
|
||||||
|
|
||||||
|
|
||||||
//debug netmonitor stuff
|
/**
|
||||||
|
* debug netmonitor stuff
|
||||||
|
*/
|
||||||
String netMonitorHandle;
|
String netMonitorHandle;
|
||||||
//Used to copy messages from network parser to NetMonitor
|
|
||||||
|
/**
|
||||||
|
* Used to copy messages from network parser to NetMonitor
|
||||||
|
*/
|
||||||
List<NetworkMessage> netMonitorCache = new LinkedList<NetworkMessage>();
|
List<NetworkMessage> netMonitorCache = new LinkedList<NetworkMessage>();
|
||||||
|
|
||||||
//the lock used for synchronizing the synchronous message queue
|
/**
|
||||||
|
* the lock used for synchronizing the synchronous message queue
|
||||||
|
*/
|
||||||
Semaphore synchronousMessageLock = new Semaphore(1);
|
Semaphore synchronousMessageLock = new Semaphore(1);
|
||||||
//the queue of synchonous network messages
|
|
||||||
|
/**
|
||||||
|
* the queue of synchonous network messages
|
||||||
|
*/
|
||||||
List<NetworkMessage> synchronousMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
|
List<NetworkMessage> synchronousMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -198,7 +244,7 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
//
|
//
|
||||||
//parse messages both incoming and outgoing
|
//parse messages both incoming and outgoing
|
||||||
try {
|
try {
|
||||||
receivedMessageThisLoop = parseMessages();
|
receivedMessageThisLoop = this.parseMessages();
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
//if we get a SocketException broken pipe (basically the client dc'd without telling us)
|
//if we get a SocketException broken pipe (basically the client dc'd without telling us)
|
||||||
//set flag to disconnect client
|
//set flag to disconnect client
|
||||||
@ -228,7 +274,7 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
//basically if we haven't sent a ping in a while, send one
|
//basically if we haven't sent a ping in a while, send one
|
||||||
if(currentTime - lastPingTime > SEND_PING_THRESHOLD){
|
if(currentTime - lastPingTime > SEND_PING_THRESHOLD){
|
||||||
addMessagetoOutgoingQueue(ServerMessage.constructPingMessage());
|
this.addMessagetoOutgoingQueue(ServerMessage.constructPingMessage());
|
||||||
lastPingTime = currentTime;
|
lastPingTime = currentTime;
|
||||||
if(lastPongTime == 0){
|
if(lastPongTime == 0){
|
||||||
lastPongTime = lastPingTime;
|
lastPongTime = lastPingTime;
|
||||||
@ -245,14 +291,14 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
//disconnected from the server
|
//disconnected from the server
|
||||||
LoggerInterface.loggerNetworking.WARNING("Client timeout");
|
LoggerInterface.loggerNetworking.WARNING("Client timeout");
|
||||||
//run disconnect routine
|
//run disconnect routine
|
||||||
disconnect();
|
this.disconnect();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(this.socketException == true){
|
if(this.socketException == true){
|
||||||
//disconnected from the server
|
//disconnected from the server
|
||||||
LoggerInterface.loggerNetworking.WARNING("Client disconnected");
|
LoggerInterface.loggerNetworking.WARNING("Client disconnected");
|
||||||
//run disconnect routine
|
//run disconnect routine
|
||||||
disconnect();
|
this.disconnect();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,7 +312,7 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
* @throws SocketException
|
* @throws SocketException
|
||||||
* @return true if connection is alive, false otherwise
|
* @return true if connection is alive, false otherwise
|
||||||
*/
|
*/
|
||||||
boolean parseMessages() throws SocketException, IOException {
|
private boolean parseMessages() throws SocketException, IOException {
|
||||||
boolean rVal = false;
|
boolean rVal = false;
|
||||||
//
|
//
|
||||||
//Read in messages
|
//Read in messages
|
||||||
@ -333,15 +379,27 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
this.messageProtocol.handleSyncMessages();
|
this.messageProtocol.handleSyncMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the player's id
|
||||||
|
* @return The player's id
|
||||||
|
*/
|
||||||
public int getPlayerId(){
|
public int getPlayerId(){
|
||||||
return playerID;
|
return playerID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the player's entity's id
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
public void setPlayerEntityId(int id){
|
public void setPlayerEntityId(int id){
|
||||||
LoggerInterface.loggerNetworking.DEBUG("Set player(" + this.playerID + ")'s entity ID to be " + id);
|
LoggerInterface.loggerNetworking.DEBUG("Set player(" + this.playerID + ")'s entity ID to be " + id);
|
||||||
playerEntityID = id;
|
playerEntityID = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the player's entity's id
|
||||||
|
* @return The id
|
||||||
|
*/
|
||||||
public int getPlayerEntityId(){
|
public int getPlayerEntityId(){
|
||||||
return playerEntityID;
|
return playerEntityID;
|
||||||
}
|
}
|
||||||
@ -374,22 +432,14 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
return this.socket;
|
return this.socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a message to the outgoing queue
|
||||||
|
* @param message The message
|
||||||
|
*/
|
||||||
public void addMessagetoOutgoingQueue(NetworkMessage message){
|
public void addMessagetoOutgoingQueue(NetworkMessage message){
|
||||||
networkParser.addOutgoingMessage(message);
|
networkParser.addOutgoingMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isConnectionPlayerEntity(int id){
|
|
||||||
return id == this.playerEntityID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if running both client and server in same instance of the app and this is the player for that instance of the app
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean isServerClient(){
|
|
||||||
return Globals.RUN_SERVER && Globals.RUN_CLIENT && Globals.clientPlayer != null && this.playerID == Globals.clientPlayer.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current creature template for the connection
|
* Sets the current creature template for the connection
|
||||||
* @param currentCreatureTemplate The new creature template
|
* @param currentCreatureTemplate The new creature template
|
||||||
@ -406,6 +456,9 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
return this.currentCreatureTemplate;
|
return this.currentCreatureTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks that this connection received a pong message
|
||||||
|
*/
|
||||||
public void markReceivedPongMessage(){
|
public void markReceivedPongMessage(){
|
||||||
lastPongTime = System.currentTimeMillis();
|
lastPongTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
@ -413,8 +466,21 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* Routine to run when the client disconnects
|
* Routine to run when the client disconnects
|
||||||
*/
|
*/
|
||||||
private void disconnect(){
|
protected void disconnect(){
|
||||||
//close socket
|
//close socket
|
||||||
|
this.synchronousMessageLock.acquireUninterruptibly();
|
||||||
|
|
||||||
|
//queue message to tell client it disconnected
|
||||||
|
this.networkParser.addOutgoingMessage(ServerMessage.constructDisconnectMessage());
|
||||||
|
|
||||||
|
//flush outgoing messages
|
||||||
|
try {
|
||||||
|
this.networkParser.pushMessagesOut();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LoggerInterface.loggerNetworking.ERROR(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//close the socket
|
||||||
if(socket != null && socket.isConnected()){
|
if(socket != null && socket.isConnected()){
|
||||||
try {
|
try {
|
||||||
socket.close();
|
socket.close();
|
||||||
@ -422,6 +488,8 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
LoggerInterface.loggerNetworking.ERROR("Error closing socket", e);
|
LoggerInterface.loggerNetworking.ERROR("Error closing socket", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.synchronousMessageLock.release();
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
//add connection to server list of connections to cleanup
|
//add connection to server list of connections to cleanup
|
||||||
if(Globals.server != null){
|
if(Globals.server != null){
|
||||||
@ -440,4 +508,22 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
return this.networkParser.getNumberOfBytesRead();
|
return this.networkParser.getNumberOfBytesRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id of the character associated with the player's entity
|
||||||
|
* @return The character's id
|
||||||
|
*/
|
||||||
|
public int getCharacterId() {
|
||||||
|
return characterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the character associated with the player's entity
|
||||||
|
* @param characterId The character's id
|
||||||
|
*/
|
||||||
|
public void setCharacterId(int characterId) {
|
||||||
|
this.characterId = characterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package electrosphere.net.server.protocol;
|
package electrosphere.net.server.protocol;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@ -24,10 +23,9 @@ import electrosphere.net.parser.net.message.PlayerMessage;
|
|||||||
import electrosphere.net.server.ServerConnectionHandler;
|
import electrosphere.net.server.ServerConnectionHandler;
|
||||||
import electrosphere.net.server.player.Player;
|
import electrosphere.net.server.player.Player;
|
||||||
import electrosphere.net.template.ServerProtocolTemplate;
|
import electrosphere.net.template.ServerProtocolTemplate;
|
||||||
|
import electrosphere.server.character.CharacterService;
|
||||||
import electrosphere.server.character.PlayerCharacterCreation;
|
import electrosphere.server.character.PlayerCharacterCreation;
|
||||||
import electrosphere.server.datacell.Realm;
|
import electrosphere.server.datacell.Realm;
|
||||||
import electrosphere.server.db.DatabaseResult;
|
|
||||||
import electrosphere.server.db.DatabaseResultRow;
|
|
||||||
import electrosphere.util.Utilities;
|
import electrosphere.util.Utilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,18 +43,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
|
|||||||
switch(message.getMessageSubtype()){
|
switch(message.getMessageSubtype()){
|
||||||
case REQUESTCHARACTERLIST: {
|
case REQUESTCHARACTERLIST: {
|
||||||
Gson gson = new Gson();
|
Gson gson = new Gson();
|
||||||
List<CharacterDescription> characters = new LinkedList<CharacterDescription>();
|
List<CharacterDescription> characters = CharacterService.getCharacters(connectionHandler.getPlayer().getDBID());
|
||||||
DatabaseResult result = Globals.dbController.executePreparedQuery("SELECT id, dataVal FROM charaData WHERE playerId=?;",connectionHandler.getPlayer().getDBID());
|
|
||||||
if(result.hasResult()){
|
|
||||||
//if we get a valid response from the database, check that it actually matches hashes
|
|
||||||
for(DatabaseResultRow row : result){
|
|
||||||
CharacterDescription description = new CharacterDescription();
|
|
||||||
CreatureTemplate template = gson.fromJson(row.getAsString("dataVal"),CreatureTemplate.class);
|
|
||||||
description.setTemplate(template);
|
|
||||||
description.setId(row.getAsInteger("id") + "");
|
|
||||||
characters.add(description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClientCharacterListDTO dto = new ClientCharacterListDTO();
|
ClientCharacterListDTO dto = new ClientCharacterListDTO();
|
||||||
dto.setCharacters(characters);
|
dto.setCharacters(characters);
|
||||||
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCharacterListMessage(gson.toJson(dto)));
|
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCharacterListMessage(gson.toJson(dto)));
|
||||||
@ -74,11 +61,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
|
|||||||
case REQUESTCREATECHARACTER: {
|
case REQUESTCREATECHARACTER: {
|
||||||
CreatureTemplate template = Utilities.deserialize(message.getdata(), CreatureTemplate.class);
|
CreatureTemplate template = Utilities.deserialize(message.getdata(), CreatureTemplate.class);
|
||||||
if(template != null){
|
if(template != null){
|
||||||
Globals.dbController.executePreparedStatement(
|
CharacterService.createCharacter(template, connectionHandler.getPlayer().getDBID());
|
||||||
"INSERT INTO charaData (playerId,dataVal) VALUES (?,?);",
|
|
||||||
connectionHandler.getPlayer().getDBID(),
|
|
||||||
new Gson().toJson(template)
|
|
||||||
);
|
|
||||||
connectionHandler.setCreatureTemplate(Utilities.deserialize(message.getdata(), CreatureTemplate.class));
|
connectionHandler.setCreatureTemplate(Utilities.deserialize(message.getdata(), CreatureTemplate.class));
|
||||||
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCreateCharacterSuccessMessage());
|
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCreateCharacterSuccessMessage());
|
||||||
} else {
|
} else {
|
||||||
@ -111,17 +94,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
|
|||||||
* @return THe player's entity
|
* @return THe player's entity
|
||||||
*/
|
*/
|
||||||
static Entity spawnEntityForClient(ServerConnectionHandler connectionHandler, int id){
|
static Entity spawnEntityForClient(ServerConnectionHandler connectionHandler, int id){
|
||||||
if(id != CharacterProtocol.SPAWN_EXISTING_TEMPLATE){
|
connectionHandler.setCharacterId(id);
|
||||||
DatabaseResult result = Globals.dbController.executePreparedQuery("SELECT id, dataVal FROM charaData WHERE playerId=? AND id=?;",connectionHandler.getPlayer().getDBID(), id);
|
|
||||||
if(result.hasResult()){
|
|
||||||
Gson gson = new Gson();
|
|
||||||
//if we get a valid response from the database, check that it actually matches hashes
|
|
||||||
for(DatabaseResultRow row : result){
|
|
||||||
CreatureTemplate template = gson.fromJson(row.getAsString("dataVal"),CreatureTemplate.class);
|
|
||||||
connectionHandler.setCreatureTemplate(template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Entity rVal = PlayerCharacterCreation.spawnPlayerCharacter(connectionHandler);
|
Entity rVal = PlayerCharacterCreation.spawnPlayerCharacter(connectionHandler);
|
||||||
Realm realm = Globals.playerManager.getPlayerRealm(connectionHandler.getPlayer());
|
Realm realm = Globals.playerManager.getPlayerRealm(connectionHandler.getPlayer());
|
||||||
Vector3d spawnPoint = PlayerCharacterCreation.solveSpawnPoint(realm, connectionHandler);
|
Vector3d spawnPoint = PlayerCharacterCreation.solveSpawnPoint(realm, connectionHandler);
|
||||||
|
|||||||
@ -9,18 +9,23 @@ import electrosphere.net.template.ServerProtocolTemplate;
|
|||||||
*/
|
*/
|
||||||
public class ServerProtocol implements ServerProtocolTemplate<ServerMessage> {
|
public class ServerProtocol implements ServerProtocolTemplate<ServerMessage> {
|
||||||
|
|
||||||
//the connection handler associated with this protocol object
|
/**
|
||||||
|
* the connection handler associated with this protocol object
|
||||||
|
*/
|
||||||
ServerConnectionHandler connectionHandler;
|
ServerConnectionHandler connectionHandler;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
|
public ServerMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
|
||||||
switch(message.getMessageSubtype()){
|
switch(message.getMessageSubtype()){
|
||||||
case PING:
|
case PING: {
|
||||||
connectionHandler.addMessagetoOutgoingQueue(ServerMessage.constructPongMessage());
|
connectionHandler.addMessagetoOutgoingQueue(ServerMessage.constructPongMessage());
|
||||||
break;
|
} break;
|
||||||
case PONG:
|
case PONG: {
|
||||||
connectionHandler.markReceivedPongMessage();
|
connectionHandler.markReceivedPongMessage();
|
||||||
|
} break;
|
||||||
|
case DISCONNECT:
|
||||||
|
//silently ignore
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -29,6 +34,7 @@ public class ServerProtocol implements ServerProtocolTemplate<ServerMessage> {
|
|||||||
@Override
|
@Override
|
||||||
public void handleSyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
|
public void handleSyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
|
||||||
switch(message.getMessageSubtype()){
|
switch(message.getMessageSubtype()){
|
||||||
|
case DISCONNECT:
|
||||||
case PING:
|
case PING:
|
||||||
case PONG:
|
case PONG:
|
||||||
//silently ignore
|
//silently ignore
|
||||||
|
|||||||
@ -0,0 +1,124 @@
|
|||||||
|
package electrosphere.server.character;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import electrosphere.client.entity.character.CharacterDescription;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.EntityUtils;
|
||||||
|
import electrosphere.entity.state.server.ServerCharacterData;
|
||||||
|
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
|
||||||
|
import electrosphere.entity.types.creature.CreatureTemplate;
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
import electrosphere.server.db.DatabaseResult;
|
||||||
|
import electrosphere.server.db.DatabaseResultRow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for interacting with macro-level characters
|
||||||
|
*/
|
||||||
|
public class CharacterService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a character in the database
|
||||||
|
* @param template The creature template for the character
|
||||||
|
* @param playerId The player's id
|
||||||
|
*/
|
||||||
|
public static void createCharacter(CreatureTemplate template, int playerId){
|
||||||
|
Globals.dbController.executePreparedStatement(
|
||||||
|
"INSERT INTO charaData (playerId,dataVal) VALUES (?,?);",
|
||||||
|
playerId,
|
||||||
|
new Gson().toJson(template)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the template for a character
|
||||||
|
* @param playerId The player's id
|
||||||
|
* @param characterId The character's id
|
||||||
|
* @return The template if it exists, null otherwise
|
||||||
|
*/
|
||||||
|
public static CreatureTemplate getTemplate(int playerId, int characterId){
|
||||||
|
DatabaseResult result = Globals.dbController.executePreparedQuery("SELECT id, dataVal FROM charaData WHERE playerId=? AND id=?;",playerId, characterId);
|
||||||
|
if(result.hasResult()){
|
||||||
|
Gson gson = new Gson();
|
||||||
|
//if we get a valid response from the database, check that it actually matches hashes
|
||||||
|
for(DatabaseResultRow row : result){
|
||||||
|
CreatureTemplate template = gson.fromJson(row.getAsString("dataVal"),CreatureTemplate.class);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LoggerInterface.loggerDB.WARNING("Failed to locate creature template for playerId=" + playerId + " characterId=" + characterId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the characters that a player has
|
||||||
|
* @param playerId The player's id
|
||||||
|
* @return The list of characters that player has
|
||||||
|
*/
|
||||||
|
public static List<CharacterDescription> getCharacters(int playerId){
|
||||||
|
DatabaseResult result = Globals.dbController.executePreparedQuery("SELECT id, dataVal FROM charaData WHERE playerId=?;",playerId);
|
||||||
|
Gson gson = new Gson();
|
||||||
|
List<CharacterDescription> rVal = new LinkedList<CharacterDescription>();
|
||||||
|
if(result.hasResult()){
|
||||||
|
//if we get a valid response from the database, check that it actually matches hashes
|
||||||
|
for(DatabaseResultRow row : result){
|
||||||
|
CharacterDescription description = new CharacterDescription();
|
||||||
|
CreatureTemplate template = gson.fromJson(row.getAsString("dataVal"),CreatureTemplate.class);
|
||||||
|
description.setTemplate(template);
|
||||||
|
description.setId(row.getAsInteger("id") + "");
|
||||||
|
rVal.add(description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the position of a character
|
||||||
|
* @param characterId The character's Id
|
||||||
|
* @return The position if it is stored in the DB, null otherwise
|
||||||
|
*/
|
||||||
|
public static Vector3d getCharacterPosition(int characterId){
|
||||||
|
DatabaseResult result = Globals.dbController.executePreparedQuery("SELECT x, y, z FROM charaRealPos WHERE id=?;",characterId);
|
||||||
|
if(result.hasResult()){
|
||||||
|
//if we get a valid response from the database, return the position
|
||||||
|
for(DatabaseResultRow row : result){
|
||||||
|
double x = row.getAsDouble("x");
|
||||||
|
double y = row.getAsDouble("y");
|
||||||
|
double z = row.getAsDouble("z");
|
||||||
|
return new Vector3d(x,y,z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a character from an entity
|
||||||
|
* @param characterEntity The entity
|
||||||
|
*/
|
||||||
|
public static void saveCharacter(Entity characterEntity){
|
||||||
|
if(!ServerCharacterData.hasServerPlayerCharacterDataTree(characterEntity)){
|
||||||
|
throw new Error("Trying to save entity hat does not contain character data!");
|
||||||
|
}
|
||||||
|
ServerCharacterData characterData = ServerCharacterData.getServerCharacterData(characterEntity);
|
||||||
|
int characterId = characterData.getCharacterId();
|
||||||
|
|
||||||
|
//store exact position if it's a player's entity
|
||||||
|
if(ServerPlayerViewDirTree.hasTree(characterEntity)){
|
||||||
|
Vector3d realPos = EntityUtils.getPosition(characterEntity);
|
||||||
|
Globals.dbController.executePreparedStatement(
|
||||||
|
"INSERT OR REPLACE INTO charaRealPos (id, x, y, z) VALUES (?,?,?,?);",
|
||||||
|
characterId,
|
||||||
|
realPos.x,
|
||||||
|
realPos.y,
|
||||||
|
realPos.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,12 +5,14 @@ import org.joml.Vector3i;
|
|||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.state.server.ServerCharacterData;
|
||||||
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
|
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
|
||||||
import electrosphere.entity.types.creature.CreatureTemplate;
|
import electrosphere.entity.types.creature.CreatureTemplate;
|
||||||
import electrosphere.entity.types.creature.CreatureUtils;
|
import electrosphere.entity.types.creature.CreatureUtils;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.net.server.ServerConnectionHandler;
|
import electrosphere.net.server.ServerConnectionHandler;
|
||||||
import electrosphere.net.server.player.Player;
|
import electrosphere.net.server.player.Player;
|
||||||
|
import electrosphere.net.server.protocol.CharacterProtocol;
|
||||||
import electrosphere.server.datacell.Realm;
|
import electrosphere.server.datacell.Realm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,7 +30,10 @@ public class PlayerCharacterCreation {
|
|||||||
|
|
||||||
//
|
//
|
||||||
//get template
|
//get template
|
||||||
CreatureTemplate template = connectionHandler.getCurrentCreatureTemplate();
|
CreatureTemplate template = CharacterService.getTemplate(connectionHandler.getPlayer().getDBID(), connectionHandler.getCharacterId());
|
||||||
|
if(connectionHandler.getCharacterId() == CharacterProtocol.SPAWN_EXISTING_TEMPLATE){
|
||||||
|
template = connectionHandler.getCurrentCreatureTemplate();
|
||||||
|
}
|
||||||
String raceName = template.getCreatureType();
|
String raceName = template.getCreatureType();
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -67,21 +72,23 @@ public class PlayerCharacterCreation {
|
|||||||
* @param serverConnectionHandler The connection handler
|
* @param serverConnectionHandler The connection handler
|
||||||
*/
|
*/
|
||||||
public static void attachEntityToPlayerObject(Entity entity, Player playerObject, ServerConnectionHandler serverConnectionHandler){
|
public static void attachEntityToPlayerObject(Entity entity, Player playerObject, ServerConnectionHandler serverConnectionHandler){
|
||||||
int playerCharacterId = entity.getId();
|
int playerEntityId = entity.getId();
|
||||||
serverConnectionHandler.setPlayerEntityId(playerCharacterId);
|
serverConnectionHandler.setPlayerEntityId(playerEntityId);
|
||||||
CreatureUtils.setControllerPlayerId(entity, serverConnectionHandler.getPlayerId());
|
CreatureUtils.setControllerPlayerId(entity, serverConnectionHandler.getPlayerId());
|
||||||
Player player = serverConnectionHandler.getPlayer();
|
Player player = serverConnectionHandler.getPlayer();
|
||||||
player.setPlayerEntity(entity);
|
player.setPlayerEntity(entity);
|
||||||
//custom player btrees
|
//custom player btrees
|
||||||
PlayerCharacterCreation.addPlayerServerBTrees(entity);
|
PlayerCharacterCreation.addPlayerServerBTrees(entity, serverConnectionHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds behavior trees that are unique to players a given entity
|
* Adds behavior trees that are unique to players a given entity
|
||||||
* @param entity The entity to add to
|
* @param entity The entity to add to
|
||||||
|
* @param serverConnectionHandler The server connection handler for the entity
|
||||||
*/
|
*/
|
||||||
static void addPlayerServerBTrees(Entity entity){
|
static void addPlayerServerBTrees(Entity entity, ServerConnectionHandler serverConnectionHandler){
|
||||||
ServerPlayerViewDirTree.attachServerPlayerViewDirTree(entity);
|
ServerPlayerViewDirTree.attachServerPlayerViewDirTree(entity);
|
||||||
|
ServerCharacterData.attachServerPlayerViewDirTree(entity, serverConnectionHandler.getCharacterId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,7 +98,10 @@ public class PlayerCharacterCreation {
|
|||||||
* @return The spawn point for the player
|
* @return The spawn point for the player
|
||||||
*/
|
*/
|
||||||
public static Vector3d solveSpawnPoint(Realm realm, ServerConnectionHandler connectionHandler){
|
public static Vector3d solveSpawnPoint(Realm realm, ServerConnectionHandler connectionHandler){
|
||||||
Vector3d spawnPoint = realm.getSpawnPoint();
|
Vector3d spawnPoint = CharacterService.getCharacterPosition(connectionHandler.getCharacterId());
|
||||||
|
if(spawnPoint == null){
|
||||||
|
spawnPoint = realm.getSpawnPoint();
|
||||||
|
}
|
||||||
return spawnPoint;
|
return spawnPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import org.joml.Vector3i;
|
|||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.state.server.ServerCharacterData;
|
||||||
|
import electrosphere.server.character.CharacterService;
|
||||||
import electrosphere.server.content.serialization.ContentSerialization;
|
import electrosphere.server.content.serialization.ContentSerialization;
|
||||||
import electrosphere.server.datacell.Realm;
|
import electrosphere.server.datacell.Realm;
|
||||||
import electrosphere.server.datacell.ServerDataCell;
|
import electrosphere.server.datacell.ServerDataCell;
|
||||||
@ -78,10 +80,18 @@ public class ServerContentManager {
|
|||||||
* @param entities the collection of entities to save
|
* @param entities the collection of entities to save
|
||||||
*/
|
*/
|
||||||
public void saveContentToDisk(Long locationKey, Collection<Entity> entities){
|
public void saveContentToDisk(Long locationKey, Collection<Entity> entities){
|
||||||
|
//serialize all non-character entities
|
||||||
ContentSerialization serialization = ContentSerialization.constructContentSerialization(entities);
|
ContentSerialization serialization = ContentSerialization.constructContentSerialization(entities);
|
||||||
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSave.getName());
|
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSave.getName());
|
||||||
String fullPath = dirPath + "/content/" + locationKey + ".dat";
|
String fullPath = dirPath + "/content/" + locationKey + ".dat";
|
||||||
FileUtils.serializeObjectToFilePath(fullPath, serialization);
|
FileUtils.serializeObjectToFilePath(fullPath, serialization);
|
||||||
|
|
||||||
|
//store all character entities in database
|
||||||
|
for(Entity entity : entities){
|
||||||
|
if(ServerCharacterData.hasServerPlayerCharacterDataTree(entity)){
|
||||||
|
CharacterService.saveCharacter(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -24,7 +24,9 @@ import electrosphere.util.Utilities;
|
|||||||
public class ContentSerialization {
|
public class ContentSerialization {
|
||||||
|
|
||||||
|
|
||||||
//The entities, serialized
|
/**
|
||||||
|
* The entities, serialized
|
||||||
|
*/
|
||||||
List<EntitySerialization> serializedEntities = new LinkedList<EntitySerialization>();
|
List<EntitySerialization> serializedEntities = new LinkedList<EntitySerialization>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,52 +40,55 @@ public class ContentSerialization {
|
|||||||
if(!CreatureUtils.hasControllerPlayerId(entity)){
|
if(!CreatureUtils.hasControllerPlayerId(entity)){
|
||||||
EntityType type = CommonEntityUtils.getEntityType(entity);
|
EntityType type = CommonEntityUtils.getEntityType(entity);
|
||||||
if(type != null){
|
if(type != null){
|
||||||
switch(type){
|
EntitySerialization serializedEntity = constructEntitySerialization(entity);
|
||||||
case CREATURE: {
|
rVal.serializedEntities.add(serializedEntity);
|
||||||
EntitySerialization serializedEntity = new EntitySerialization();
|
|
||||||
serializedEntity.setPosition(EntityUtils.getPosition(entity));
|
|
||||||
serializedEntity.setRotation(EntityUtils.getRotation(entity));
|
|
||||||
serializedEntity.setType(EntityType.CREATURE.getValue());
|
|
||||||
serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
|
|
||||||
if(CreatureUtils.getCreatureTemplate(entity) != null){
|
|
||||||
serializedEntity.setTemplate(Utilities.stringify(CreatureUtils.getCreatureTemplate(entity)));
|
|
||||||
}
|
|
||||||
rVal.serializedEntities.add(serializedEntity);
|
|
||||||
} break;
|
|
||||||
case ITEM: {
|
|
||||||
if(!AttachUtils.isAttached(entity)){
|
|
||||||
EntitySerialization serializedEntity = new EntitySerialization();
|
|
||||||
serializedEntity.setPosition(EntityUtils.getPosition(entity));
|
|
||||||
serializedEntity.setRotation(EntityUtils.getRotation(entity));
|
|
||||||
serializedEntity.setType(EntityType.ITEM.getValue());
|
|
||||||
serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
|
|
||||||
rVal.serializedEntities.add(serializedEntity);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case FOLIAGE: {
|
|
||||||
EntitySerialization serializedEntity = new EntitySerialization();
|
|
||||||
serializedEntity.setPosition(EntityUtils.getPosition(entity));
|
|
||||||
serializedEntity.setRotation(EntityUtils.getRotation(entity));
|
|
||||||
serializedEntity.setType(EntityType.FOLIAGE.getValue());
|
|
||||||
serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
|
|
||||||
serializedEntity.setTemplate(FoliageUtils.getFoliageSeed(entity) + "");
|
|
||||||
rVal.serializedEntities.add(serializedEntity);
|
|
||||||
} break;
|
|
||||||
case COMMON: {
|
|
||||||
EntitySerialization serializedEntity = new EntitySerialization();
|
|
||||||
serializedEntity.setPosition(EntityUtils.getPosition(entity));
|
|
||||||
serializedEntity.setRotation(EntityUtils.getRotation(entity));
|
|
||||||
serializedEntity.setType(EntityType.COMMON.getValue());
|
|
||||||
serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
|
|
||||||
rVal.serializedEntities.add(serializedEntity);
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a serialization of an entity
|
||||||
|
* @param entity The entity
|
||||||
|
* @return The serialization of the entity
|
||||||
|
*/
|
||||||
|
public static EntitySerialization constructEntitySerialization(Entity entity){
|
||||||
|
EntitySerialization serializedEntity = new EntitySerialization();
|
||||||
|
serializedEntity.setPosition(EntityUtils.getPosition(entity));
|
||||||
|
serializedEntity.setRotation(EntityUtils.getRotation(entity));
|
||||||
|
EntityType type = CommonEntityUtils.getEntityType(entity);
|
||||||
|
if(type != null){
|
||||||
|
switch(type){
|
||||||
|
case CREATURE: {
|
||||||
|
serializedEntity.setType(EntityType.CREATURE.getValue());
|
||||||
|
serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
|
||||||
|
if(CreatureUtils.getCreatureTemplate(entity) != null){
|
||||||
|
serializedEntity.setTemplate(Utilities.stringify(CreatureUtils.getCreatureTemplate(entity)));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case ITEM: {
|
||||||
|
if(!AttachUtils.isAttached(entity)){
|
||||||
|
serializedEntity.setType(EntityType.ITEM.getValue());
|
||||||
|
serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case FOLIAGE: {
|
||||||
|
serializedEntity.setType(EntityType.FOLIAGE.getValue());
|
||||||
|
serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
|
||||||
|
serializedEntity.setTemplate(FoliageUtils.getFoliageSeed(entity) + "");
|
||||||
|
} break;
|
||||||
|
case COMMON: {
|
||||||
|
serializedEntity.setType(EntityType.COMMON.getValue());
|
||||||
|
serializedEntity.setSubtype(CommonEntityUtils.getEntitySubtype(entity));
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error("Trying to save entity that does not have a type!");
|
||||||
|
}
|
||||||
|
return serializedEntity;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actually creates the entities from a content serialization
|
* Actually creates the entities from a content serialization
|
||||||
* @param contentRaw The content serialization
|
* @param contentRaw The content serialization
|
||||||
|
|||||||
@ -37,7 +37,6 @@ import electrosphere.server.datacell.ServerDataCell;
|
|||||||
import electrosphere.server.datacell.interfaces.DataCellManager;
|
import electrosphere.server.datacell.interfaces.DataCellManager;
|
||||||
import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
||||||
import electrosphere.server.datacell.physics.PhysicsDataCell;
|
import electrosphere.server.datacell.physics.PhysicsDataCell;
|
||||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
|
||||||
import electrosphere.server.fluid.manager.ServerFluidChunk;
|
import electrosphere.server.fluid.manager.ServerFluidChunk;
|
||||||
import electrosphere.server.fluid.manager.ServerFluidManager;
|
import electrosphere.server.fluid.manager.ServerFluidManager;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
||||||
|
|||||||
@ -13,6 +13,11 @@ import java.util.Properties;
|
|||||||
*/
|
*/
|
||||||
public class DatabaseController {
|
public class DatabaseController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file extension for allowed database files to open
|
||||||
|
*/
|
||||||
|
public static final String FILE_EXT = ".sqlite";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The database connection
|
* The database connection
|
||||||
*/
|
*/
|
||||||
@ -43,6 +48,7 @@ public class DatabaseController {
|
|||||||
* Executes a write statement to the database
|
* Executes a write statement to the database
|
||||||
* @param statementRaw The raw string for the statement
|
* @param statementRaw The raw string for the statement
|
||||||
* @param arguments The arguments to be inserted into the raw sql
|
* @param arguments The arguments to be inserted into the raw sql
|
||||||
|
* @return true if there is a result set, false if there is an update count or no result
|
||||||
*/
|
*/
|
||||||
public boolean executePreparedStatement(String statementRaw, Object...arguments){
|
public boolean executePreparedStatement(String statementRaw, Object...arguments){
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -90,21 +90,24 @@ public class DatabaseResultIterator implements Iterator<DatabaseResultRow> {
|
|||||||
//increment at the beginning because result sets are indexed starting at 1
|
//increment at the beginning because result sets are indexed starting at 1
|
||||||
columnIncrementer++;
|
columnIncrementer++;
|
||||||
switch(type){
|
switch(type){
|
||||||
case Types.INTEGER:
|
case Types.INTEGER: {
|
||||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getInt(columnIncrementer));
|
row.putValue(metadata.getColumnName(columnIncrementer), rs.getInt(columnIncrementer));
|
||||||
break;
|
} break;
|
||||||
case Types.VARCHAR:
|
case Types.VARCHAR: {
|
||||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getString(columnIncrementer));
|
row.putValue(metadata.getColumnName(columnIncrementer), rs.getString(columnIncrementer));
|
||||||
break;
|
} break;
|
||||||
case Types.BIGINT:
|
case Types.BIGINT: {
|
||||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getLong(columnIncrementer));
|
row.putValue(metadata.getColumnName(columnIncrementer), rs.getLong(columnIncrementer));
|
||||||
break;
|
} break;
|
||||||
case Types.FLOAT:
|
case Types.FLOAT: {
|
||||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getFloat(columnIncrementer));
|
row.putValue(metadata.getColumnName(columnIncrementer), rs.getFloat(columnIncrementer));
|
||||||
break;
|
} break;
|
||||||
case Types.DOUBLE:
|
case Types.DOUBLE: {
|
||||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getDouble(columnIncrementer));
|
row.putValue(metadata.getColumnName(columnIncrementer), rs.getDouble(columnIncrementer));
|
||||||
break;
|
} break;
|
||||||
|
case Types.REAL: {
|
||||||
|
row.putValue(metadata.getColumnName(columnIncrementer), rs.getDouble(columnIncrementer));
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
LoggerInterface.loggerEngine.WARNING("Unsupported type from database in DatabaseResultIterator " + type);
|
LoggerInterface.loggerEngine.WARNING("Unsupported type from database in DatabaseResultIterator " + type);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -3,11 +3,14 @@ package electrosphere.server.db;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A row result from a database operation
|
||||||
|
*/
|
||||||
public class DatabaseResultRow {
|
public class DatabaseResultRow {
|
||||||
|
|
||||||
// protected addColumn(int column)
|
/**
|
||||||
|
* stores all the values of the row in an easily indexible-by-column-name format
|
||||||
//stores all the values of the row in an easily indexible-by-column-name format
|
*/
|
||||||
Map<String,Object> values = new HashMap<String,Object>();
|
Map<String,Object> values = new HashMap<String,Object>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -6,38 +6,40 @@ import electrosphere.util.FileUtils;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Utilities for working with the database
|
||||||
* @author satellite
|
|
||||||
*/
|
*/
|
||||||
public class DatabaseUtils {
|
public class DatabaseUtils {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the central db file
|
||||||
|
* @param path The path to initialize at
|
||||||
|
* @return true if it succeeded, false otherwise
|
||||||
|
*/
|
||||||
public static boolean initCentralDBFile(String path){
|
public static boolean initCentralDBFile(String path){
|
||||||
String sanitizedPath = FileUtils.sanitizeFilePath(path);
|
String sanitizedPath = FileUtils.sanitizeFilePath(path);
|
||||||
if(!FileUtils.checkFileExists(sanitizedPath)){
|
if(!FileUtils.checkFileExists(sanitizedPath)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String dbFilePath = sanitizedPath + "/central.db";
|
String dbFilePath = sanitizedPath + "/central" + DatabaseController.FILE_EXT;
|
||||||
if(Globals.dbController == null){
|
if(Globals.dbController == null){
|
||||||
Globals.dbController = new DatabaseController();
|
Globals.dbController = new DatabaseController();
|
||||||
}
|
}
|
||||||
if(!Globals.dbController.isConnected()){
|
if(!Globals.dbController.isConnected()){
|
||||||
Globals.dbController.connect(dbFilePath);
|
Globals.dbController.connect(dbFilePath);
|
||||||
}
|
}
|
||||||
runScript(Globals.dbController,"createTables.sql");
|
DatabaseUtils.runScript(Globals.dbController,"createTables.sql");
|
||||||
//both of these are used for arena mode as well as main game
|
//both of these are used for arena mode as well as main game
|
||||||
runScript(Globals.dbController,"/auth/createAuthTables.sql");
|
|
||||||
runScript(Globals.dbController,"/character/createCharacterTables.sql");
|
|
||||||
//create adventure-only files
|
|
||||||
if(!dbFilePath.equals("./saves/arena/central.db")){
|
|
||||||
//we only want to create these if we're not in arena mode
|
|
||||||
runScript(Globals.dbController,"/towns/createTownsTables.sql");
|
|
||||||
runScript(Globals.dbController,"/structs/createStructsTables.sql");
|
|
||||||
}
|
|
||||||
Globals.dbController.disconnect();
|
Globals.dbController.disconnect();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a script
|
||||||
|
* @param controller The controller
|
||||||
|
* @param scriptPath The script's path
|
||||||
|
* @return true if it succeeds, false otherwise
|
||||||
|
*/
|
||||||
public static boolean runScript(DatabaseController controller, String scriptPath){
|
public static boolean runScript(DatabaseController controller, String scriptPath){
|
||||||
String rawScript = "";
|
String rawScript = "";
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import electrosphere.entity.scene.SceneFile;
|
|||||||
import electrosphere.entity.scene.SceneLoader;
|
import electrosphere.entity.scene.SceneLoader;
|
||||||
import electrosphere.game.server.world.ServerWorldData;
|
import electrosphere.game.server.world.ServerWorldData;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
import electrosphere.server.db.DatabaseController;
|
||||||
import electrosphere.server.db.DatabaseUtils;
|
import electrosphere.server.db.DatabaseUtils;
|
||||||
import electrosphere.server.fluid.generation.DefaultFluidGenerator;
|
import electrosphere.server.fluid.generation.DefaultFluidGenerator;
|
||||||
import electrosphere.server.fluid.manager.ServerFluidManager;
|
import electrosphere.server.fluid.manager.ServerFluidManager;
|
||||||
@ -155,6 +156,9 @@ public class SaveUtils {
|
|||||||
|
|
||||||
//write server structures
|
//write server structures
|
||||||
Globals.realmManager.save(saveName);
|
Globals.realmManager.save(saveName);
|
||||||
|
|
||||||
|
//close the server
|
||||||
|
Globals.server.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -211,7 +215,7 @@ public class SaveUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//load db
|
//load db
|
||||||
String dbFilePath = FileUtils.sanitizeFilePath(dirPath) + "/central.db";
|
String dbFilePath = FileUtils.sanitizeFilePath(dirPath) + "/central" + DatabaseController.FILE_EXT;
|
||||||
Globals.dbController.connect(dbFilePath);
|
Globals.dbController.connect(dbFilePath);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -17,6 +17,11 @@
|
|||||||
"messageName" : "Pong",
|
"messageName" : "Pong",
|
||||||
"description" : "Replies to a ping from the other side of the socket",
|
"description" : "Replies to a ping from the other side of the socket",
|
||||||
"data" : []
|
"data" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"messageName" : "Disconnect",
|
||||||
|
"description" : "Tell the other side of the socket that this side is disconnecting",
|
||||||
|
"data" : []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user