synchronization full flow initial implementation

This commit is contained in:
austin 2024-02-24 21:38:29 -05:00
parent b7d993ddbb
commit e924511883
17 changed files with 607 additions and 153 deletions

55
net/synchronization.json Normal file
View File

@ -0,0 +1,55 @@
{
"outputPath" : "./src/main/java/electrosphere/net/parser/",
"packageName" : "electrosphere.net.parser",
"categories":[
{
"categoryName" : "Synchronization",
"data" : [
{
"name" : "entityId",
"type" : "FIXED_INT"
},
{
"name" : "bTreeId",
"type" : "FIXED_INT"
},
{
"name" : "fieldId",
"type" : "FIXED_INT"
},
{
"name" : "bTreeValue",
"type" : "FIXED_INT"
}
],
"messageTypes" : [
{
"messageName" : "UpdateClientState",
"data" : [
"entityId",
"bTreeId",
"fieldId",
"bTreeValue"
]
},
{
"messageName" : "AttachTree",
"data" : [
"entityId",
"bTreeId"
]
},
{
"messageName" : "DetatchTree",
"data" : [
"entityId",
"bTreeId"
]
}
]
}
]
}

View File

@ -20,6 +20,8 @@ public class ClientFunctions {
if(Globals.playerEntity != null){
oldPlayerCharacterPosition = new Vector3d(EntityUtils.getPosition(Globals.playerEntity));
}
//process all server synchronization messages
Globals.clientSynchronizationManager.processMessages();
}
public static void runClientFunctions(){

View File

@ -43,6 +43,7 @@ import electrosphere.net.monitor.NetMonitor;
import electrosphere.net.server.Server;
import electrosphere.net.server.player.Player;
import electrosphere.net.server.player.PlayerManager;
import electrosphere.net.synchronization.ClientSynchronizationManager;
import electrosphere.net.synchronization.EntityValueTrackingService;
import electrosphere.renderer.Material;
import electrosphere.renderer.RenderUtils;
@ -268,6 +269,7 @@ public class Globals {
public static ClientSceneWrapper clientSceneWrapper;
public static ClientEntityCullingManager clientEntityCullingManager;
public static ClientSimulation clientSimulation;
public static ClientSynchronizationManager clientSynchronizationManager;
//instanced actor manager
public static InstanceManager clientInstanceManager = new InstanceManager();
@ -406,6 +408,8 @@ public class Globals {
if(Globals.userSettings.getNetRunNetMonitor()){
netMonitor = new NetMonitor();
}
//client synchronization manager
clientSynchronizationManager = new ClientSynchronizationManager();
}
public static void initDefaultAudioResources(){

View File

@ -219,7 +219,8 @@ public class EntityDataStrings {
/*
idle behavior tree
*/
public static final String IDLE_TREE = "idleTree";
public static final String TREE_IDLE = "treeIdle";
public static final String TREE_SERVERIDLE = "treeServerIdle";
/*
particle behavior tree

View File

@ -1,5 +1,8 @@
package electrosphere.entity.state.idle;
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
import electrosphere.entity.state.BehaviorTree;
import electrosphere.entity.state.attack.AttackTree;
import electrosphere.entity.state.attack.AttackTree.AttackTreeState;
@ -38,9 +41,6 @@ public class IdleTree implements BehaviorTree {
@SyncedField
IdleTreeState state;
@SyncedField
int test;
Entity parent;
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
@ -50,7 +50,7 @@ public class IdleTree implements BehaviorTree {
int maxFrame = 60;
public IdleTree(Entity e){
state = IdleTreeState.IDLE;
state = IdleTreeState.NOT_IDLE;
parent = e;
}
@ -58,12 +58,11 @@ public class IdleTree implements BehaviorTree {
return state;
}
public void start(){
//TODO: check if can start moving
state = IdleTreeState.IDLE;
frameCurrent = 0;
public void setState(IdleTreeState state){
this.state = state;
}
public void interrupt(){
state = IdleTreeState.NOT_IDLE;
}
@ -85,38 +84,38 @@ public class IdleTree implements BehaviorTree {
}
//parse attached network messages
for(EntityMessage message : networkMessageQueue){
networkMessageQueue.remove(message);
// System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ());
switch(message.getMessageSubtype()){
case ATTACKUPDATE:
switch(message.gettreeState()){
case 0:
state = IdleTreeState.IDLE;
break;
case 1:
state = IdleTreeState.NOT_IDLE;
break;
}
EntityUtils.getPosition(parent).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
CreatureUtils.setFacingVector(parent, new Vector3d(message.getrotationX(),message.getrotationY(),message.getrotationZ()));
break;
case ATTACHENTITYTOENTITY:
case CREATE:
case DESTROY:
case MOVE:
case MOVEUPDATE:
case SETBEHAVIORTREE:
case SETFACING:
case SETPOSITION:
case SETPROPERTY:
case SPAWNCREATURE:
case SPAWNITEM:
case KILL:
//silently ignore
break;
}
}
// for(EntityMessage message : networkMessageQueue){
// networkMessageQueue.remove(message);
// // System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ());
// switch(message.getMessageSubtype()){
// case ATTACKUPDATE:
// switch(message.gettreeState()){
// case 0:
// state = IdleTreeState.IDLE;
// break;
// case 1:
// state = IdleTreeState.NOT_IDLE;
// break;
// }
// EntityUtils.getPosition(parent).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
// CreatureUtils.setFacingVector(parent, new Vector3d(message.getrotationX(),message.getrotationY(),message.getrotationZ()));
// break;
// case ATTACHENTITYTOENTITY:
// case CREATE:
// case DESTROY:
// case MOVE:
// case MOVEUPDATE:
// case SETBEHAVIORTREE:
// case SETFACING:
// case SETPOSITION:
// case SETPROPERTY:
// case SPAWNCREATURE:
// case SPAWNITEM:
// case KILL:
// //silently ignore
// break;
// }
// }
boolean isIdle;
@ -133,32 +132,32 @@ public class IdleTree implements BehaviorTree {
entityActor.incrementAnimationTime(0.0001);
}
}
isIdle = true;
if(!movementTreeIsIdle){
isIdle = false;
}
if(hasAttackTree){
if(attackTree.getState() != AttackTreeState.IDLE){
isIdle = false;
}
}
if(!isIdle){
state = IdleTreeState.NOT_IDLE;
}
// isIdle = true;
// if(!movementTreeIsIdle){
// isIdle = false;
// }
// if(hasAttackTree){
// if(attackTree.getState() != AttackTreeState.IDLE){
// isIdle = false;
// }
// }
// if(!isIdle){
// state = IdleTreeState.NOT_IDLE;
// }
break;
case NOT_IDLE:
isIdle = true;
if(!movementTreeIsIdle){
isIdle = false;
}
if(hasAttackTree){
if(attackTree.getState() != AttackTreeState.IDLE){
isIdle = false;
}
}
if(isIdle){
state = IdleTreeState.IDLE;
}
// isIdle = true;
// if(!movementTreeIsIdle){
// isIdle = false;
// }
// if(hasAttackTree){
// if(attackTree.getState() != AttackTreeState.IDLE){
// isIdle = false;
// }
// }
// if(isIdle){
// state = IdleTreeState.IDLE;
// }
break;
}
}
@ -183,4 +182,82 @@ public class IdleTree implements BehaviorTree {
networkMessageQueue.add(networkMessage);
}
/**
* <p> Automatically generated </p>
* <p>
* Detatches this tree from the entity.
* </p>
* @param entity The entity to detach to
* @param tree The behavior tree to detach
*/
public static void detachTree(Entity entity, BehaviorTree tree){
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_IDLE_ID);
}
/**
* <p> (initially) Automatically generated </p>
* <p> More parameters can be safely added to this method</p>
* <p>
* Attaches this tree to the entity.
* </p>
* @param entity The entity to attach to
* @param tree The behavior tree to attach
*/
public static IdleTree attachTree(Entity parent){
IdleTree rVal = new IdleTree(parent);
//put manual code here (setting params, etc)
//!!WARNING!! from here below should not be touched
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
parent.putData(EntityDataStrings.TREE_IDLE, rVal);
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_IDLE_ID);
return rVal;
}
/**
* <p> Automatically generated </p>
* <p>
* Converts this enum type to an equivalent short value
* </p>
* @param enumVal The enum value
* @return The short value
*/
public static short getIdleTreeStateEnumAsShort(IdleTreeState enumVal){
switch(enumVal){
case IDLE:
return 0;
case NOT_IDLE:
return 1;
default:
return 0;
}
}
/**
* <p> Automatically generated </p>
* <p>
* Converts a short to the equivalent enum value
* </p>
* @param shortVal The short value
* @return The enum value
*/
public static IdleTreeState getIdleTreeStateShortAsEnum(short shortVal){
switch(shortVal){
case 0:
return IdleTreeState.IDLE;
case 1:
return IdleTreeState.NOT_IDLE;
default:
return IdleTreeState.IDLE;
}
}
/**
* <p>
* Gets the IdleTree of the entity
* </p>
* @param entity the entity
* @return The IdleTree
*/
public static IdleTree getIdleTree(Entity entity){
return (IdleTree)entity.getData(EntityDataStrings.TREE_IDLE);
}
}

View File

@ -10,26 +10,26 @@ import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.engine.Main;
import electrosphere.entity.state.movement.ServerGroundMovementTree.MovementTreeState;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.anim.Animation;
import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Vector3d;
@SynchronizedBehaviorTree(name = "serverIdle", isServer = true)
@SynchronizedBehaviorTree(name = "serverIdle", isServer = true, correspondingTree = "idle")
/**
* Tree for playing an idle animation when an entity isn't doing anything
*/
public class ServerIdleTree {
public class ServerIdleTree implements BehaviorTree {
@SyncedField
IdleTreeState state;
@ -47,9 +47,15 @@ public class ServerIdleTree {
parent = e;
}
/**
* <p> Automatically generated </p>
* <p>
* Gets state.
* </p>
*/
public IdleTreeState getState(){
return state;
}
return state;
}
public void start(){
//TODO: check if can start moving
@ -66,6 +72,7 @@ public class ServerIdleTree {
}
public void simulate(float deltaTime){
System.out.println("simulate server chunk");
Actor entityActor = EntityUtils.getActor(parent);
boolean movementTreeIsIdle = movementTreeIsIdle();
@ -76,40 +83,6 @@ public class ServerIdleTree {
attackTree = CreatureUtils.serverGetAttackTree(parent);
}
//parse attached network messages
for(EntityMessage message : networkMessageQueue){
networkMessageQueue.remove(message);
// System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ());
switch(message.getMessageSubtype()){
case ATTACKUPDATE:
switch(message.gettreeState()){
case 0:
state = IdleTreeState.IDLE;
break;
case 1:
state = IdleTreeState.NOT_IDLE;
break;
}
EntityUtils.getPosition(parent).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
CreatureUtils.setFacingVector(parent, new Vector3d(message.getrotationX(),message.getrotationY(),message.getrotationZ()));
break;
case ATTACHENTITYTOENTITY:
case CREATE:
case DESTROY:
case MOVE:
case MOVEUPDATE:
case SETBEHAVIORTREE:
case SETFACING:
case SETPOSITION:
case SETPROPERTY:
case SPAWNCREATURE:
case SPAWNITEM:
case KILL:
//silently ignore
break;
}
}
boolean isIdle;
//state machine
@ -135,7 +108,7 @@ public class ServerIdleTree {
}
}
if(!isIdle){
state = IdleTreeState.NOT_IDLE;
this.setState(IdleTreeState.NOT_IDLE);
}
break;
case NOT_IDLE:
@ -149,7 +122,7 @@ public class ServerIdleTree {
}
}
if(isIdle){
state = IdleTreeState.IDLE;
this.setState(IdleTreeState.IDLE);
}
break;
}
@ -176,15 +149,25 @@ public class ServerIdleTree {
}
/**
* <p> Automatically generated </p>
* <p> (initially) Automatically generated </p>
* <p> More parameters can be safely added to this method</p>
* <p>
* Attaches this tree to the entity.
* </p>
* @param entity The entity to attach to
* @param tree The behavior tree to attach
*/
public static void attachTree(Entity entity, BehaviorTree tree){
Globals.entityValueTrackingService.attachTreeToEntity(entity, BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID);
public static ServerIdleTree attachTree(Entity parent){
ServerIdleTree rVal = new ServerIdleTree(parent);
//put manual code here (setting params, etc)
//!!WARNING!! from here below should not be touched
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
ServerBehaviorTreeUtils.attachBTreeToEntity(parent, rVal);
parent.putData(EntityDataStrings.TREE_SERVERIDLE, rVal);
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID);
return rVal;
}
/**
@ -199,4 +182,27 @@ public class ServerIdleTree {
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID);
}
/**
* <p> Automatically generated </p>
* <p>
* Sets state and handles the synchronization logic for it.
* </p>
* @param state The value to set state to.
*/
public void setState(IdleTreeState state){
this.state = state;
int value = IdleTree.getIdleTreeStateEnumAsShort(state);
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 1, 1, value));
}
/**
* <p>
* Gets the ServerIdleTree of the entity
* </p>
* @param entity the entity
* @return The ServerIdleTree
*/
public static ServerIdleTree getServerIdleTree(Entity entity){
return (ServerIdleTree)entity.getData(EntityDataStrings.TREE_SERVERIDLE);
}
}

View File

@ -28,6 +28,7 @@ import electrosphere.entity.state.equip.EquipState;
import electrosphere.entity.state.gravity.ClientGravityTree;
import electrosphere.entity.state.gravity.ServerGravityTree;
import electrosphere.entity.state.idle.IdleTree;
import electrosphere.entity.state.idle.ServerIdleTree;
import electrosphere.entity.state.inventory.InventoryState;
import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.entity.state.inventory.RelationalInventoryState;
@ -370,7 +371,7 @@ public class CreatureUtils {
Globals.clientScene.registerEntityToTag(rVal, EntityTags.LIFE_STATE);
//idle tree & generic stuff all creatures have
IdleTree idleTree = new IdleTree(rVal);
rVal.putData(EntityDataStrings.IDLE_TREE, idleTree);
rVal.putData(EntityDataStrings.TREE_IDLE, idleTree);
Globals.clientScene.registerBehaviorTree(idleTree);
Globals.clientScene.registerEntityToTag(rVal, EntityTags.CREATURE);
rVal.putData(EntityDataStrings.DATA_STRING_CREATURE_IS_CREATURE, true);
@ -669,9 +670,8 @@ public class CreatureUtils {
rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.LIFE_STATE);
//idle tree & generic stuff all creatures have
IdleTree idleTree = new IdleTree(rVal);
rVal.putData(EntityDataStrings.IDLE_TREE, idleTree);
ServerBehaviorTreeUtils.attachBTreeToEntity(rVal, idleTree);
ServerIdleTree.attachTree(rVal);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.CREATURE);
rVal.putData(EntityDataStrings.DATA_STRING_CREATURE_IS_CREATURE, true);
rVal.putData(EntityDataStrings.DATA_STRING_CREATURE_TYPE, type);
@ -790,7 +790,7 @@ public class CreatureUtils {
}
public static IdleTree getIdleTree(Entity e){
return (IdleTree)e.getData(EntityDataStrings.IDLE_TREE);
return (IdleTree)e.getData(EntityDataStrings.TREE_IDLE);
}
public static SprintTree clientGetSprintTree(Entity e){

View File

@ -115,7 +115,7 @@ public class ObjectUtils {
// rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));
// Globals.entityManager.registerLifeStateEntity(rVal);
//idle tree & generic stuff all objects have
rVal.putData(EntityDataStrings.IDLE_TREE, new IdleTree(rVal));
rVal.putData(EntityDataStrings.TREE_IDLE, new IdleTree(rVal));
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
return rVal;
}
@ -212,7 +212,7 @@ public class ObjectUtils {
// rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));
// Globals.entityManager.registerLifeStateEntity(rVal);
//idle tree & generic stuff all objects have
rVal.putData(EntityDataStrings.IDLE_TREE, new IdleTree(rVal));
rVal.putData(EntityDataStrings.TREE_IDLE, new IdleTree(rVal));
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
return rVal;
}

View File

@ -17,6 +17,7 @@ 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 org.joml.Vector2f;
import org.joml.Vector3f;
@ -53,6 +54,9 @@ public class ClientProtocol {
case INVENTORY_MESSAGE:
InventoryProtocol.handleInventoryMessage((InventoryMessage)message);
break;
case SYNCHRONIZATION_MESSAGE:
SynchronizationProtocol.handleSynchronizationMessage((SynchronizationMessage)message);
break;
}
}

View File

@ -0,0 +1,18 @@
package electrosphere.net.client.protocol;
import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.SynchronizationMessage;
public class SynchronizationProtocol {
protected static void handleSynchronizationMessage(SynchronizationMessage message){
switch(message.getMessageSubtype()){
case UPDATECLIENTSTATE:
case ATTACHTREE:
case DETATCHTREE:
Globals.clientSynchronizationManager.pushMessage(message);
break;
}
}
}

View File

@ -16,6 +16,7 @@ SERVER_MESSAGE,
AUTH_MESSAGE,
CHARACTER_MESSAGE,
INVENTORY_MESSAGE,
SYNCHRONIZATION_MESSAGE,
}
MessageType type;
@ -352,6 +353,26 @@ INVENTORY_MESSAGE,
break;
}
break;
case TypeBytes.MESSAGE_TYPE_SYNCHRONIZATION:
secondByte = byteBuffer.peek(1);
switch(secondByte){
case TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_UPDATECLIENTSTATE:
if(SynchronizationMessage.canParseMessage(byteBuffer,secondByte)){
rVal = SynchronizationMessage.parseUpdateClientStateMessage(byteBuffer);
}
break;
case TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE:
if(SynchronizationMessage.canParseMessage(byteBuffer,secondByte)){
rVal = SynchronizationMessage.parseAttachTreeMessage(byteBuffer);
}
break;
case TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE:
if(SynchronizationMessage.canParseMessage(byteBuffer,secondByte)){
rVal = SynchronizationMessage.parseDetatchTreeMessage(byteBuffer);
}
break;
}
break;
}
}
return rVal;

View File

@ -0,0 +1,205 @@
package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList;
import java.util.List;
public class SynchronizationMessage extends NetworkMessage {
public enum SynchronizationMessageType {
UPDATECLIENTSTATE,
ATTACHTREE,
DETATCHTREE,
}
SynchronizationMessageType messageType;
int entityId;
int bTreeId;
int fieldId;
int bTreeValue;
SynchronizationMessage(SynchronizationMessageType messageType){
this.type = MessageType.SYNCHRONIZATION_MESSAGE;
this.messageType = messageType;
}
public SynchronizationMessageType getMessageSubtype(){
return this.messageType;
}
public int getentityId() {
return entityId;
}
public void setentityId(int entityId) {
this.entityId = entityId;
}
public int getbTreeId() {
return bTreeId;
}
public void setbTreeId(int bTreeId) {
this.bTreeId = bTreeId;
}
public int getfieldId() {
return fieldId;
}
public void setfieldId(int fieldId) {
this.fieldId = fieldId;
}
public int getbTreeValue() {
return bTreeValue;
}
public void setbTreeValue(int bTreeValue) {
this.bTreeValue = bTreeValue;
}
static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteBuffer.read(2);
}
public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){
case TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_UPDATECLIENTSTATE:
if(byteBuffer.getRemaining() >= TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_UPDATECLIENTSTATE_SIZE){
return true;
} else {
return false;
}
case TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE:
if(byteBuffer.getRemaining() >= TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE_SIZE){
return true;
} else {
return false;
}
case TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE:
if(byteBuffer.getRemaining() >= TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE_SIZE){
return true;
} else {
return false;
}
}
return false;
}
public static SynchronizationMessage parseUpdateClientStateMessage(CircularByteBuffer byteBuffer){
SynchronizationMessage rVal = new SynchronizationMessage(SynchronizationMessageType.UPDATECLIENTSTATE);
stripPacketHeader(byteBuffer);
rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setbTreeId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setfieldId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setbTreeValue(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal;
}
public static SynchronizationMessage constructUpdateClientStateMessage(int entityId,int bTreeId,int fieldId,int bTreeValue){
SynchronizationMessage rVal = new SynchronizationMessage(SynchronizationMessageType.UPDATECLIENTSTATE);
rVal.setentityId(entityId);
rVal.setbTreeId(bTreeId);
rVal.setfieldId(fieldId);
rVal.setbTreeValue(bTreeValue);
rVal.serialize();
return rVal;
}
public static SynchronizationMessage parseAttachTreeMessage(CircularByteBuffer byteBuffer){
SynchronizationMessage rVal = new SynchronizationMessage(SynchronizationMessageType.ATTACHTREE);
stripPacketHeader(byteBuffer);
rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setbTreeId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal;
}
public static SynchronizationMessage constructAttachTreeMessage(int entityId,int bTreeId){
SynchronizationMessage rVal = new SynchronizationMessage(SynchronizationMessageType.ATTACHTREE);
rVal.setentityId(entityId);
rVal.setbTreeId(bTreeId);
rVal.serialize();
return rVal;
}
public static SynchronizationMessage parseDetatchTreeMessage(CircularByteBuffer byteBuffer){
SynchronizationMessage rVal = new SynchronizationMessage(SynchronizationMessageType.DETATCHTREE);
stripPacketHeader(byteBuffer);
rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setbTreeId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal;
}
public static SynchronizationMessage constructDetatchTreeMessage(int entityId,int bTreeId){
SynchronizationMessage rVal = new SynchronizationMessage(SynchronizationMessageType.DETATCHTREE);
rVal.setentityId(entityId);
rVal.setbTreeId(bTreeId);
rVal.serialize();
return rVal;
}
@Override
void serialize(){
byte[] intValues = new byte[8];
byte[] stringBytes;
switch(this.messageType){
case UPDATECLIENTSTATE:
rawBytes = new byte[2+4+4+4+4];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_SYNCHRONIZATION;
//entity messaage header
rawBytes[1] = TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_UPDATECLIENTSTATE;
intValues = ByteStreamUtils.serializeIntToBytes(entityId);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(bTreeId);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(fieldId);
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(bTreeValue);
for(int i = 0; i < 4; i++){
rawBytes[14+i] = intValues[i];
}
break;
case ATTACHTREE:
rawBytes = new byte[2+4+4];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_SYNCHRONIZATION;
//entity messaage header
rawBytes[1] = TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE;
intValues = ByteStreamUtils.serializeIntToBytes(entityId);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(bTreeId);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
break;
case DETATCHTREE:
rawBytes = new byte[2+4+4];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_SYNCHRONIZATION;
//entity messaage header
rawBytes[1] = TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE;
intValues = ByteStreamUtils.serializeIntToBytes(entityId);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(bTreeId);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
break;
}
serialized = true;
}
}

View File

@ -13,6 +13,7 @@ Message categories
public static final byte MESSAGE_TYPE_AUTH = 5;
public static final byte MESSAGE_TYPE_CHARACTER = 6;
public static final byte MESSAGE_TYPE_INVENTORY = 7;
public static final byte MESSAGE_TYPE_SYNCHRONIZATION = 8;
/*
Entity subcategories
*/
@ -151,5 +152,17 @@ Message categories
Inventory packet sizes
*/
public static final byte INVENTORY_MESSAGE_TYPE_REMOVEITEMFROMINVENTORY_SIZE = 6;
/*
Synchronization subcategories
*/
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_UPDATECLIENTSTATE = 0;
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE = 1;
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE = 2;
/*
Synchronization packet sizes
*/
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_UPDATECLIENTSTATE_SIZE = 18;
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE_SIZE = 10;
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE_SIZE = 10;
}

View File

@ -1,6 +1,6 @@
package electrosphere.net.parser.net.raw;
import electrosphere.net.parser.net.message.NetworkMessage;
package electrosphere.net.parser.net.raw;
import electrosphere.net.parser.net.message.NetworkMessage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -15,7 +15,7 @@ public class NetworkParser {
CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CircularByteBuffer incomingByteBuffer = new CircularByteBuffer(64 * 1024 * 1024);
CircularByteBuffer incomingByteBuffer = new CircularByteBuffer(64 * 1024 * 124);
CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList<Byte>();

View File

@ -1,8 +1,85 @@
package electrosphere.net.synchronization;
import electrosphere.entity.state.idle.ServerIdleTree;
import electrosphere.entity.state.idle.IdleTree;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.net.parser.net.message.SynchronizationMessage;
/**
* Takes in raw behavior tree packets from server and pushes their values into respective behavior trees in entities
*/
public class ClientSynchronizationManager {
//The list of messages to loop through
List<SynchronizationMessage> messages = new CopyOnWriteArrayList<SynchronizationMessage>();
/**
* Pushes a message into the queue to be processed
* @param message The message
*/
public void pushMessage(SynchronizationMessage message){
this.messages.add(message);
}
/**
* Processes all messages in the queue and then clears the queue
*/
public void processMessages(){
List<SynchronizationMessage> messagesToClear = new LinkedList<SynchronizationMessage>();
for(SynchronizationMessage message : messages){
messagesToClear.add(message);
switch(message.getMessageSubtype()){
case UPDATECLIENTSTATE:{
int bTreeId = message.getbTreeId();
int entityId = message.getentityId();
Entity targetEntity = Globals.clientSceneWrapper.getEntityFromServerId(entityId);
updateEntityState(targetEntity,bTreeId,message);
} break;
case ATTACHTREE:{
int bTreeId = message.getbTreeId();
int bTreeValue = message.getbTreeValue();
int entityId = message.getentityId();
} break;
case DETATCHTREE:{
int bTreeId = message.getbTreeId();
int entityId = message.getentityId();
} break;
}
}
for(SynchronizationMessage message : messagesToClear){
messages.remove(message);
}
}
/**
* <p> Automatically generated </p>
* <p>
* Updates the state of a given behavior tree on a given entity
* </p>
* @param entity The entity
* @param bTreeId The id of the behavior tree
* @param message The raw synchronization message holding the update data
*/
private void updateEntityState(Entity entity, int bTreeId, SynchronizationMessage message){
switch(bTreeId){
case BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID: {
switch(message.getfieldId()){
case 1:{
IdleTree tree = IdleTree.getIdleTree(entity);
tree.setState(IdleTree.getIdleTreeStateShortAsEnum((short)message.getbTreeValue()));
} break;
}
} break;
}
}
}

View File

@ -1,30 +0,0 @@
package electrosphere.net.synchronization;
import electrosphere.entity.state.idle.IdleTree.IdleTreeState;
public class TypeTranslator {
public static short getIdleStateEnumAsShort(IdleTreeState enumVal){
switch(enumVal){
case IDLE:
return 0;
case NOT_IDLE:
return 1;
default:
return 0;
}
}
public static IdleTreeState getIdleStateShortAsEnum(short rawValue){
switch(rawValue){
case 0:
return IdleTreeState.IDLE;
case 1:
return IdleTreeState.NOT_IDLE;
default:
return IdleTreeState.IDLE;
}
}
}

View File

@ -13,7 +13,8 @@
"./net/world.json",
"./net/server.json",
"./net/character.json",
"./net/inventory.json"
"./net/inventory.json",
"./net/synchronization.json"
]
}