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);
|
||||
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
|
||||
Tests for above bugs
|
||||
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
|
||||
{
|
||||
Button button = Button.createButton("Save", () -> {
|
||||
Button button = Button.createButton("Save and Quit", () -> {
|
||||
SaveUtils.overwriteSave(Globals.currentSave.getName());
|
||||
Globals.signalSystem.post(SignalType.ENGINE_RETURN_TO_TITLE);
|
||||
});
|
||||
button.setMarginTop(BUTTON_MARGIN);
|
||||
button.setMarginLeft(BUTTON_MARGIN);
|
||||
@ -116,7 +117,7 @@ public class MenuGeneratorsInGame {
|
||||
|
||||
//Quit
|
||||
{
|
||||
Button button = Button.createButton("Quit", () -> {
|
||||
Button button = Button.createButton("Shutdown", () -> {
|
||||
Main.running = false;
|
||||
});
|
||||
button.setMarginTop(BUTTON_MARGIN);
|
||||
|
||||
@ -326,6 +326,7 @@ public class EntityDataStrings {
|
||||
* Server-specific btrees
|
||||
*/
|
||||
public static final String TREE_SERVERPLAYERVIEWDIR = "treeServerPlayerViewDir";
|
||||
public static final String TREE_SERVERCHARACTERDATA = "treeServerCharacterData";
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private static void setTyping(Entity entity, CommonEntityType type){
|
||||
if(type == null){
|
||||
throw new Error("Provided null typing!");
|
||||
}
|
||||
if(type instanceof CreatureData){
|
||||
CommonEntityUtils.setEntityType(entity, EntityType.CREATURE);
|
||||
CommonEntityUtils.setEntitySubtype(entity, type.getId());
|
||||
|
||||
@ -482,14 +482,29 @@ public class CreatureUtils {
|
||||
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){
|
||||
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){
|
||||
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){
|
||||
return e.containsKey(EntityDataStrings.DATA_STRING_CREATURE_CONTROLLER_PLAYER_ID);
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package electrosphere.net.client.protocol;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.parser.net.message.ServerMessage;
|
||||
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
|
||||
Globals.clientConnection.markReceivedPongMessage();
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case TypeBytes.SERVER_MESSAGE_TYPE_DISCONNECT:
|
||||
if(ServerMessage.canParseMessage(byteBuffer,secondByte)){
|
||||
rVal = ServerMessage.parseDisconnectMessage(byteBuffer,pool);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TypeBytes.MESSAGE_TYPE_AUTH:
|
||||
|
||||
@ -9,6 +9,7 @@ public class ServerMessage extends NetworkMessage {
|
||||
public enum ServerMessageType {
|
||||
PING,
|
||||
PONG,
|
||||
DISCONNECT,
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,6 +65,12 @@ public class ServerMessage extends NetworkMessage {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case TypeBytes.SERVER_MESSAGE_TYPE_DISCONNECT:
|
||||
if(byteBuffer.getRemaining() >= TypeBytes.SERVER_MESSAGE_TYPE_DISCONNECT_SIZE){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -106,6 +113,25 @@ public class ServerMessage extends NetworkMessage {
|
||||
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
|
||||
void serialize(){
|
||||
switch(this.messageType){
|
||||
@ -123,6 +149,13 @@ public class ServerMessage extends NetworkMessage {
|
||||
//entity messaage header
|
||||
rawBytes[1] = TypeBytes.SERVER_MESSAGE_TYPE_PONG;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -103,11 +103,13 @@ public class TypeBytes {
|
||||
*/
|
||||
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_DISCONNECT = 2;
|
||||
/*
|
||||
Server packet sizes
|
||||
*/
|
||||
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_DISCONNECT_SIZE = 2;
|
||||
|
||||
/*
|
||||
Auth subcategories
|
||||
|
||||
@ -28,32 +28,46 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
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;
|
||||
|
||||
//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
|
||||
*/
|
||||
void initServer(){
|
||||
private void initServer(){
|
||||
// clientMap = new HashMap<String,ServerConnectionHandler>();
|
||||
}
|
||||
|
||||
@ -67,7 +81,7 @@ public class Server implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
initServer();
|
||||
this.initServer();
|
||||
try {
|
||||
serverSocket = new ServerSocket(port);
|
||||
//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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return true if is open, false otherwise
|
||||
|
||||
@ -25,66 +25,112 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
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;
|
||||
|
||||
//socket carrier variables
|
||||
/**
|
||||
* socket carrier variables
|
||||
*/
|
||||
Socket socket;
|
||||
|
||||
//the streams for the connection
|
||||
// CryptoInputStream inputStream;
|
||||
// CryptoOutputStream outputStream;
|
||||
|
||||
/**
|
||||
* The input stream for packets
|
||||
*/
|
||||
InputStream inputStream;
|
||||
|
||||
/**
|
||||
* The output stream for packets
|
||||
*/
|
||||
OutputStream outputStream;
|
||||
|
||||
//the network parser for the streams
|
||||
/**
|
||||
* the network parser for the streams
|
||||
*/
|
||||
NetworkParser networkParser;
|
||||
|
||||
//initialized status
|
||||
/**
|
||||
* initialized status
|
||||
*/
|
||||
boolean initialized;
|
||||
//authentication status
|
||||
|
||||
/**
|
||||
* authentication status
|
||||
*/
|
||||
boolean isAuthenticated = false;
|
||||
|
||||
//the player id
|
||||
/**
|
||||
* the player id
|
||||
*/
|
||||
int playerID;
|
||||
//the player's entity id
|
||||
|
||||
/**
|
||||
* the player's entity id
|
||||
*/
|
||||
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
|
||||
*/
|
||||
boolean isConnected = true;
|
||||
|
||||
//the creature template associated with this player
|
||||
/**
|
||||
* the creature template associated with this player
|
||||
*/
|
||||
CreatureTemplate currentCreatureTemplate;
|
||||
|
||||
//the server protocol object associated with this player
|
||||
/**
|
||||
* the server protocol object associated with this player
|
||||
*/
|
||||
MessageProtocol messageProtocol;
|
||||
|
||||
//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;
|
||||
//used to keep track of ping/pong messages with client
|
||||
/**
|
||||
* Keeps track of the last time this connection received a ping from the client
|
||||
*/
|
||||
long lastPingTime = 0;
|
||||
/**
|
||||
* Keeps track of the last time this connection received a pong from the client
|
||||
*/
|
||||
long lastPongTime = 0;
|
||||
//flag to disconnect due to pipe break
|
||||
|
||||
/**
|
||||
* flag to disconnect due to pipe break
|
||||
*/
|
||||
boolean socketException = false;
|
||||
|
||||
|
||||
//debug netmonitor stuff
|
||||
/**
|
||||
* debug netmonitor stuff
|
||||
*/
|
||||
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>();
|
||||
|
||||
//the lock used for synchronizing the synchronous message queue
|
||||
/**
|
||||
* the lock used for synchronizing the synchronous message queue
|
||||
*/
|
||||
Semaphore synchronousMessageLock = new Semaphore(1);
|
||||
//the queue of synchonous network messages
|
||||
|
||||
/**
|
||||
* the queue of synchonous network messages
|
||||
*/
|
||||
List<NetworkMessage> synchronousMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
|
||||
|
||||
/**
|
||||
@ -198,7 +244,7 @@ public class ServerConnectionHandler implements Runnable {
|
||||
//
|
||||
//parse messages both incoming and outgoing
|
||||
try {
|
||||
receivedMessageThisLoop = parseMessages();
|
||||
receivedMessageThisLoop = this.parseMessages();
|
||||
} catch (SocketException e) {
|
||||
//if we get a SocketException broken pipe (basically the client dc'd without telling us)
|
||||
//set flag to disconnect client
|
||||
@ -228,7 +274,7 @@ public class ServerConnectionHandler implements Runnable {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
//basically if we haven't sent a ping in a while, send one
|
||||
if(currentTime - lastPingTime > SEND_PING_THRESHOLD){
|
||||
addMessagetoOutgoingQueue(ServerMessage.constructPingMessage());
|
||||
this.addMessagetoOutgoingQueue(ServerMessage.constructPingMessage());
|
||||
lastPingTime = currentTime;
|
||||
if(lastPongTime == 0){
|
||||
lastPongTime = lastPingTime;
|
||||
@ -245,14 +291,14 @@ public class ServerConnectionHandler implements Runnable {
|
||||
//disconnected from the server
|
||||
LoggerInterface.loggerNetworking.WARNING("Client timeout");
|
||||
//run disconnect routine
|
||||
disconnect();
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
if(this.socketException == true){
|
||||
//disconnected from the server
|
||||
LoggerInterface.loggerNetworking.WARNING("Client disconnected");
|
||||
//run disconnect routine
|
||||
disconnect();
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -266,7 +312,7 @@ public class ServerConnectionHandler implements Runnable {
|
||||
* @throws SocketException
|
||||
* @return true if connection is alive, false otherwise
|
||||
*/
|
||||
boolean parseMessages() throws SocketException, IOException {
|
||||
private boolean parseMessages() throws SocketException, IOException {
|
||||
boolean rVal = false;
|
||||
//
|
||||
//Read in messages
|
||||
@ -333,15 +379,27 @@ public class ServerConnectionHandler implements Runnable {
|
||||
this.messageProtocol.handleSyncMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's id
|
||||
* @return The player's id
|
||||
*/
|
||||
public int getPlayerId(){
|
||||
return playerID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's entity's id
|
||||
* @param id
|
||||
*/
|
||||
public void setPlayerEntityId(int id){
|
||||
LoggerInterface.loggerNetworking.DEBUG("Set player(" + this.playerID + ")'s entity ID to be " + id);
|
||||
playerEntityID = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's entity's id
|
||||
* @return The id
|
||||
*/
|
||||
public int getPlayerEntityId(){
|
||||
return playerEntityID;
|
||||
}
|
||||
@ -374,22 +432,14 @@ public class ServerConnectionHandler implements Runnable {
|
||||
return this.socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a message to the outgoing queue
|
||||
* @param message The message
|
||||
*/
|
||||
public void addMessagetoOutgoingQueue(NetworkMessage 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
|
||||
* @param currentCreatureTemplate The new creature template
|
||||
@ -406,6 +456,9 @@ public class ServerConnectionHandler implements Runnable {
|
||||
return this.currentCreatureTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks that this connection received a pong message
|
||||
*/
|
||||
public void markReceivedPongMessage(){
|
||||
lastPongTime = System.currentTimeMillis();
|
||||
}
|
||||
@ -413,8 +466,21 @@ public class ServerConnectionHandler implements Runnable {
|
||||
/**
|
||||
* Routine to run when the client disconnects
|
||||
*/
|
||||
private void disconnect(){
|
||||
protected void disconnect(){
|
||||
//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()){
|
||||
try {
|
||||
socket.close();
|
||||
@ -422,6 +488,8 @@ public class ServerConnectionHandler implements Runnable {
|
||||
LoggerInterface.loggerNetworking.ERROR("Error closing socket", e);
|
||||
}
|
||||
}
|
||||
|
||||
this.synchronousMessageLock.release();
|
||||
this.isConnected = false;
|
||||
//add connection to server list of connections to cleanup
|
||||
if(Globals.server != null){
|
||||
@ -440,4 +508,22 @@ public class ServerConnectionHandler implements Runnable {
|
||||
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;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@ -24,10 +23,9 @@ import electrosphere.net.parser.net.message.PlayerMessage;
|
||||
import electrosphere.net.server.ServerConnectionHandler;
|
||||
import electrosphere.net.server.player.Player;
|
||||
import electrosphere.net.template.ServerProtocolTemplate;
|
||||
import electrosphere.server.character.CharacterService;
|
||||
import electrosphere.server.character.PlayerCharacterCreation;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.db.DatabaseResult;
|
||||
import electrosphere.server.db.DatabaseResultRow;
|
||||
import electrosphere.util.Utilities;
|
||||
|
||||
/**
|
||||
@ -45,18 +43,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
|
||||
switch(message.getMessageSubtype()){
|
||||
case REQUESTCHARACTERLIST: {
|
||||
Gson gson = new Gson();
|
||||
List<CharacterDescription> characters = new LinkedList<CharacterDescription>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
List<CharacterDescription> characters = CharacterService.getCharacters(connectionHandler.getPlayer().getDBID());
|
||||
ClientCharacterListDTO dto = new ClientCharacterListDTO();
|
||||
dto.setCharacters(characters);
|
||||
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCharacterListMessage(gson.toJson(dto)));
|
||||
@ -74,11 +61,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
|
||||
case REQUESTCREATECHARACTER: {
|
||||
CreatureTemplate template = Utilities.deserialize(message.getdata(), CreatureTemplate.class);
|
||||
if(template != null){
|
||||
Globals.dbController.executePreparedStatement(
|
||||
"INSERT INTO charaData (playerId,dataVal) VALUES (?,?);",
|
||||
connectionHandler.getPlayer().getDBID(),
|
||||
new Gson().toJson(template)
|
||||
);
|
||||
CharacterService.createCharacter(template, connectionHandler.getPlayer().getDBID());
|
||||
connectionHandler.setCreatureTemplate(Utilities.deserialize(message.getdata(), CreatureTemplate.class));
|
||||
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCreateCharacterSuccessMessage());
|
||||
} else {
|
||||
@ -111,17 +94,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
|
||||
* @return THe player's entity
|
||||
*/
|
||||
static Entity spawnEntityForClient(ServerConnectionHandler connectionHandler, int id){
|
||||
if(id != CharacterProtocol.SPAWN_EXISTING_TEMPLATE){
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
connectionHandler.setCharacterId(id);
|
||||
Entity rVal = PlayerCharacterCreation.spawnPlayerCharacter(connectionHandler);
|
||||
Realm realm = Globals.playerManager.getPlayerRealm(connectionHandler.getPlayer());
|
||||
Vector3d spawnPoint = PlayerCharacterCreation.solveSpawnPoint(realm, connectionHandler);
|
||||
|
||||
@ -9,18 +9,23 @@ import electrosphere.net.template.ServerProtocolTemplate;
|
||||
*/
|
||||
public class ServerProtocol implements ServerProtocolTemplate<ServerMessage> {
|
||||
|
||||
//the connection handler associated with this protocol object
|
||||
/**
|
||||
* the connection handler associated with this protocol object
|
||||
*/
|
||||
ServerConnectionHandler connectionHandler;
|
||||
|
||||
|
||||
@Override
|
||||
public ServerMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
|
||||
switch(message.getMessageSubtype()){
|
||||
case PING:
|
||||
case PING: {
|
||||
connectionHandler.addMessagetoOutgoingQueue(ServerMessage.constructPongMessage());
|
||||
break;
|
||||
case PONG:
|
||||
} break;
|
||||
case PONG: {
|
||||
connectionHandler.markReceivedPongMessage();
|
||||
} break;
|
||||
case DISCONNECT:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
@ -29,6 +34,7 @@ public class ServerProtocol implements ServerProtocolTemplate<ServerMessage> {
|
||||
@Override
|
||||
public void handleSyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
|
||||
switch(message.getMessageSubtype()){
|
||||
case DISCONNECT:
|
||||
case PING:
|
||||
case PONG:
|
||||
//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.entity.Entity;
|
||||
import electrosphere.entity.state.server.ServerCharacterData;
|
||||
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
|
||||
import electrosphere.entity.types.creature.CreatureTemplate;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.server.ServerConnectionHandler;
|
||||
import electrosphere.net.server.player.Player;
|
||||
import electrosphere.net.server.protocol.CharacterProtocol;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
|
||||
/**
|
||||
@ -28,7 +30,10 @@ public class PlayerCharacterCreation {
|
||||
|
||||
//
|
||||
//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();
|
||||
|
||||
//
|
||||
@ -67,21 +72,23 @@ public class PlayerCharacterCreation {
|
||||
* @param serverConnectionHandler The connection handler
|
||||
*/
|
||||
public static void attachEntityToPlayerObject(Entity entity, Player playerObject, ServerConnectionHandler serverConnectionHandler){
|
||||
int playerCharacterId = entity.getId();
|
||||
serverConnectionHandler.setPlayerEntityId(playerCharacterId);
|
||||
int playerEntityId = entity.getId();
|
||||
serverConnectionHandler.setPlayerEntityId(playerEntityId);
|
||||
CreatureUtils.setControllerPlayerId(entity, serverConnectionHandler.getPlayerId());
|
||||
Player player = serverConnectionHandler.getPlayer();
|
||||
player.setPlayerEntity(entity);
|
||||
//custom player btrees
|
||||
PlayerCharacterCreation.addPlayerServerBTrees(entity);
|
||||
PlayerCharacterCreation.addPlayerServerBTrees(entity, serverConnectionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds behavior trees that are unique to players a given entity
|
||||
* @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);
|
||||
ServerCharacterData.attachServerPlayerViewDirTree(entity, serverConnectionHandler.getCharacterId());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,7 +98,10 @@ public class PlayerCharacterCreation {
|
||||
* @return The spawn point for the player
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ import org.joml.Vector3i;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.server.ServerCharacterData;
|
||||
import electrosphere.server.character.CharacterService;
|
||||
import electrosphere.server.content.serialization.ContentSerialization;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.datacell.ServerDataCell;
|
||||
@ -78,10 +80,18 @@ public class ServerContentManager {
|
||||
* @param entities the collection of entities to save
|
||||
*/
|
||||
public void saveContentToDisk(Long locationKey, Collection<Entity> entities){
|
||||
//serialize all non-character entities
|
||||
ContentSerialization serialization = ContentSerialization.constructContentSerialization(entities);
|
||||
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSave.getName());
|
||||
String fullPath = dirPath + "/content/" + locationKey + ".dat";
|
||||
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 {
|
||||
|
||||
|
||||
//The entities, serialized
|
||||
/**
|
||||
* The entities, serialized
|
||||
*/
|
||||
List<EntitySerialization> serializedEntities = new LinkedList<EntitySerialization>();
|
||||
|
||||
/**
|
||||
@ -38,50 +40,53 @@ public class ContentSerialization {
|
||||
if(!CreatureUtils.hasControllerPlayerId(entity)){
|
||||
EntityType type = CommonEntityUtils.getEntityType(entity);
|
||||
if(type != null){
|
||||
switch(type){
|
||||
case CREATURE: {
|
||||
EntitySerialization serializedEntity = constructEntitySerialization(entity);
|
||||
rVal.serializedEntities.add(serializedEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
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)));
|
||||
}
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
throw new Error("Trying to save entity that does not have a type!");
|
||||
}
|
||||
}
|
||||
}
|
||||
return rVal;
|
||||
return serializedEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -37,7 +37,6 @@ import electrosphere.server.datacell.ServerDataCell;
|
||||
import electrosphere.server.datacell.interfaces.DataCellManager;
|
||||
import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
||||
import electrosphere.server.datacell.physics.PhysicsDataCell;
|
||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||
import electrosphere.server.fluid.manager.ServerFluidChunk;
|
||||
import electrosphere.server.fluid.manager.ServerFluidManager;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
||||
|
||||
@ -13,6 +13,11 @@ import java.util.Properties;
|
||||
*/
|
||||
public class DatabaseController {
|
||||
|
||||
/**
|
||||
* file extension for allowed database files to open
|
||||
*/
|
||||
public static final String FILE_EXT = ".sqlite";
|
||||
|
||||
/**
|
||||
* The database connection
|
||||
*/
|
||||
@ -43,6 +48,7 @@ public class DatabaseController {
|
||||
* Executes a write statement to the database
|
||||
* @param statementRaw The raw string for the statement
|
||||
* @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){
|
||||
try {
|
||||
|
||||
@ -90,21 +90,24 @@ public class DatabaseResultIterator implements Iterator<DatabaseResultRow> {
|
||||
//increment at the beginning because result sets are indexed starting at 1
|
||||
columnIncrementer++;
|
||||
switch(type){
|
||||
case Types.INTEGER:
|
||||
case Types.INTEGER: {
|
||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getInt(columnIncrementer));
|
||||
break;
|
||||
case Types.VARCHAR:
|
||||
} break;
|
||||
case Types.VARCHAR: {
|
||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getString(columnIncrementer));
|
||||
break;
|
||||
case Types.BIGINT:
|
||||
} break;
|
||||
case Types.BIGINT: {
|
||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getLong(columnIncrementer));
|
||||
break;
|
||||
case Types.FLOAT:
|
||||
} break;
|
||||
case Types.FLOAT: {
|
||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getFloat(columnIncrementer));
|
||||
break;
|
||||
case Types.DOUBLE:
|
||||
} break;
|
||||
case Types.DOUBLE: {
|
||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getDouble(columnIncrementer));
|
||||
break;
|
||||
} break;
|
||||
case Types.REAL: {
|
||||
row.putValue(metadata.getColumnName(columnIncrementer), rs.getDouble(columnIncrementer));
|
||||
} break;
|
||||
default:
|
||||
LoggerInterface.loggerEngine.WARNING("Unsupported type from database in DatabaseResultIterator " + type);
|
||||
break;
|
||||
|
||||
@ -3,11 +3,14 @@ package electrosphere.server.db;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A row result from a database operation
|
||||
*/
|
||||
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>();
|
||||
|
||||
/**
|
||||
|
||||
@ -6,38 +6,40 @@ import electrosphere.util.FileUtils;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author satellite
|
||||
* Utilities for working with the database
|
||||
*/
|
||||
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){
|
||||
String sanitizedPath = FileUtils.sanitizeFilePath(path);
|
||||
if(!FileUtils.checkFileExists(sanitizedPath)){
|
||||
return false;
|
||||
}
|
||||
String dbFilePath = sanitizedPath + "/central.db";
|
||||
String dbFilePath = sanitizedPath + "/central" + DatabaseController.FILE_EXT;
|
||||
if(Globals.dbController == null){
|
||||
Globals.dbController = new DatabaseController();
|
||||
}
|
||||
if(!Globals.dbController.isConnected()){
|
||||
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
|
||||
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();
|
||||
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){
|
||||
String rawScript = "";
|
||||
try {
|
||||
|
||||
@ -8,6 +8,7 @@ import electrosphere.entity.scene.SceneFile;
|
||||
import electrosphere.entity.scene.SceneLoader;
|
||||
import electrosphere.game.server.world.ServerWorldData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.server.db.DatabaseController;
|
||||
import electrosphere.server.db.DatabaseUtils;
|
||||
import electrosphere.server.fluid.generation.DefaultFluidGenerator;
|
||||
import electrosphere.server.fluid.manager.ServerFluidManager;
|
||||
@ -155,6 +156,9 @@ public class SaveUtils {
|
||||
|
||||
//write server structures
|
||||
Globals.realmManager.save(saveName);
|
||||
|
||||
//close the server
|
||||
Globals.server.close();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,7 +215,7 @@ public class SaveUtils {
|
||||
}
|
||||
|
||||
//load db
|
||||
String dbFilePath = FileUtils.sanitizeFilePath(dirPath) + "/central.db";
|
||||
String dbFilePath = FileUtils.sanitizeFilePath(dirPath) + "/central" + DatabaseController.FILE_EXT;
|
||||
Globals.dbController.connect(dbFilePath);
|
||||
|
||||
return true;
|
||||
|
||||
@ -17,6 +17,11 @@
|
||||
"messageName" : "Pong",
|
||||
"description" : "Replies to a ping from the other side of the socket",
|
||||
"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