network refactor
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-07-29 21:27:13 -04:00
parent be5c24a7fc
commit b37f80c18d
36 changed files with 772 additions and 469 deletions

View File

@ -480,6 +480,7 @@ Alignment work for human right hand
(07/29/2024) (07/29/2024)
Option to load all cells on init scene file Option to load all cells on init scene file
Insidious Entity protocol bugfix on server Insidious Entity protocol bugfix on server
Refactor network protocols to enforce async/sync split
# TODO # TODO

View File

@ -273,7 +273,7 @@ public class Main {
if(Globals.clientConnection != null){ if(Globals.clientConnection != null){
Globals.profiler.beginCpuSample("Client networking"); Globals.profiler.beginCpuSample("Client networking");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin parse client messages"); LoggerInterface.loggerEngine.DEBUG_LOOP("Begin parse client messages");
Globals.clientConnection.parseMessages(); Globals.clientConnection.parseMessagesSynchronous();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }
@ -369,7 +369,6 @@ public class Main {
/// ///
/// S H U T D O W N C H E C K /// S H U T D O W N C H E C K
/// ///
if(Globals.HEADLESS){ if(Globals.HEADLESS){
if(Globals.ENGINE_SHUTDOWN_FLAG){ if(Globals.ENGINE_SHUTDOWN_FLAG){
running = false; running = false;
@ -385,9 +384,9 @@ public class Main {
// ///
// C L E A N U P T I M E V A R I A B L E S /// C L E A N U P T I M E V A R I A B L E S
// ///
Globals.profiler.beginCpuSample("sleep"); Globals.profiler.beginCpuSample("sleep");
if(Globals.timekeeper.getMostRecentRawFrametime() < targetFramePeriod){ if(Globals.timekeeper.getMostRecentRawFrametime() < targetFramePeriod){
sleep((int)(1000.0 * (targetFramePeriod - Globals.timekeeper.getMostRecentRawFrametime()))); sleep((int)(1000.0 * (targetFramePeriod - Globals.timekeeper.getMostRecentRawFrametime())));
@ -401,9 +400,9 @@ public class Main {
} }
// ///
// End main loop /// E N D M A I N L O O P
// ///
LoggerInterface.loggerEngine.DEBUG_LOOP("End Main Loop Frame"); LoggerInterface.loggerEngine.DEBUG_LOOP("End Main Loop Frame");
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();

View File

@ -3,7 +3,6 @@ package electrosphere.net.client;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main; import electrosphere.engine.Main;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.client.protocol.ClientProtocol;
import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.ServerMessage; import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.message.NetworkMessage.MessageType; import electrosphere.net.parser.net.message.NetworkMessage.MessageType;
@ -13,21 +12,34 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* Client networking thread * Client networking thread
*/ */
public class ClientNetworking implements Runnable{ public class ClientNetworking implements Runnable {
/**
* The server's address
*/
String address; String address;
/**
* The port on the server
*/
int port; int port;
/**
* Controls whether the connection is formed locally (with lists) or not (with sockets)
*/
boolean local = false; boolean local = false;
/**
* The socket for the connection
*/
public Socket socket; public Socket socket;
// CryptoInputStream inputStream; // CryptoInputStream inputStream;
// CryptoOutputStream outputStream; // CryptoOutputStream outputStream;
InputStream inputStream; InputStream inputStream;
@ -35,8 +47,14 @@ public class ClientNetworking implements Runnable{
boolean initialized; boolean initialized;
NetworkParser parser; NetworkParser parser;
ClientProtocol clientProtocol = new ClientProtocol(); /**
* The client protocol
*/
MessageProtocol messageProtocol = new MessageProtocol();
/**
* Maximum number of times to try connecting to a server
*/
static final int MAX_CONNECTION_ATTEMPTS = 10; static final int MAX_CONNECTION_ATTEMPTS = 10;
//set to true to also get ping and pong messages in debug logging //set to true to also get ping and pong messages in debug logging
@ -52,11 +70,21 @@ public class ClientNetworking implements Runnable{
//debugging stuff //debugging stuff
String netMonitorHandle = null; String netMonitorHandle = null;
/**
* Creates a ClientNetworking object with a server address and port
* @param address The address of the server
* @param port The port to connect to on the server
*/
public ClientNetworking(String address, int port){ public ClientNetworking(String address, int port){
this.address = address; this.address = address;
this.port = port; this.port = port;
} }
/**
* Creates a ClientNetworking object with a pair of streams
* @param clientInputStream The input stream
* @param clientOutputStream The output stream
*/
public ClientNetworking(InputStream clientInputStream, OutputStream clientOutputStream){ public ClientNetworking(InputStream clientInputStream, OutputStream clientOutputStream){
this.local = true; this.local = true;
this.inputStream = clientInputStream; this.inputStream = clientInputStream;
@ -83,7 +111,14 @@ public class ClientNetworking implements Runnable{
// } // }
//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>();
///
///
/// SETUP
///
///
if(!this.local) { if(!this.local) {
//attempt connection //attempt connection
@ -123,6 +158,14 @@ public class ClientNetworking implements Runnable{
//create parser //create parser
parser = new NetworkParser(inputStream,outputStream); parser = new NetworkParser(inputStream,outputStream);
///
///
/// MAIN LOOP
///
///
//start parsing messages //start parsing messages
initialized = true; initialized = true;
while(Main.isRunning()){ while(Main.isRunning()){
@ -130,6 +173,8 @@ public class ClientNetworking implements Runnable{
parser.readMessagesIn(); parser.readMessagesIn();
//outgoing messages //outgoing messages
parser.pushMessagesOut(); parser.pushMessagesOut();
//parses messages asynchronously
this.parseMessagesAsynchronously();
//ping logic //ping logic
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
@ -160,9 +205,11 @@ public class ClientNetworking implements Runnable{
} }
static final int MAX_MESSAGES_PARSED = 1000;
public void parseMessages(){ /**
* Parses messages asynchronously
*/
public void parseMessagesAsynchronously(){
if(initialized){ if(initialized){
while(parser.hasIncomingMessaage()){ while(parser.hasIncomingMessaage()){
NetworkMessage message = parser.popIncomingMessage(); NetworkMessage message = parser.popIncomingMessage();
@ -174,12 +221,20 @@ public class ClientNetworking implements Runnable{
printMessage(message); printMessage(message);
//do something //do something
Globals.profiler.beginCpuSample("ClientProtocol.handleMessage"); Globals.profiler.beginCpuSample("ClientProtocol.handleMessage");
clientProtocol.handleMessage(message); this.messageProtocol.handleAsyncMessage(message);
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }
} }
} }
/**
* Parses messages from the client
*/
public void parseMessagesSynchronous(){
this.messageProtocol.handleSyncMessages();
}
/** /**
* Print out the network message type, this only prints ping and pong if echoPings is true * Print out the network message type, this only prints ping and pong if echoPings is true
*/ */
@ -200,7 +255,10 @@ public class ClientNetworking implements Runnable{
} }
} }
/**
* Queues an outgoing message
* @param message The message to send to the server
*/
public void queueOutgoingMessage(NetworkMessage message){ public void queueOutgoingMessage(NetworkMessage message){
//net monitor stuff //net monitor stuff
if(Globals.netMonitor != null){ if(Globals.netMonitor != null){
@ -210,8 +268,12 @@ public class ClientNetworking implements Runnable{
parser.addOutgoingMessage(message); parser.addOutgoingMessage(message);
} }
public ClientProtocol getClientProtocol(){ /**
return clientProtocol; * Gets the message protocol
* @return The message protocol inside this object
*/
public MessageProtocol getMessageProtocol(){
return messageProtocol;
} }
public void markReceivedPongMessage(){ public void markReceivedPongMessage(){

View File

@ -0,0 +1,151 @@
package electrosphere.net.client;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
import electrosphere.engine.Globals;
import electrosphere.net.client.protocol.AuthProtocol;
import electrosphere.net.client.protocol.CharacterProtocol;
import electrosphere.net.client.protocol.EntityProtocol;
import electrosphere.net.client.protocol.InventoryProtocol;
import electrosphere.net.client.protocol.LoreProtocol;
import electrosphere.net.client.protocol.PlayerProtocol;
import electrosphere.net.client.protocol.ServerProtocol;
import electrosphere.net.client.protocol.SynchronizationProtocol;
import electrosphere.net.client.protocol.TerrainProtocol;
import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.net.parser.net.message.TerrainMessage;
/**
* The message protocol on the client
*/
public class MessageProtocol {
/**
* Tracks whether the message protocol has received world data or not
*/
boolean hasReceivedWorld = false;
//the lock used for synchronizing the synchronous message queue
Semaphore synchronousMessageLock = new Semaphore(1);
//the queue of synchonous network messages
List<NetworkMessage> synchronousMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
//The individual protocols
AuthProtocol authProtocol = new AuthProtocol();
CharacterProtocol characterProtocol = new CharacterProtocol();
EntityProtocol entityProtocol = new EntityProtocol();
InventoryProtocol inventoryProtocol = new InventoryProtocol();
LoreProtocol loreProtocol = new LoreProtocol();
PlayerProtocol playerProtocol = new PlayerProtocol();
ServerProtocol serverProtocol = new ServerProtocol();
SynchronizationProtocol synchronizationProtocol = new SynchronizationProtocol();
TerrainProtocol terrainProtocol = new TerrainProtocol();
/**
* Asynchronously handles a message
* @param message The message
*/
public void handleAsyncMessage(NetworkMessage message){
Globals.profiler.beginAggregateCpuSample("MessageProtocol(client).handleAsyncMessage");
NetworkMessage result = null;
switch(message.getType()){
case AUTH_MESSAGE:
result = this.authProtocol.handleAsyncMessage((AuthMessage)message);
break;
case CHARACTER_MESSAGE:
result = this.characterProtocol.handleAsyncMessage((CharacterMessage)message);
break;
case ENTITY_MESSAGE:
result = this.entityProtocol.handleAsyncMessage((EntityMessage)message);
break;
case INVENTORY_MESSAGE:
result = this.inventoryProtocol.handleAsyncMessage((InventoryMessage)message);
break;
case LORE_MESSAGE:
result = this.loreProtocol.handleAsyncMessage((LoreMessage)message);
break;
case PLAYER_MESSAGE:
result = this.playerProtocol.handleAsyncMessage((PlayerMessage)message);
break;
case SERVER_MESSAGE:
result = this.serverProtocol.handleAsyncMessage((ServerMessage)message);
break;
case SYNCHRONIZATION_MESSAGE:
result = this.synchronizationProtocol.handleAsyncMessage((SynchronizationMessage)message);
break;
case TERRAIN_MESSAGE:
result = this.terrainProtocol.handleAsyncMessage((TerrainMessage)message);
break;
}
//queue bounced messages for synchronous resolution
if(result != null){
this.synchronousMessageLock.acquireUninterruptibly();
this.synchronousMessageQueue.add(result);
this.synchronousMessageLock.release();
}
Globals.profiler.endCpuSample();
}
public void handleSyncMessages(){
Globals.profiler.beginAggregateCpuSample("MessageProtocol(client).handleSyncMessages");
this.synchronousMessageLock.acquireUninterruptibly();
for(NetworkMessage message : synchronousMessageQueue){
switch(message.getType()){
case AUTH_MESSAGE:
this.authProtocol.handleSyncMessage((AuthMessage)message);
break;
case CHARACTER_MESSAGE:
this.characterProtocol.handleSyncMessage((CharacterMessage)message);
break;
case ENTITY_MESSAGE:
this.entityProtocol.handleSyncMessage((EntityMessage)message);
break;
case INVENTORY_MESSAGE:
this.inventoryProtocol.handleSyncMessage((InventoryMessage)message);
break;
case LORE_MESSAGE:
this.loreProtocol.handleSyncMessage((LoreMessage)message);
break;
case PLAYER_MESSAGE:
this.playerProtocol.handleSyncMessage((PlayerMessage)message);
break;
case SERVER_MESSAGE:
this.serverProtocol.handleSyncMessage((ServerMessage)message);
break;
case SYNCHRONIZATION_MESSAGE:
this.synchronizationProtocol.handleSyncMessage((SynchronizationMessage)message);
break;
case TERRAIN_MESSAGE:
this.terrainProtocol.handleSyncMessage((TerrainMessage)message);
break;
}
}
synchronousMessageQueue.clear();
this.synchronousMessageLock.release();
Globals.profiler.endCpuSample();
}
public void setHasReceivedWorld(boolean hasReceivedWorld){
this.hasReceivedWorld = hasReceivedWorld;
}
public boolean hasReceivedWorld(){
return hasReceivedWorld;
}
}

View File

@ -4,10 +4,15 @@ import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.AuthMessage; import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.LoreMessage; import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class AuthProtocol { /**
* The client protocol for handling auth messages
*/
public class AuthProtocol implements ClientProtocolTemplate<AuthMessage> {
protected static void handleAuthenticationMessage(AuthMessage message){ @Override
public AuthMessage handleAsyncMessage(AuthMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case AUTHREQUEST: case AUTHREQUEST:
//Try login //Try login
@ -31,6 +36,18 @@ public class AuthProtocol {
//silently ignore //silently ignore
break; break;
} }
return null;
}
@Override
public void handleSyncMessage(AuthMessage message) {
switch(message.getMessageSubtype()){
case AUTHREQUEST:
case AUTHSUCCESS:
case AUTHFAILURE:
case AUTHDETAILS:
break;
}
} }
} }

View File

@ -5,10 +5,20 @@ import electrosphere.engine.loadingthreads.LoadingThread;
import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType; import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType;
import electrosphere.net.parser.net.message.CharacterMessage; import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class CharacterProtocol { /**
* The client protocol for handling character messages
*/
public class CharacterProtocol implements ClientProtocolTemplate<CharacterMessage> {
protected static void handleCharacterMessage(CharacterMessage message){ @Override
public CharacterMessage handleAsyncMessage(CharacterMessage message) {
return message;
}
@Override
public void handleSyncMessage(CharacterMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case RESPONSECREATECHARACTERSUCCESS: case RESPONSECREATECHARACTERSUCCESS:
//trigger request to spawn character //trigger request to spawn character

View File

@ -1,78 +0,0 @@
package electrosphere.net.client.protocol;
import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.net.parser.net.message.TerrainMessage;
public class ClientProtocol {
boolean isLoading = true;
boolean hasReceivedWorld = false;
public void handleMessage(NetworkMessage message){
Globals.profiler.beginAggregateCpuSample("ClientProtocol.handleMessage");
switch(message.getType()){
case ENTITY_MESSAGE:
EntityProtocol.handleEntityMessage((EntityMessage)message);
break;
case PLAYER_MESSAGE:
PlayerProtocol.handlePlayerMessage((PlayerMessage)message);
break;
case TERRAIN_MESSAGE:
TerrainProtocol.handleTerrainMessage((TerrainMessage)message);
break;
case AUTH_MESSAGE:
AuthProtocol.handleAuthenticationMessage((AuthMessage)message);
break;
case SERVER_MESSAGE:
ServerProtocol.handleServerMessage((ServerMessage)message);
break;
case LORE_MESSAGE:
LoreProtocol.handleLoreMessage((LoreMessage)message);
break;
case CHARACTER_MESSAGE:
CharacterProtocol.handleCharacterMessage((CharacterMessage)message);
break;
case INVENTORY_MESSAGE:
InventoryProtocol.handleInventoryMessage((InventoryMessage)message);
break;
case SYNCHRONIZATION_MESSAGE:
SynchronizationProtocol.handleSynchronizationMessage((SynchronizationMessage)message);
break;
}
Globals.profiler.endCpuSample();
}
// void handleStatusMessage(StatusMessage message){
// switch(message.getMessageSubtype()){
// case READY:
// isLoading = false;
// break;
// }
// }
public void setHasReceivedWorld(boolean hasReceivedWorld){
this.hasReceivedWorld = hasReceivedWorld;
}
public boolean isLoading(){
return isLoading;
}
public boolean hasReceivedWorld(){
return hasReceivedWorld;
}
}

View File

@ -22,12 +22,13 @@ import electrosphere.game.data.creature.type.ViewModelData;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.EntityMessage.EntityMessageType; import electrosphere.net.parser.net.message.EntityMessage.EntityMessageType;
import electrosphere.net.template.ClientProtocolTemplate;
import electrosphere.util.Utilities; import electrosphere.util.Utilities;
/** /**
* Client entity network protocol * Client entity network protocol
*/ */
public class EntityProtocol { public class EntityProtocol implements ClientProtocolTemplate<EntityMessage> {
//Messages to ignore when complaining about messages that have nonexistant entity associated //Messages to ignore when complaining about messages that have nonexistant entity associated
static List<EntityMessageType> spawnMessageTypes = Arrays.asList(new EntityMessageType[]{ static List<EntityMessageType> spawnMessageTypes = Arrays.asList(new EntityMessageType[]{
@ -38,11 +39,13 @@ public class EntityProtocol {
EntityMessageType.SPAWNOBJECT, EntityMessageType.SPAWNOBJECT,
}); });
/** @Override
* Handles a single clientbound entity message public EntityMessage handleAsyncMessage(EntityMessage message) {
* @param message The message to handle return message;
*/ }
protected static void handleEntityMessage(EntityMessage message){
@Override
public void handleSyncMessage(EntityMessage message) {
Globals.profiler.beginCpuSample("EntityProtocol.handleEntityMessage"); Globals.profiler.beginCpuSample("EntityProtocol.handleEntityMessage");
LoggerInterface.loggerNetworking.DEBUG_LOOP("Parse entity message of type " + message.getMessageSubtype()); LoggerInterface.loggerNetworking.DEBUG_LOOP("Parse entity message of type " + message.getMessageSubtype());

View File

@ -8,9 +8,20 @@ import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.game.data.creature.type.equip.EquipPoint; import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.InventoryMessage; import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class InventoryProtocol { /**
protected static void handleInventoryMessage(InventoryMessage message){ * The client protocol for handling inventory messages
*/
public class InventoryProtocol implements ClientProtocolTemplate<InventoryMessage> {
@Override
public InventoryMessage handleAsyncMessage(InventoryMessage message) {
return message;
}
@Override
public void handleSyncMessage(InventoryMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case ADDITEMTOINVENTORY: case ADDITEMTOINVENTORY:
LoggerInterface.loggerNetworking.DEBUG("[CLIENT] ADD ITEM TO INVENTORY " + message.getentityId()); LoggerInterface.loggerNetworking.DEBUG("[CLIENT] ADD ITEM TO INVENTORY " + message.getentityId());

View File

@ -6,10 +6,17 @@ import com.google.gson.Gson;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.LoreMessage; import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class LoreProtocol { public class LoreProtocol implements ClientProtocolTemplate<LoreMessage> {
protected static void handleLoreMessage(LoreMessage message){ @Override
public LoreMessage handleAsyncMessage(LoreMessage message) {
return message;
}
@Override
public void handleSyncMessage(LoreMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case RESPONSERACES: case RESPONSERACES:
//we get back the race list as a json array, deserialize, and push into type loader //we get back the race list as a json array, deserialize, and push into type loader

View File

@ -6,10 +6,20 @@ import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.PlayerMessage; import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.net.template.ClientProtocolTemplate;
public class PlayerProtocol { /**
* The client protocol for handling player messages
*/
public class PlayerProtocol implements ClientProtocolTemplate<PlayerMessage> {
protected static void handlePlayerMessage(PlayerMessage message){ @Override
public PlayerMessage handleAsyncMessage(PlayerMessage message) {
return message;
}
@Override
public void handleSyncMessage(PlayerMessage message) {
Globals.profiler.beginCpuSample("PlayerProtocol.handlePlayerMessage"); Globals.profiler.beginCpuSample("PlayerProtocol.handlePlayerMessage");
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case SET_ID: case SET_ID:

View File

@ -2,10 +2,20 @@ package electrosphere.net.client.protocol;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.ServerMessage; import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class ServerProtocol { /**
* The client protocol for handling server messages
*/
public class ServerProtocol implements ClientProtocolTemplate<ServerMessage> {
protected static void handleServerMessage(ServerMessage message){ @Override
public ServerMessage handleAsyncMessage(ServerMessage message) {
return message;
}
@Override
public void handleSyncMessage(ServerMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case PING: case PING:
Globals.clientConnection.queueOutgoingMessage(ServerMessage.constructPongMessage()); Globals.clientConnection.queueOutgoingMessage(ServerMessage.constructPongMessage());

View File

@ -2,10 +2,20 @@ package electrosphere.net.client.protocol;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.SynchronizationMessage; import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class SynchronizationProtocol { /**
* The client protocol for handling synchronization messages
*/
public class SynchronizationProtocol implements ClientProtocolTemplate<SynchronizationMessage> {
protected static void handleSynchronizationMessage(SynchronizationMessage message){ @Override
public SynchronizationMessage handleAsyncMessage(SynchronizationMessage message) {
return message;
}
@Override
public void handleSyncMessage(SynchronizationMessage message) {
Globals.profiler.beginCpuSample("SynchronizationProtocol.handleSynchronizationMessage"); Globals.profiler.beginCpuSample("SynchronizationProtocol.handleSynchronizationMessage");
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case UPDATECLIENTSTATE: case UPDATECLIENTSTATE:

View File

@ -9,10 +9,20 @@ import electrosphere.collision.CollisionWorldData;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class TerrainProtocol { /**
* The client protocol for handling terrain messages
*/
public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
protected static void handleTerrainMessage(TerrainMessage message){ @Override
public TerrainMessage handleAsyncMessage(TerrainMessage message) {
return message;
}
@Override
public void handleSyncMessage(TerrainMessage message) {
Globals.profiler.beginCpuSample("TerrainProtocol.handleTerrainMessage"); Globals.profiler.beginCpuSample("TerrainProtocol.handleTerrainMessage");
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case RESPONSEMETADATA: case RESPONSEMETADATA:
@ -25,7 +35,7 @@ public class TerrainProtocol {
message.getworldSizeDiscrete() message.getworldSizeDiscrete()
); );
Globals.clientSceneWrapper.getCollisionEngine().setCollisionWorldData(new CollisionWorldData(Globals.clientWorldData)); Globals.clientSceneWrapper.getCollisionEngine().setCollisionWorldData(new CollisionWorldData(Globals.clientWorldData));
Globals.clientConnection.getClientProtocol().setHasReceivedWorld(true); Globals.clientConnection.getMessageProtocol().setHasReceivedWorld(true);
break; break;
case SPAWNPOSITION: case SPAWNPOSITION:
LoggerInterface.loggerNetworking.WARNING("Received spawnPosition packet on client. This is deprecated!"); LoggerInterface.loggerNetworking.WARNING("Received spawnPosition packet on client. This is deprecated!");

View File

@ -87,7 +87,7 @@ public class AuthMessage extends NetworkMessage {
public static boolean canParseAuthDetailsMessage(CircularByteBuffer byteBuffer){ public static boolean canParseAuthDetailsMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int userSize = 0; int userSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;

View File

@ -91,7 +91,7 @@ public class CharacterMessage extends NetworkMessage {
public static boolean canParseResponseCharacterListMessage(CircularByteBuffer byteBuffer){ public static boolean canParseResponseCharacterListMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -124,7 +124,7 @@ public class CharacterMessage extends NetworkMessage {
public static boolean canParseRequestCreateCharacterMessage(CircularByteBuffer byteBuffer){ public static boolean canParseRequestCreateCharacterMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -193,7 +193,7 @@ public class CharacterMessage extends NetworkMessage {
public static boolean canParseResponseSpawnCharacterMessage(CircularByteBuffer byteBuffer){ public static boolean canParseResponseSpawnCharacterMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;

View File

@ -343,7 +343,7 @@ public class EntityMessage extends NetworkMessage {
public static boolean canParseCreateMessage(CircularByteBuffer byteBuffer){ public static boolean canParseCreateMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -401,7 +401,7 @@ public class EntityMessage extends NetworkMessage {
public static boolean canParseSpawnCreatureMessage(CircularByteBuffer byteBuffer){ public static boolean canParseSpawnCreatureMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -454,7 +454,7 @@ public class EntityMessage extends NetworkMessage {
public static boolean canParseSpawnItemMessage(CircularByteBuffer byteBuffer){ public static boolean canParseSpawnItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -507,7 +507,7 @@ public class EntityMessage extends NetworkMessage {
public static boolean canParseSpawnObjectMessage(CircularByteBuffer byteBuffer){ public static boolean canParseSpawnObjectMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -690,7 +690,7 @@ public class EntityMessage extends NetworkMessage {
public static boolean canParseattachEntityToEntityMessage(CircularByteBuffer byteBuffer){ public static boolean canParseattachEntityToEntityMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -733,7 +733,7 @@ public class EntityMessage extends NetworkMessage {
public static boolean canParseSpawnFoliageSeedMessage(CircularByteBuffer byteBuffer){ public static boolean canParseSpawnFoliageSeedMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }

View File

@ -124,7 +124,7 @@ public class InventoryMessage extends NetworkMessage {
public static boolean canParseaddItemToInventoryMessage(CircularByteBuffer byteBuffer){ public static boolean canParseaddItemToInventoryMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -176,7 +176,7 @@ public class InventoryMessage extends NetworkMessage {
public static boolean canParseclientRequestEquipItemMessage(CircularByteBuffer byteBuffer){ public static boolean canParseclientRequestEquipItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int equipPointIdSize = 0; int equipPointIdSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -214,7 +214,7 @@ public class InventoryMessage extends NetworkMessage {
public static boolean canParseserverCommandMoveItemContainerMessage(CircularByteBuffer byteBuffer){ public static boolean canParseserverCommandMoveItemContainerMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -257,7 +257,7 @@ public class InventoryMessage extends NetworkMessage {
public static boolean canParseserverCommandEquipItemMessage(CircularByteBuffer byteBuffer){ public static boolean canParseserverCommandEquipItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -315,7 +315,7 @@ public class InventoryMessage extends NetworkMessage {
public static boolean canParseserverCommandUnequipItemMessage(CircularByteBuffer byteBuffer){ public static boolean canParseserverCommandUnequipItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -353,7 +353,7 @@ public class InventoryMessage extends NetworkMessage {
public static boolean canParseclientRequestUnequipItemMessage(CircularByteBuffer byteBuffer){ public static boolean canParseclientRequestUnequipItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int equipPointIdSize = 0; int equipPointIdSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -386,7 +386,7 @@ public class InventoryMessage extends NetworkMessage {
public static boolean canParseclientRequestPerformItemActionMessage(CircularByteBuffer byteBuffer){ public static boolean canParseclientRequestPerformItemActionMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int equipPointIdSize = 0; int equipPointIdSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;

View File

@ -64,7 +64,7 @@ public class LoreMessage extends NetworkMessage {
public static boolean canParseResponseRacesMessage(CircularByteBuffer byteBuffer){ public static boolean canParseResponseRacesMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;

View File

@ -125,7 +125,7 @@ public class SynchronizationMessage extends NetworkMessage {
public static boolean canParseUpdateClientStringStateMessage(CircularByteBuffer byteBuffer){ public static boolean canParseUpdateClientStringStateMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -205,7 +205,7 @@ public class SynchronizationMessage extends NetworkMessage {
public static boolean canParseLoadSceneMessage(CircularByteBuffer byteBuffer){ public static boolean canParseLoadSceneMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int stringValueSize = 0; int stringValueSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;

View File

@ -451,7 +451,7 @@ public class TerrainMessage extends NetworkMessage {
public static boolean canParsesendChunkDataMessage(CircularByteBuffer byteBuffer){ public static boolean canParsesendChunkDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -519,7 +519,7 @@ public class TerrainMessage extends NetworkMessage {
public static boolean canParseSendReducedChunkDataMessage(CircularByteBuffer byteBuffer){ public static boolean canParseSendReducedChunkDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -590,7 +590,7 @@ public class TerrainMessage extends NetworkMessage {
public static boolean canParsesendFluidDataMessage(CircularByteBuffer byteBuffer){ public static boolean canParsesendFluidDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }
@ -638,7 +638,7 @@ public class TerrainMessage extends NetworkMessage {
public static boolean canParseupdateFluidDataMessage(CircularByteBuffer byteBuffer){ public static boolean canParseupdateFluidDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} }

View File

@ -0,0 +1,154 @@
package electrosphere.net.server;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.protocol.AuthProtocol;
import electrosphere.net.server.protocol.CharacterProtocol;
import electrosphere.net.server.protocol.EntityProtocol;
import electrosphere.net.server.protocol.InventoryProtocol;
import electrosphere.net.server.protocol.LoreProtocol;
import electrosphere.net.server.protocol.PlayerProtocol;
import electrosphere.net.server.protocol.ServerProtocol;
import electrosphere.net.server.protocol.SynchronizationProtocol;
import electrosphere.net.server.protocol.TerrainProtocol;
/**
* The server message protocol
*/
public class MessageProtocol {
//the lock used for synchronizing the synchronous message queue
Semaphore synchronousMessageLock = new Semaphore(1);
//the queue of synchonous network messages
List<NetworkMessage> synchronousMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
//The server connection handler
ServerConnectionHandler serverConnectionHandler;
//The individual protocols
AuthProtocol authProtocol = new AuthProtocol();
CharacterProtocol characterProtocol = new CharacterProtocol();
EntityProtocol entityProtocol = new EntityProtocol();
InventoryProtocol inventoryProtocol = new InventoryProtocol();
LoreProtocol loreProtocol = new LoreProtocol();
PlayerProtocol playerProtocol = new PlayerProtocol();
ServerProtocol serverProtocol = new ServerProtocol();
SynchronizationProtocol synchronizationProtocol = new SynchronizationProtocol();
TerrainProtocol terrainProtocol = new TerrainProtocol();
/**
* Constructor
* @param serverConnectionHandler The linked server connection handler
*/
public MessageProtocol(ServerConnectionHandler serverConnectionHandler){
this.serverConnectionHandler = serverConnectionHandler;
}
/**
* Asynchronously handles a message
* @param message The message
*/
public void handleAsyncMessage(NetworkMessage message){
Globals.profiler.beginAggregateCpuSample("MessageProtocol(client).handleAsyncMessage");
printMessage(message);
NetworkMessage result = null;
switch(message.getType()){
case AUTH_MESSAGE:
result = this.authProtocol.handleAsyncMessage(serverConnectionHandler, (AuthMessage)message);
break;
case CHARACTER_MESSAGE:
result = this.characterProtocol.handleAsyncMessage(serverConnectionHandler, (CharacterMessage)message);
break;
case ENTITY_MESSAGE:
result = this.entityProtocol.handleAsyncMessage(serverConnectionHandler, (EntityMessage)message);
break;
case INVENTORY_MESSAGE:
result = this.inventoryProtocol.handleAsyncMessage(serverConnectionHandler, (InventoryMessage)message);
break;
case LORE_MESSAGE:
result = this.loreProtocol.handleAsyncMessage(serverConnectionHandler, (LoreMessage)message);
break;
case PLAYER_MESSAGE:
result = this.playerProtocol.handleAsyncMessage(serverConnectionHandler, (PlayerMessage)message);
break;
case SERVER_MESSAGE:
result = this.serverProtocol.handleAsyncMessage(serverConnectionHandler, (ServerMessage)message);
break;
case SYNCHRONIZATION_MESSAGE:
result = this.synchronizationProtocol.handleAsyncMessage(serverConnectionHandler, (SynchronizationMessage)message);
break;
case TERRAIN_MESSAGE:
result = this.terrainProtocol.handleAsyncMessage(serverConnectionHandler, (TerrainMessage)message);
break;
}
//queue bounced messages for synchronous resolution
if(result != null){
this.synchronousMessageLock.acquireUninterruptibly();
this.synchronousMessageQueue.add(result);
this.synchronousMessageLock.release();
}
Globals.profiler.endCpuSample();
}
public void handleSyncMessages(){
Globals.profiler.beginAggregateCpuSample("MessageProtocol(client).handleSyncMessages");
this.synchronousMessageLock.acquireUninterruptibly();
for(NetworkMessage message : synchronousMessageQueue){
switch(message.getType()){
case AUTH_MESSAGE:
this.authProtocol.handleSyncMessage(serverConnectionHandler, (AuthMessage)message);
break;
case CHARACTER_MESSAGE:
this.characterProtocol.handleSyncMessage(serverConnectionHandler, (CharacterMessage)message);
break;
case ENTITY_MESSAGE:
this.entityProtocol.handleSyncMessage(serverConnectionHandler, (EntityMessage)message);
break;
case INVENTORY_MESSAGE:
this.inventoryProtocol.handleSyncMessage(serverConnectionHandler, (InventoryMessage)message);
break;
case LORE_MESSAGE:
this.loreProtocol.handleSyncMessage(serverConnectionHandler, (LoreMessage)message);
break;
case PLAYER_MESSAGE:
this.playerProtocol.handleSyncMessage(serverConnectionHandler, (PlayerMessage)message);
break;
case SERVER_MESSAGE:
this.serverProtocol.handleSyncMessage(serverConnectionHandler, (ServerMessage)message);
break;
case SYNCHRONIZATION_MESSAGE:
this.synchronizationProtocol.handleSyncMessage(serverConnectionHandler, (SynchronizationMessage)message);
break;
case TERRAIN_MESSAGE:
this.terrainProtocol.handleSyncMessage(serverConnectionHandler, (TerrainMessage)message);
break;
}
}
synchronousMessageQueue.clear();
this.synchronousMessageLock.release();
Globals.profiler.endCpuSample();
}
/**
* Print out the network message type, this only prints ping and pong if echoPings is true
*/
void printMessage(NetworkMessage message){
LoggerInterface.loggerNetworking.DEBUG_LOOP("[Server] New message " + message.getType());
}
}

View File

@ -10,7 +10,6 @@ import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.ServerMessage; import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.raw.NetworkParser; import electrosphere.net.parser.net.raw.NetworkParser;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.net.server.protocol.ServerProtocol;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -40,7 +39,13 @@ public class ServerConnectionHandler implements Runnable {
//the streams for the connection //the streams for the connection
// CryptoInputStream inputStream; // CryptoInputStream inputStream;
// CryptoOutputStream outputStream; // CryptoOutputStream outputStream;
/**
* The input stream for packets
*/
InputStream inputStream; InputStream inputStream;
/**
* The output stream for packets
*/
OutputStream outputStream; OutputStream outputStream;
//the network parser for the streams //the network parser for the streams
@ -60,7 +65,7 @@ public class ServerConnectionHandler implements Runnable {
CreatureTemplate currentCreatureTemplate; CreatureTemplate currentCreatureTemplate;
//the server protocol object associated with this player //the server protocol object associated with this player
ServerProtocol serverProtocol; MessageProtocol messageProtocol;
//thresholds for determining when to send pings and when a client has disconnected //thresholds for determining when to send pings and when a client has disconnected
static final long SEND_PING_THRESHOLD = 3000; static final long SEND_PING_THRESHOLD = 3000;
@ -90,6 +95,7 @@ public class ServerConnectionHandler implements Runnable {
this.socket = socket; this.socket = socket;
playerID = getNewPlayerID(); playerID = getNewPlayerID();
LoggerInterface.loggerNetworking.INFO("Player ID: " + playerID); LoggerInterface.loggerNetworking.INFO("Player ID: " + playerID);
this.messageProtocol = new MessageProtocol(this);
} }
/** /**
@ -103,6 +109,7 @@ public class ServerConnectionHandler implements Runnable {
LoggerInterface.loggerNetworking.INFO("Player ID: " + playerID); LoggerInterface.loggerNetworking.INFO("Player ID: " + playerID);
inputStream = serverInputStream; inputStream = serverInputStream;
outputStream = serverOutputStream; outputStream = serverOutputStream;
this.messageProtocol = new MessageProtocol(this);
} }
@Override @Override
@ -110,11 +117,19 @@ public class ServerConnectionHandler implements Runnable {
LoggerInterface.loggerNetworking.INFO("ServerConnectionHandler start"); LoggerInterface.loggerNetworking.INFO("ServerConnectionHandler start");
initialized = false; initialized = false;
///
///
/// SETUP
///
///
//startup is different whether need to set socket streams or received in construction of object (ie if creating local "connection") //startup is different whether need to set socket streams or received in construction of object (ie if creating local "connection")
if(this.local){ if(this.local){
//run if serverconnectionHandler is created by passing in input/output streams //run if serverconnectionHandler is created by passing in input/output streams
networkParser = new NetworkParser(inputStream,outputStream); networkParser = new NetworkParser(inputStream,outputStream);
serverProtocol = new ServerProtocol(this); messageProtocol = new MessageProtocol(this);
} else { } else {
//run if ServerConnectionHandler is created by passing in a socket //run if ServerConnectionHandler is created by passing in a socket
try { try {
@ -143,7 +158,7 @@ public class ServerConnectionHandler implements Runnable {
inputStream = socket.getInputStream(); inputStream = socket.getInputStream();
outputStream = socket.getOutputStream(); outputStream = socket.getOutputStream();
networkParser = new NetworkParser(inputStream,outputStream); networkParser = new NetworkParser(inputStream,outputStream);
serverProtocol = new ServerProtocol(this); messageProtocol = new MessageProtocol(this);
} catch (IOException ex) { } catch (IOException ex) {
ex.printStackTrace(); ex.printStackTrace();
LoggerInterface.loggerNetworking.ERROR("", ex); LoggerInterface.loggerNetworking.ERROR("", ex);
@ -163,8 +178,22 @@ public class ServerConnectionHandler implements Runnable {
networkParser.addOutgoingMessage(pingMessage); networkParser.addOutgoingMessage(pingMessage);
networkParser.addOutgoingMessage(authRequestMessage); networkParser.addOutgoingMessage(authRequestMessage);
///
///
/// MAIN LOOP
///
///
initialized = true; initialized = true;
while(Main.isRunning()){ while(Main.isRunning()){
//
// Main Loop
//
//parse messages both incoming and outgoing //parse messages both incoming and outgoing
try { try {
parseMessages(); parseMessages();
@ -175,6 +204,10 @@ public class ServerConnectionHandler implements Runnable {
socketException = true; socketException = true;
LoggerInterface.loggerNetworking.DEBUG(e.getLocalizedMessage()); LoggerInterface.loggerNetworking.DEBUG(e.getLocalizedMessage());
} }
//
// Pings
//
//ping logic //ping logic
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
@ -185,6 +218,10 @@ public class ServerConnectionHandler implements Runnable {
lastPongTime = lastPingTime; lastPongTime = lastPingTime;
} }
} }
//
// Disconnections
//
//check if we meet disconnection criteria //check if we meet disconnection criteria
//has it been too long since the last ping? //has it been too long since the last ping?
//have we had a socket exception? //have we had a socket exception?
@ -204,9 +241,16 @@ public class ServerConnectionHandler implements Runnable {
* @throws SocketException * @throws SocketException
*/ */
void parseMessages() throws SocketException { void parseMessages() throws SocketException {
//
//Read in messages
//
//attempt poll incoming messages //attempt poll incoming messages
networkParser.readMessagesIn(); networkParser.readMessagesIn();
//
//Net monitor (debug)
//
//net monitor //net monitor
if(Globals.netMonitor != null){ if(Globals.netMonitor != null){
//incoming //incoming
@ -217,18 +261,19 @@ public class ServerConnectionHandler implements Runnable {
} }
} }
//
//Parse messages
//
//ponder incoming messages //ponder incoming messages
while(networkParser.hasIncomingMessaage()){ while(networkParser.hasIncomingMessaage()){
NetworkMessage message = networkParser.popIncomingMessage(); NetworkMessage message = networkParser.popIncomingMessage();
NetworkMessage bouncedMessage = serverProtocol.handleAsyncMessage(message); this.messageProtocol.handleAsyncMessage(message);
//if the message bounces back from the async handle function, means we need to handle synchronously
if(bouncedMessage != null){
this.synchronousMessageLock.acquireUninterruptibly();
this.synchronousMessageQueue.add(bouncedMessage);
this.synchronousMessageLock.release();
}
} }
//
//Net monitor (debug)
//
if(Globals.netMonitor != null){ if(Globals.netMonitor != null){
//outgoing //outgoing
netMonitorCache.clear(); netMonitorCache.clear();
@ -238,6 +283,9 @@ public class ServerConnectionHandler implements Runnable {
} }
} }
//
//Send out messages
//
//push outgoing message //push outgoing message
networkParser.pushMessagesOut(); networkParser.pushMessagesOut();
try { try {
@ -252,12 +300,7 @@ public class ServerConnectionHandler implements Runnable {
* Handles synchronous packets in the queue * Handles synchronous packets in the queue
*/ */
public void handleSynchronousPacketQueue(){ public void handleSynchronousPacketQueue(){
synchronousMessageLock.acquireUninterruptibly(); this.messageProtocol.handleSyncMessages();
for(NetworkMessage message : synchronousMessageQueue){
this.serverProtocol.handleSynchronousMessage(message);
}
synchronousMessageQueue.clear();
synchronousMessageLock.release();
} }
public void setPlayerId(int id){ public void setPlayerId(int id){

View File

@ -5,10 +5,15 @@ import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.PlayerMessage; 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;
public class AuthProtocol { /**
* The server protocol for authorization packets
*/
public class AuthProtocol implements ServerProtocolTemplate<AuthMessage> {
protected static void handleAuthenticationMessage(ServerConnectionHandler connectionHandler, AuthMessage message){ @Override
public AuthMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, AuthMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case AUTHDETAILS: case AUTHDETAILS:
//auth check //auth check
@ -37,20 +42,17 @@ public class AuthProtocol {
//silently drop //silently drop
break; break;
} }
return null;
} }
/** @Override
* Handles the network message from the context of the main server simulation thread public void handleSyncMessage(ServerConnectionHandler connectionHandler, AuthMessage message) {
* @param connectionHandler The connection handler
* @param message The network message
*/
protected static void handleSynchronousAuthMessage(ServerConnectionHandler connectionHandler, AuthMessage message){
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case AUTHDETAILS: case AUTHDETAILS:
case AUTHFAILURE:
case AUTHREQUEST: case AUTHREQUEST:
case AUTHSUCCESS: case AUTHSUCCESS:
//silently ignore case AUTHFAILURE:
//silently drop
break; break;
} }
} }

View File

@ -8,13 +8,23 @@ import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.PlayerMessage; import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.server.character.PlayerCharacterCreation; import electrosphere.server.character.PlayerCharacterCreation;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.util.Utilities; import electrosphere.util.Utilities;
public class CharacterProtocol { /**
* The server protocol for handling character messages
*/
public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessage> {
protected static void handleCharacterMessage(ServerConnectionHandler connectionHandler, CharacterMessage message){ @Override
public CharacterMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, CharacterMessage message) {
return message;
}
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, CharacterMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case REQUESTCHARACTERLIST: case REQUESTCHARACTERLIST:
//TODO //TODO
@ -40,25 +50,6 @@ public class CharacterProtocol {
} }
} }
/**
* Handles the network message from the context of the main server simulation thread
* @param connectionHandler The connection handler
* @param message The network message
*/
protected static void handleSynchronousCharacterMessage(ServerConnectionHandler connectionHandler, CharacterMessage message){
switch(message.getMessageSubtype()){
case REQUESTCHARACTERLIST:
case REQUESTCREATECHARACTER:
case REQUESTSPAWNCHARACTER:
case RESPONSECHARACTERLIST:
case RESPONSECREATECHARACTERFAILURE:
case RESPONSECREATECHARACTERSUCCESS:
case RESPONSESPAWNCHARACTER:
//silently ignore
break;
}
}
/** /**
* Spawns the player's entity * Spawns the player's entity
* @param connectionHandler The connection handler for the player * @param connectionHandler The connection handler for the player

View File

@ -10,11 +10,21 @@ import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
public class EntityProtocol { /**
* The server protocol for handling entity messages
*/
public class EntityProtocol implements ServerProtocolTemplate<EntityMessage> {
protected static void handleEntityMessage(ServerConnectionHandler connectionHandler, EntityMessage message){ @Override
public EntityMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, EntityMessage message) {
return message;
}
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, EntityMessage message) {
//error check //error check
if(Globals.clientScene != null && Globals.clientScene.getEntityFromId(message.getentityID()) != null){ if(Globals.clientScene != null && Globals.clientScene.getEntityFromId(message.getentityID()) != null){
LoggerInterface.loggerNetworking.WARNING("Server received packet for entity that is in client scene wrapper!"); LoggerInterface.loggerNetworking.WARNING("Server received packet for entity that is in client scene wrapper!");
@ -62,29 +72,4 @@ public class EntityProtocol {
} }
} }
/**
* Handles the network message from the context of the main server simulation thread
* @param connectionHandler The connection handler
* @param message The network message
*/
protected static void handleSynchronousEntityMessage(ServerConnectionHandler connectionHandler, EntityMessage message){
switch(message.getMessageSubtype()){
case MOVEUPDATE:
case ATTACKUPDATE:
case STARTATTACK:
case UPDATEENTITYVIEWDIR:
case KILL:
case SPAWNCREATURE:
case DESTROY:
case CREATE:
case ATTACHENTITYTOENTITY:
case SETPROPERTY:
case SPAWNFOLIAGESEED:
case SPAWNITEM:
case SPAWNOBJECT:
//silently ignore
break;
}
}
} }

View File

@ -5,13 +5,14 @@ import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.InventoryMessage; import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.player.PlayerActions; import electrosphere.server.player.PlayerActions;
/** /**
* Server protocol for dealing with inventory messages * Server protocol for dealing with inventory messages
*/ */
public class InventoryProtocol { public class InventoryProtocol implements ServerProtocolTemplate<InventoryMessage> {
//the entity's equip inventory //the entity's equip inventory
@ -19,13 +20,13 @@ public class InventoryProtocol {
//the natural inventory of the entity //the natural inventory of the entity
public static final int INVENTORY_TYPE_NATURAL = 1; public static final int INVENTORY_TYPE_NATURAL = 1;
/** @Override
* Handles asynchronous inventory messages public InventoryMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, InventoryMessage message) {
* @param connectionHandler The connection handler return message;
* @param message The message to handle }
* @return The network message if it should be handled synchronously, otherwise null
*/ @Override
protected static InventoryMessage handleAsyncInventoryMessage(ServerConnectionHandler connectionHandler, InventoryMessage message){ public void handleSyncMessage(ServerConnectionHandler connectionHandler, InventoryMessage message) {
Entity target; Entity target;
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case ADDITEMTOINVENTORY: case ADDITEMTOINVENTORY:
@ -56,33 +57,9 @@ public class InventoryProtocol {
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message); InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
} }
break; break;
case CLIENTREQUESTPERFORMITEMACTION: {
//perform some action on the server based on what the client has equipped
return message;
}
case SERVERCOMMANDUNEQUIPITEM:
case SERVERCOMMANDMOVEITEMCONTAINER:
case SERVERCOMMANDEQUIPITEM:
//silently ignore
break;
}
return null;
}
/**
* Handles the network message from the context of the main server simulation thread
* @param connectionHandler The connection handler
* @param message The network message
*/
protected static void handleSynchronousInventoryMessage(ServerConnectionHandler connectionHandler, InventoryMessage message){
switch(message.getMessageSubtype()){
case CLIENTREQUESTPERFORMITEMACTION: { case CLIENTREQUESTPERFORMITEMACTION: {
PlayerActions.attemptPlayerAction(connectionHandler, message); PlayerActions.attemptPlayerAction(connectionHandler, message);
} break; }
case ADDITEMTOINVENTORY:
case REMOVEITEMFROMINVENTORY:
case CLIENTREQUESTEQUIPITEM:
case CLIENTREQUESTUNEQUIPITEM:
case SERVERCOMMANDUNEQUIPITEM: case SERVERCOMMANDUNEQUIPITEM:
case SERVERCOMMANDMOVEITEMCONTAINER: case SERVERCOMMANDMOVEITEMCONTAINER:
case SERVERCOMMANDEQUIPITEM: case SERVERCOMMANDEQUIPITEM:

View File

@ -5,30 +5,31 @@ import java.util.List;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.LoreMessage; import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.util.Utilities; import electrosphere.util.Utilities;
public class LoreProtocol { /**
* The server protocol for handling lore messages
*/
public class LoreProtocol implements ServerProtocolTemplate<LoreMessage> {
protected static void handleLoreMessage(ServerConnectionHandler connectionHandler, LoreMessage message){ @Override
public LoreMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, LoreMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case REQUESTRACES: case REQUESTRACES: {
List<String> playableRaces = Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces(); List<String> playableRaces = Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces();
String returnData = Utilities.stringify(playableRaces); String returnData = Utilities.stringify(playableRaces);
connectionHandler.addMessagetoOutgoingQueue(LoreMessage.constructResponseRacesMessage(returnData)); connectionHandler.addMessagetoOutgoingQueue(LoreMessage.constructResponseRacesMessage(returnData));
break; return null;
}
case RESPONSERACES: case RESPONSERACES:
//silently ignore return message;
break;
} }
return null;
} }
/** @Override
* Handles the network message from the context of the main server simulation thread public void handleSyncMessage(ServerConnectionHandler connectionHandler, LoreMessage message) {
* @param connectionHandler The connection handler
* @param message The network message
*/
protected static void handleSynchronousLoreMessage(ServerConnectionHandler connectionHandler, LoreMessage message){
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case REQUESTRACES: case REQUESTRACES:
case RESPONSERACES: case RESPONSERACES:

View File

@ -2,18 +2,27 @@ package electrosphere.net.server.protocol;
import electrosphere.net.parser.net.message.PlayerMessage; import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
/** /**
* Player protocol handling * Player protocol handling
*/ */
public class PlayerProtocol { public class PlayerProtocol implements ServerProtocolTemplate<PlayerMessage> {
/**
* Handles a player network message @Override
* @param connectionHandler The connection handler public PlayerMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, PlayerMessage message) {
* @param message The player message switch(message.getMessageSubtype()){
*/ case SETINITIALDISCRETEPOSITION:
protected static void handlePlayerMessage(ServerConnectionHandler connectionHandler, PlayerMessage message){ case SET_ID:
//silently ignore
break;
}
return null;
}
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, PlayerMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case SETINITIALDISCRETEPOSITION: case SETINITIALDISCRETEPOSITION:
case SET_ID: case SET_ID:
@ -22,18 +31,4 @@ public class PlayerProtocol {
} }
} }
/**
* Handles the network message from the context of the main server simulation thread
* @param connectionHandler The connection handler
* @param message The network message
*/
protected static void handleSynchronousPlayerMessage(ServerConnectionHandler connectionHandler, PlayerMessage message){
switch(message.getMessageSubtype()){
case SETINITIALDISCRETEPOSITION:
case SET_ID:
//silently ignore
break;
}
}
} }

View File

@ -1,123 +1,20 @@
package electrosphere.net.server.protocol; package electrosphere.net.server.protocol;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.ServerMessage; import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.parser.net.message.NetworkMessage.MessageType;
import electrosphere.net.parser.net.message.ServerMessage.ServerMessageType;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
/** /**
* The server's protocol for handling a message * The server's protocol for handling a message
*/ */
public class ServerProtocol { 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;
//if set to true, will log ping messages
boolean echoPings = false;
/**
* Constructor
* @param connectionHandler the associated connection handler
*/
public ServerProtocol(ServerConnectionHandler connectionHandler){
this.connectionHandler = connectionHandler;
}
/**
* Handles a given network message
* @param message The network message to handle
* @return Returns the message if it should be synchronously handled with the main server thread instead
*/
public NetworkMessage handleAsyncMessage(NetworkMessage message){
//print out message
printMessage(message);
//actually handle message
switch(message.getType()){
case ENTITY_MESSAGE: {
EntityProtocol.handleEntityMessage(connectionHandler, (EntityMessage)message);
} break;
case TERRAIN_MESSAGE: {
TerrainProtocol.handleTerrainMessage(connectionHandler, (TerrainMessage)message);
} break;
case PLAYER_MESSAGE: {
PlayerProtocol.handlePlayerMessage(connectionHandler, (PlayerMessage)message);
} break;
case AUTH_MESSAGE: {
AuthProtocol.handleAuthenticationMessage(connectionHandler, (AuthMessage)message);
} break;
case SERVER_MESSAGE: {
handleServerMessage((ServerMessage)message);
} break;
case CHARACTER_MESSAGE: {
CharacterProtocol.handleCharacterMessage(connectionHandler, (CharacterMessage)message);
} break;
case LORE_MESSAGE: {
LoreProtocol.handleLoreMessage(connectionHandler, (LoreMessage)message);
} break;
case INVENTORY_MESSAGE: {
return InventoryProtocol.handleAsyncInventoryMessage(connectionHandler, (InventoryMessage)message);
}
case SYNCHRONIZATION_MESSAGE:
//silently ignore sync messages from client
break;
}
return null;
}
/**
* Synchronously handles a network message
* @param message The network message
*/
public void handleSynchronousMessage(NetworkMessage message){
//print out message
printMessage(message);
//actually handle message
switch(message.getType()){
case ENTITY_MESSAGE: {
EntityProtocol.handleSynchronousEntityMessage(connectionHandler, (EntityMessage)message);
} break;
case TERRAIN_MESSAGE: {
TerrainProtocol.handleSynchronousServerMessage(connectionHandler, (TerrainMessage)message);
} break;
case PLAYER_MESSAGE: {
PlayerProtocol.handleSynchronousPlayerMessage(connectionHandler, (PlayerMessage)message);
} break;
case AUTH_MESSAGE: {
AuthProtocol.handleSynchronousAuthMessage(connectionHandler, (AuthMessage)message);
} break;
case SERVER_MESSAGE: {
ServerProtocol.handleSynchronousServerMessage(connectionHandler, (ServerMessage)message);
} break;
case CHARACTER_MESSAGE: {
CharacterProtocol.handleSynchronousCharacterMessage(connectionHandler, (CharacterMessage)message);
} break;
case LORE_MESSAGE: {
LoreProtocol.handleSynchronousLoreMessage(connectionHandler, (LoreMessage)message);
} break;
case INVENTORY_MESSAGE: {
InventoryProtocol.handleSynchronousInventoryMessage(connectionHandler, (InventoryMessage)message);
} break;
case SYNCHRONIZATION_MESSAGE:
//silently ignore sync messages from client
break;
}
}
/** @Override
* Handles a server-type network message public ServerMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
* @param message The server message
*/
void handleServerMessage(ServerMessage message){
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case PING: case PING:
connectionHandler.addMessagetoOutgoingQueue(ServerMessage.constructPongMessage()); connectionHandler.addMessagetoOutgoingQueue(ServerMessage.constructPongMessage());
@ -126,14 +23,11 @@ public class ServerProtocol {
connectionHandler.markReceivedPongMessage(); connectionHandler.markReceivedPongMessage();
break; break;
} }
return null;
} }
/** @Override
* Handles the network message from the context of the main server simulation thread public void handleSyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
* @param connectionHandler The connection handler
* @param message The network message
*/
protected static void handleSynchronousServerMessage(ServerConnectionHandler connectionHandler, ServerMessage message){
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case PING: case PING:
case PONG: case PONG:
@ -142,24 +36,4 @@ public class ServerProtocol {
} }
} }
/**
* Print out the network message type, this only prints ping and pong if echoPings is true
*/
void printMessage(NetworkMessage message){
//only print ping and pong if echoPings is true
if(message.getType() == MessageType.SERVER_MESSAGE){
if((((ServerMessage)message).getMessageSubtype()) == ServerMessageType.PING ||
(((ServerMessage)message).getMessageSubtype()) == ServerMessageType.PONG
){
if(this.echoPings == true){
LoggerInterface.loggerNetworking.DEBUG_LOOP("[Server] New message " + message.getType());
}
} else {
LoggerInterface.loggerNetworking.DEBUG_LOOP("[Server] New message " + message.getType());
}
} else {
LoggerInterface.loggerNetworking.DEBUG_LOOP("[Server] New message " + message.getType());
}
}
} }

View File

@ -0,0 +1,37 @@
package electrosphere.net.server.protocol;
import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
/**
* Server protocol for synchronization packet handling
*/
public class SynchronizationProtocol implements ServerProtocolTemplate<SynchronizationMessage> {
@Override
public SynchronizationMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, SynchronizationMessage message) {
switch(message.getMessageSubtype()){
case UPDATECLIENTSTATE:
case UPDATECLIENTSTRINGSTATE:
case ATTACHTREE:
case DETATCHTREE:
case LOADSCENE:
break;
}
return null;
}
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, SynchronizationMessage message) {
switch(message.getMessageSubtype()){
case UPDATECLIENTSTATE:
case UPDATECLIENTSTRINGSTATE:
case ATTACHTREE:
case DETATCHTREE:
case LOADSCENE:
break;
}
}
}

View File

@ -10,6 +10,7 @@ import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
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.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.fluid.manager.ServerFluidChunk; import electrosphere.server.fluid.manager.ServerFluidChunk;
import electrosphere.server.terrain.editing.TerrainEditing; import electrosphere.server.terrain.editing.TerrainEditing;
@ -18,14 +19,15 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
/** /**
* Server handling for terrain network messages * Server handling for terrain network messages
*/ */
public class TerrainProtocol { public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
/** @Override
* Handles a terrain message public TerrainMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, TerrainMessage message) {
* @param connectionHandler The connection handler return message;
* @param message The terrain message }
*/
protected static void handleTerrainMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){ @Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, TerrainMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case REQUESTMETADATA: case REQUESTMETADATA:
sendWorldMetadata(connectionHandler); sendWorldMetadata(connectionHandler);
@ -53,34 +55,13 @@ public class TerrainProtocol {
case UPDATEVOXEL: case UPDATEVOXEL:
case SENDCHUNKDATA: case SENDCHUNKDATA:
case SENDFLUIDDATA: case SENDFLUIDDATA:
case REQUESTREDUCEDCHUNKDATA:
case SENDREDUCEDCHUNKDATA:
//silently ignore //silently ignore
break; break;
} }
} }
/**
* Handles the network message from the context of the main server simulation thread
* @param connectionHandler The connection handler
* @param message The network message
*/
protected static void handleSynchronousServerMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){
switch(message.getMessageSubtype()){
case REQUESTCHUNKDATA:
case REQUESTEDITVOXEL:
case REQUESTFLUIDDATA:
case REQUESTMETADATA:
case REQUESTUSETERRAINPALETTE:
case RESPONSEMETADATA:
case UPDATEFLUIDDATA:
case SPAWNPOSITION:
case UPDATEVOXEL:
case SENDCHUNKDATA:
case SENDFLUIDDATA:
//silently ignore
break;
}
}
/** /**
* Sends a subchunk to the client * Sends a subchunk to the client
* @param connectionHandler The connection handler * @param connectionHandler The connection handler

View File

@ -73,13 +73,13 @@ public class ClientSynchronizationManager {
updateEntityState(targetEntity,bTreeId,message); updateEntityState(targetEntity,bTreeId,message);
} break; } break;
case ATTACHTREE:{ case ATTACHTREE:{
int bTreeId = message.getbTreeId(); // int bTreeId = message.getbTreeId();
int bTreeValue = message.getbTreeValue(); // int bTreeValue = message.getbTreeValue();
int entityId = message.getentityId(); // int entityId = message.getentityId();
} break; } break;
case DETATCHTREE:{ case DETATCHTREE:{
int bTreeId = message.getbTreeId(); // int bTreeId = message.getbTreeId();
int entityId = message.getentityId(); // int entityId = message.getentityId();
} break; } break;
case LOADSCENE: { case LOADSCENE: {
} break; } break;

View File

@ -0,0 +1,20 @@
package electrosphere.net.template;
/**
* A client protocol interface
*/
public interface ClientProtocolTemplate<T> {
/**
* Handles a message asynchronously
* @param message The message
*/
public T handleAsyncMessage(T message);
/**
* Handles a message synchronously
* @param message The message
*/
public void handleSyncMessage(T message);
}

View File

@ -0,0 +1,24 @@
package electrosphere.net.template;
import electrosphere.net.server.ServerConnectionHandler;
/**
* A server protocol interface
*/
public interface ServerProtocolTemplate<T> {
/**
* Handles a message asynchronously
* @param connectionHandler The connection to the server
* @param message The message
*/
public T handleAsyncMessage(ServerConnectionHandler connectionHandler, T message);
/**
* Handles a message synchronously
* @param connectionHandler The connection to the server
* @param message The message
*/
public void handleSyncMessage(ServerConnectionHandler connectionHandler, T message);
}

View File

@ -45,10 +45,6 @@ public class PlayerCharacterCreation {
realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.z) realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.z)
)); ));
realm.getDataCellManager().addPlayerToRealm(playerObject); realm.getDataCellManager().addPlayerToRealm(playerObject);
//parse network messages on client if running
if(playerObject == Globals.clientPlayer){
Globals.clientConnection.parseMessages();
}
} }
/** /**