diff --git a/net/synchronization.json b/net/synchronization.json index 81d2cac4..51cda9a8 100644 --- a/net/synchronization.json +++ b/net/synchronization.json @@ -113,6 +113,16 @@ "bTreeValue" ] }, + { + "messageName" : "ServerNotifyBTreeTransition", + "description" : "Packet from the server to the client notifying the client that it should transition a btree from one state to another", + "data" : [ + "entityId", + "bTreeId", + "fieldId", + "bTreeValue" + ] + }, { "messageName" : "AttachTree", "description" : "Attaches a btree to an entity on the client", diff --git a/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java b/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java index 3f12e10c..022a3084 100644 --- a/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java +++ b/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java @@ -191,6 +191,87 @@ public class StateTransitionUtil { } } + /** + * Interrupts a given state + * @param stateEnum The state enum + */ + public void interrupt(Object stateEnum){ + StateTransitionUtilItem state = null; + for(StateTransitionUtilItem targetState : states){ + if(targetState.stateEnum == stateEnum){ + state = targetState; + break; + } + } + if(state == null){ + LoggerInterface.loggerEngine.DEBUG("Skipping state " + stateEnum + " because there is not a state registered to that enum value!"); + } else { + if(this.isServer){ + interruptServerState(this.parent,state); + } else { + interruptClientState(this.parent,state); + } + } + } + + /** + * Interrupts animation logic for client tree + * @param parent The parent entity + * @param state The state + */ + private static void interruptClientState(Entity parent, StateTransitionUtilItem state){ + Actor actor = EntityUtils.getActor(parent); + if(actor != null){ + + //get the animation to play + TreeDataAnimation animation = state.animation; + if(state.getAnimation != null && state.getAnimation.get() != null){ + animation = state.getAnimation.get(); + } + + + // + //Interrupt main animation + // + if(animation != null && actor.isPlayingAnimation() && actor.isPlayingAnimation(animation)){ + actor.interruptAnimation(animation, true); + } + + // + //Interrupt animation in first person + // + if(animation != null){ + FirstPersonTree.conditionallyInterruptAnimation(Globals.firstPersonEntity, animation); + } + } + } + + /** + * Interrupts animation logic for server tree + * @param parent The parent entity + * @param state The state + */ + private static void interruptServerState(Entity parent, StateTransitionUtilItem state){ + PoseActor poseActor = EntityUtils.getPoseActor(parent); + if(poseActor != null){ + + //get the animation to play + TreeDataAnimation animation = state.animation; + if(state.getAnimation != null && state.getAnimation.get() != null){ + animation = state.getAnimation.get(); + } + + + + // + //Interrupt main animation + // + if(animation != null && poseActor.isPlayingAnimation() && poseActor.isPlayingAnimation(animation)){ + poseActor.interruptAnimation(animation, true); + } + } + } + /** * A parameter used to construct a StateTransitionUtil */ diff --git a/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java b/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java index 581007af..59a9a852 100644 --- a/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java +++ b/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java @@ -31,7 +31,7 @@ public class ClientBlockTree implements BehaviorTree { NOT_BLOCKING, } - @SyncedField + @SyncedField(serverSendTransitionPacket = true) BlockState state = BlockState.NOT_BLOCKING; //the current state //the parent entity to this tree @@ -74,6 +74,31 @@ public class ClientBlockTree implements BehaviorTree { }); } + /** + *
(Initially) Automatically Generated
+ *+ * Performs a state transition on a client state variable. + * Will be triggered when a server performs a state change. + *
+ * @param newState The new value of the state + */ + public void transitionState(BlockState newState){ + this.setState(newState); + switch(newState){ + case WIND_UP: { + } break; + case BLOCKING: { + this.stateTransitionUtil.interrupt(BlockState.WIND_UP); + } break; + case COOLDOWN: { + this.stateTransitionUtil.interrupt(BlockState.BLOCKING); + } break; + case NOT_BLOCKING: { + this.stateTransitionUtil.interrupt(BlockState.COOLDOWN); + } break; + } + } + @Override public void simulate(float deltaTime) { switch(state){ diff --git a/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java b/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java index b8792d79..9d9d95b4 100644 --- a/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java +++ b/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java @@ -26,7 +26,7 @@ import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; */ public class ServerBlockTree implements BehaviorTree { - @SyncedField + @SyncedField(serverSendTransitionPacket = true) BlockState state = BlockState.NOT_BLOCKING; //the current state of the tree //the parent entity to this tree @@ -152,7 +152,7 @@ public class ServerBlockTree implements BehaviorTree { public void setState(BlockState state){ this.state = state; int value = ClientBlockTree.getBlockStateEnumAsShort(state); - DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), BehaviorTreeIdEnums.BTREE_SERVERBLOCKTREE_ID, FieldIdEnums.TREE_SERVERBLOCKTREE_SYNCEDFIELD_STATE_ID, value)); + DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructServerNotifyBTreeTransitionMessage(parent.getId(), BehaviorTreeIdEnums.BTREE_SERVERBLOCKTREE_ID, FieldIdEnums.TREE_SERVERBLOCKTREE_SYNCEDFIELD_STATE_ID, value)); } /** *(initially) Automatically generated
diff --git a/src/main/java/electrosphere/net/client/protocol/SynchronizationProtocol.java b/src/main/java/electrosphere/net/client/protocol/SynchronizationProtocol.java index 875cd7f1..b97efd57 100644 --- a/src/main/java/electrosphere/net/client/protocol/SynchronizationProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/SynchronizationProtocol.java @@ -27,6 +27,7 @@ public class SynchronizationProtocol implements ClientProtocolTemplate+ * Transitions a behavior tree to a new state + *
+ * @param entity The entity + * @param bTreeId The id of the behavior tree + * @param message The raw synchronization message holding the update data + */ + private void transitionBTree(Entity entity, int bTreeId, SynchronizationMessage message){ + switch(bTreeId){ + case BehaviorTreeIdEnums.BTREE_SERVERBLOCKTREE_ID: { + switch(message.getfieldId()){ + case FieldIdEnums.TREE_SERVERBLOCKTREE_SYNCEDFIELD_STATE_ID:{ + ClientBlockTree tree = ClientBlockTree.getClientBlockTree(entity); + tree.transitionState(ClientBlockTree.getBlockStateShortAsEnum((short)message.getbTreeValue())); + } break; + } + } break; + + } + } } diff --git a/src/main/java/electrosphere/net/synchronization/ServerSynchronizationManager.java b/src/main/java/electrosphere/net/synchronization/ServerSynchronizationManager.java index d04d1311..0251ca90 100644 --- a/src/main/java/electrosphere/net/synchronization/ServerSynchronizationManager.java +++ b/src/main/java/electrosphere/net/synchronization/ServerSynchronizationManager.java @@ -59,6 +59,7 @@ public class ServerSynchronizationManager { case ATTACHTREE: case DETATCHTREE: case LOADSCENE: + case SERVERNOTIFYBTREETRANSITION: //silently ignore break; } diff --git a/src/main/java/electrosphere/net/synchronization/annotation/SyncedField.java b/src/main/java/electrosphere/net/synchronization/annotation/SyncedField.java index 9c1601a5..b1e59c87 100644 --- a/src/main/java/electrosphere/net/synchronization/annotation/SyncedField.java +++ b/src/main/java/electrosphere/net/synchronization/annotation/SyncedField.java @@ -23,4 +23,8 @@ public @interface SyncedField { //ie when idle state changes (to idle from not idle), tell the client the position of the entity when this update happened alongside the actual state update public boolean updatePositionOnStateChange() default false; + //Instructs the server to send a state-transition packet instead of an immediate update packet + //The state transition packet will invoke the transitionBTree function on the client instead of immediately overwriting the state's value + public boolean serverSendTransitionPacket() default false; + }