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)
Option to load all cells on init scene file
Insidious Entity protocol bugfix on server
Refactor network protocols to enforce async/sync split
# TODO

View File

@ -273,7 +273,7 @@ public class Main {
if(Globals.clientConnection != null){
Globals.profiler.beginCpuSample("Client networking");
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin parse client messages");
Globals.clientConnection.parseMessages();
Globals.clientConnection.parseMessagesSynchronous();
Globals.profiler.endCpuSample();
}
@ -369,7 +369,6 @@ public class Main {
///
/// S H U T D O W N C H E C K
///
if(Globals.HEADLESS){
if(Globals.ENGINE_SHUTDOWN_FLAG){
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");
if(Globals.timekeeper.getMostRecentRawFrametime() < targetFramePeriod){
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");
Globals.profiler.endCpuSample();

View File

@ -3,7 +3,6 @@ package electrosphere.net.client;
import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.client.protocol.ClientProtocol;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.message.NetworkMessage.MessageType;
@ -13,21 +12,34 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Client networking thread
*/
public class ClientNetworking implements Runnable{
public class ClientNetworking implements Runnable {
/**
* The server's address
*/
String address;
/**
* The port on the server
*/
int port;
/**
* Controls whether the connection is formed locally (with lists) or not (with sockets)
*/
boolean local = false;
/**
* The socket for the connection
*/
public Socket socket;
// CryptoInputStream inputStream;
// CryptoOutputStream outputStream;
InputStream inputStream;
@ -35,8 +47,14 @@ public class ClientNetworking implements Runnable{
boolean initialized;
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;
//set to true to also get ping and pong messages in debug logging
@ -52,11 +70,21 @@ public class ClientNetworking implements Runnable{
//debugging stuff
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){
this.address = address;
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){
this.local = true;
this.inputStream = clientInputStream;
@ -83,7 +111,14 @@ public class ClientNetworking implements Runnable{
// }
//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) {
//attempt connection
@ -123,6 +158,14 @@ public class ClientNetworking implements Runnable{
//create parser
parser = new NetworkParser(inputStream,outputStream);
///
///
/// MAIN LOOP
///
///
//start parsing messages
initialized = true;
while(Main.isRunning()){
@ -130,6 +173,8 @@ public class ClientNetworking implements Runnable{
parser.readMessagesIn();
//outgoing messages
parser.pushMessagesOut();
//parses messages asynchronously
this.parseMessagesAsynchronously();
//ping logic
long currentTime = System.currentTimeMillis();
@ -158,11 +203,13 @@ public class ClientNetworking implements Runnable{
}
}
static final int MAX_MESSAGES_PARSED = 1000;
public void parseMessages(){
/**
* Parses messages asynchronously
*/
public void parseMessagesAsynchronously(){
if(initialized){
while(parser.hasIncomingMessaage()){
NetworkMessage message = parser.popIncomingMessage();
@ -174,11 +221,19 @@ public class ClientNetworking implements Runnable{
printMessage(message);
//do something
Globals.profiler.beginCpuSample("ClientProtocol.handleMessage");
clientProtocol.handleMessage(message);
this.messageProtocol.handleAsyncMessage(message);
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
@ -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){
//net monitor stuff
if(Globals.netMonitor != null){
@ -210,8 +268,12 @@ public class ClientNetworking implements Runnable{
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(){

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.net.parser.net.message.AuthMessage;
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()){
case AUTHREQUEST:
//Try login
@ -31,6 +36,18 @@ public class AuthProtocol {
//silently ignore
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.net.parser.net.message.CharacterMessage;
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()){
case RESPONSECREATECHARACTERSUCCESS:
//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.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.EntityMessage.EntityMessageType;
import electrosphere.net.template.ClientProtocolTemplate;
import electrosphere.util.Utilities;
/**
* 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
static List<EntityMessageType> spawnMessageTypes = Arrays.asList(new EntityMessageType[]{
@ -37,12 +38,14 @@ public class EntityProtocol {
EntityMessageType.SPAWNITEM,
EntityMessageType.SPAWNOBJECT,
});
/**
* Handles a single clientbound entity message
* @param message The message to handle
*/
protected static void handleEntityMessage(EntityMessage message){
@Override
public EntityMessage handleAsyncMessage(EntityMessage message) {
return message;
}
@Override
public void handleSyncMessage(EntityMessage message) {
Globals.profiler.beginCpuSample("EntityProtocol.handleEntityMessage");
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.logger.LoggerInterface;
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()){
case ADDITEMTOINVENTORY:
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.net.parser.net.message.LoreMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class LoreProtocol {
protected static void handleLoreMessage(LoreMessage message){
public class LoreProtocol implements ClientProtocolTemplate<LoreMessage> {
@Override
public LoreMessage handleAsyncMessage(LoreMessage message) {
return message;
}
@Override
public void handleSyncMessage(LoreMessage message) {
switch(message.getMessageSubtype()){
case RESPONSERACES:
//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.net.parser.net.message.PlayerMessage;
import electrosphere.net.server.player.Player;
import electrosphere.net.template.ClientProtocolTemplate;
public class PlayerProtocol {
protected static void handlePlayerMessage(PlayerMessage message){
/**
* The client protocol for handling player messages
*/
public class PlayerProtocol implements ClientProtocolTemplate<PlayerMessage> {
@Override
public PlayerMessage handleAsyncMessage(PlayerMessage message) {
return message;
}
@Override
public void handleSyncMessage(PlayerMessage message) {
Globals.profiler.beginCpuSample("PlayerProtocol.handlePlayerMessage");
switch(message.getMessageSubtype()){
case SET_ID:

View File

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

View File

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

View File

@ -9,10 +9,20 @@ import electrosphere.collision.CollisionWorldData;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.template.ClientProtocolTemplate;
public class TerrainProtocol {
protected static void handleTerrainMessage(TerrainMessage message){
/**
* The client protocol for handling terrain messages
*/
public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
@Override
public TerrainMessage handleAsyncMessage(TerrainMessage message) {
return message;
}
@Override
public void handleSyncMessage(TerrainMessage message) {
Globals.profiler.beginCpuSample("TerrainProtocol.handleTerrainMessage");
switch(message.getMessageSubtype()){
case RESPONSEMETADATA:
@ -25,7 +35,7 @@ public class TerrainProtocol {
message.getworldSizeDiscrete()
);
Globals.clientSceneWrapper.getCollisionEngine().setCollisionWorldData(new CollisionWorldData(Globals.clientWorldData));
Globals.clientConnection.getClientProtocol().setHasReceivedWorld(true);
Globals.clientConnection.getMessageProtocol().setHasReceivedWorld(true);
break;
case SPAWNPOSITION:
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){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList();
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
int userSize = 0;
if(currentStreamLength < 6){
return false;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -451,7 +451,7 @@ public class TerrainMessage extends NetworkMessage {
public static boolean canParsesendChunkDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList();
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){
return false;
}
@ -519,7 +519,7 @@ public class TerrainMessage extends NetworkMessage {
public static boolean canParseSendReducedChunkDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList();
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){
return false;
}
@ -590,7 +590,7 @@ public class TerrainMessage extends NetworkMessage {
public static boolean canParsesendFluidDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList();
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){
return false;
}
@ -638,7 +638,7 @@ public class TerrainMessage extends NetworkMessage {
public static boolean canParseupdateFluidDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList();
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){
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.raw.NetworkParser;
import electrosphere.net.server.player.Player;
import electrosphere.net.server.protocol.ServerProtocol;
import java.io.IOException;
import java.io.InputStream;
@ -40,7 +39,13 @@ public class ServerConnectionHandler implements Runnable {
//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
@ -60,7 +65,7 @@ public class ServerConnectionHandler implements Runnable {
CreatureTemplate currentCreatureTemplate;
//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
static final long SEND_PING_THRESHOLD = 3000;
@ -90,6 +95,7 @@ public class ServerConnectionHandler implements Runnable {
this.socket = socket;
playerID = getNewPlayerID();
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);
inputStream = serverInputStream;
outputStream = serverOutputStream;
this.messageProtocol = new MessageProtocol(this);
}
@Override
@ -110,11 +117,19 @@ public class ServerConnectionHandler implements Runnable {
LoggerInterface.loggerNetworking.INFO("ServerConnectionHandler start");
initialized = false;
///
///
/// SETUP
///
///
//startup is different whether need to set socket streams or received in construction of object (ie if creating local "connection")
if(this.local){
//run if serverconnectionHandler is created by passing in input/output streams
networkParser = new NetworkParser(inputStream,outputStream);
serverProtocol = new ServerProtocol(this);
messageProtocol = new MessageProtocol(this);
} else {
//run if ServerConnectionHandler is created by passing in a socket
try {
@ -143,7 +158,7 @@ public class ServerConnectionHandler implements Runnable {
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
networkParser = new NetworkParser(inputStream,outputStream);
serverProtocol = new ServerProtocol(this);
messageProtocol = new MessageProtocol(this);
} catch (IOException ex) {
ex.printStackTrace();
LoggerInterface.loggerNetworking.ERROR("", ex);
@ -163,8 +178,22 @@ public class ServerConnectionHandler implements Runnable {
networkParser.addOutgoingMessage(pingMessage);
networkParser.addOutgoingMessage(authRequestMessage);
///
///
/// MAIN LOOP
///
///
initialized = true;
while(Main.isRunning()){
//
// Main Loop
//
//parse messages both incoming and outgoing
try {
parseMessages();
@ -175,6 +204,10 @@ public class ServerConnectionHandler implements Runnable {
socketException = true;
LoggerInterface.loggerNetworking.DEBUG(e.getLocalizedMessage());
}
//
// Pings
//
//ping logic
long currentTime = System.currentTimeMillis();
//basically if we haven't sent a ping in a while, send one
@ -185,6 +218,10 @@ public class ServerConnectionHandler implements Runnable {
lastPongTime = lastPingTime;
}
}
//
// Disconnections
//
//check if we meet disconnection criteria
//has it been too long since the last ping?
//have we had a socket exception?
@ -204,9 +241,16 @@ public class ServerConnectionHandler implements Runnable {
* @throws SocketException
*/
void parseMessages() throws SocketException {
//
//Read in messages
//
//attempt poll incoming messages
networkParser.readMessagesIn();
//
//Net monitor (debug)
//
//net monitor
if(Globals.netMonitor != null){
//incoming
@ -217,18 +261,19 @@ public class ServerConnectionHandler implements Runnable {
}
}
//
//Parse messages
//
//ponder incoming messages
while(networkParser.hasIncomingMessaage()){
NetworkMessage message = networkParser.popIncomingMessage();
NetworkMessage bouncedMessage = serverProtocol.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();
}
this.messageProtocol.handleAsyncMessage(message);
}
//
//Net monitor (debug)
//
if(Globals.netMonitor != null){
//outgoing
netMonitorCache.clear();
@ -238,6 +283,9 @@ public class ServerConnectionHandler implements Runnable {
}
}
//
//Send out messages
//
//push outgoing message
networkParser.pushMessagesOut();
try {
@ -252,12 +300,7 @@ public class ServerConnectionHandler implements Runnable {
* Handles synchronous packets in the queue
*/
public void handleSynchronousPacketQueue(){
synchronousMessageLock.acquireUninterruptibly();
for(NetworkMessage message : synchronousMessageQueue){
this.serverProtocol.handleSynchronousMessage(message);
}
synchronousMessageQueue.clear();
synchronousMessageLock.release();
this.messageProtocol.handleSyncMessages();
}
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.server.ServerConnectionHandler;
import electrosphere.net.server.player.Player;
import electrosphere.net.template.ServerProtocolTemplate;
public class AuthProtocol {
protected static void handleAuthenticationMessage(ServerConnectionHandler connectionHandler, AuthMessage message){
/**
* The server protocol for authorization packets
*/
public class AuthProtocol implements ServerProtocolTemplate<AuthMessage> {
@Override
public AuthMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, AuthMessage message) {
switch(message.getMessageSubtype()){
case AUTHDETAILS:
//auth check
@ -37,20 +42,17 @@ public class AuthProtocol {
//silently drop
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 handleSynchronousAuthMessage(ServerConnectionHandler connectionHandler, AuthMessage message){
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, AuthMessage message) {
switch(message.getMessageSubtype()){
case AUTHDETAILS:
case AUTHFAILURE:
case AUTHREQUEST:
case AUTHSUCCESS:
//silently ignore
case AUTHFAILURE:
//silently drop
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.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.server.character.PlayerCharacterCreation;
import electrosphere.server.datacell.Realm;
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()){
case REQUESTCHARACTERLIST:
//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
* @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.net.parser.net.message.EntityMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
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
if(Globals.clientScene != null && Globals.clientScene.getEntityFromId(message.getentityID()) != null){
LoggerInterface.loggerNetworking.WARNING("Server received packet for entity that is in client scene wrapper!");
@ -61,30 +71,5 @@ public class EntityProtocol {
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 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,27 +5,28 @@ import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.player.PlayerActions;
/**
* Server protocol for dealing with inventory messages
*/
public class InventoryProtocol {
public class InventoryProtocol implements ServerProtocolTemplate<InventoryMessage> {
//the entity's equip inventory
public static final int INVENTORY_TYPE_EQUIP = 0;
//the natural inventory of the entity
public static final int INVENTORY_TYPE_NATURAL = 1;
/**
* Handles asynchronous inventory messages
* @param connectionHandler The connection handler
* @param message The message to handle
* @return The network message if it should be handled synchronously, otherwise null
*/
protected static InventoryMessage handleAsyncInventoryMessage(ServerConnectionHandler connectionHandler, InventoryMessage message){
@Override
public InventoryMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, InventoryMessage message) {
return message;
}
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, InventoryMessage message) {
Entity target;
switch(message.getMessageSubtype()){
case ADDITEMTOINVENTORY:
@ -56,33 +57,9 @@ public class InventoryProtocol {
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
}
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: {
PlayerActions.attemptPlayerAction(connectionHandler, message);
} break;
case ADDITEMTOINVENTORY:
case REMOVEITEMFROMINVENTORY:
case CLIENTREQUESTEQUIPITEM:
case CLIENTREQUESTUNEQUIPITEM:
}
case SERVERCOMMANDUNEQUIPITEM:
case SERVERCOMMANDMOVEITEMCONTAINER:
case SERVERCOMMANDEQUIPITEM:

View File

@ -5,30 +5,31 @@ import java.util.List;
import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.LoreMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
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()){
case REQUESTRACES:
case REQUESTRACES: {
List<String> playableRaces = Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces();
String returnData = Utilities.stringify(playableRaces);
connectionHandler.addMessagetoOutgoingQueue(LoreMessage.constructResponseRacesMessage(returnData));
break;
return null;
}
case RESPONSERACES:
//silently ignore
break;
return message;
}
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 handleSynchronousLoreMessage(ServerConnectionHandler connectionHandler, LoreMessage message){
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, LoreMessage message) {
switch(message.getMessageSubtype()){
case REQUESTRACES:
case RESPONSERACES:

View File

@ -2,18 +2,27 @@ package electrosphere.net.server.protocol;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate;
/**
* Player protocol handling
*/
public class PlayerProtocol {
public class PlayerProtocol implements ServerProtocolTemplate<PlayerMessage> {
/**
* Handles a player network message
* @param connectionHandler The connection handler
* @param message The player message
*/
protected static void handlePlayerMessage(ServerConnectionHandler connectionHandler, PlayerMessage message){
@Override
public PlayerMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, PlayerMessage message) {
switch(message.getMessageSubtype()){
case SETINITIALDISCRETEPOSITION:
case SET_ID:
//silently ignore
break;
}
return null;
}
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, PlayerMessage message) {
switch(message.getMessageSubtype()){
case SETINITIALDISCRETEPOSITION:
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;
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.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.template.ServerProtocolTemplate;
/**
* 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
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;
}
}
/**
* Handles a server-type network message
* @param message The server message
*/
void handleServerMessage(ServerMessage message){
@Override
public ServerMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
switch(message.getMessageSubtype()){
case PING:
connectionHandler.addMessagetoOutgoingQueue(ServerMessage.constructPongMessage());
@ -126,14 +23,11 @@ public class ServerProtocol {
connectionHandler.markReceivedPongMessage();
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 handleSynchronousServerMessage(ServerConnectionHandler connectionHandler, ServerMessage message){
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, ServerMessage message) {
switch(message.getMessageSubtype()){
case PING:
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.server.ServerConnectionHandler;
import electrosphere.net.server.player.Player;
import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.server.datacell.Realm;
import electrosphere.server.fluid.manager.ServerFluidChunk;
import electrosphere.server.terrain.editing.TerrainEditing;
@ -18,14 +19,15 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
/**
* Server handling for terrain network messages
*/
public class TerrainProtocol {
public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
/**
* Handles a terrain message
* @param connectionHandler The connection handler
* @param message The terrain message
*/
protected static void handleTerrainMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){
@Override
public TerrainMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, TerrainMessage message) {
return message;
}
@Override
public void handleSyncMessage(ServerConnectionHandler connectionHandler, TerrainMessage message) {
switch(message.getMessageSubtype()){
case REQUESTMETADATA:
sendWorldMetadata(connectionHandler);
@ -53,34 +55,13 @@ public class TerrainProtocol {
case UPDATEVOXEL:
case SENDCHUNKDATA:
case SENDFLUIDDATA:
case REQUESTREDUCEDCHUNKDATA:
case SENDREDUCEDCHUNKDATA:
//silently ignore
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
* @param connectionHandler The connection handler

View File

@ -73,13 +73,13 @@ public class ClientSynchronizationManager {
updateEntityState(targetEntity,bTreeId,message);
} break;
case ATTACHTREE:{
int bTreeId = message.getbTreeId();
int bTreeValue = message.getbTreeValue();
int entityId = message.getentityId();
// int bTreeId = message.getbTreeId();
// int bTreeValue = message.getbTreeValue();
// int entityId = message.getentityId();
} break;
case DETATCHTREE:{
int bTreeId = message.getbTreeId();
int entityId = message.getentityId();
// int bTreeId = message.getbTreeId();
// int entityId = message.getentityId();
} break;
case LOADSCENE: {
} 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.getDataCellManager().addPlayerToRealm(playerObject);
//parse network messages on client if running
if(playerObject == Globals.clientPlayer){
Globals.clientConnection.parseMessages();
}
}
/**