diff --git a/assets/Data/creatures/human.json b/assets/Data/creatures/human.json
index bc3c3059..9f4dc1f5 100644
--- a/assets/Data/creatures/human.json
+++ b/assets/Data/creatures/human.json
@@ -257,6 +257,7 @@
"firstPersonBone" : "hand.R",
"offsetVector" : [0,0,0],
"offsetRotation" : [-0.334,0.145,-0.28,0.89],
+ "canBlock" : true,
"equipClassWhitelist" : [
"tool",
"weapon",
@@ -284,6 +285,22 @@
]
}
],
+ "blockSystem" : {
+ "variants": [
+ {
+ "variantId": "blockWeaponRight",
+ "windUpAnimation" : "Jump",
+ "mainAnimation" : "Fall",
+ "cooldownAnimation" : "Land",
+ "defaults" : [
+ {
+ "equipPoint" : "handRight",
+ "itemClassEquipped" : "weapon"
+ }
+ ]
+ }
+ ]
+ },
"collidable" : {
"type" : "CYLINDER",
"dimension1" : 0.1,
diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md
index 7a44f5cf..bce4b2c1 100644
--- a/docs/src/progress/renderertodo.md
+++ b/docs/src/progress/renderertodo.md
@@ -362,6 +362,9 @@ Fix equipping an item spawning two items
Fix inventory ui not closing when you hit 'i' key (will need to update utility functions to manage input mode so you're not doing it in callback)
Develop debug ui for equip points
+(06/18/2024)
+Block state synchronization between client and server
+
# TODO
@@ -375,15 +378,16 @@ Audio FX for everything
= Coding =
+Sour spot, sweet spot for damage hitboxes and hurtboxes
Fix items falling below the ground
-Control rebinding menu from title screen
+Sub menu on title screen that allows changing control mappings
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
- Introduce block hitbox (blockbox) type
Enemy AI
Probably some kind of tutorial text
Network-able ui messages
Ability to display video both on title screen as well as in game windows for tutorials
-better scaffolding for scripting engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
+better scaffolding for scriptig engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
Ability for private realms to have time start/stop based on the player's feedback <-- sync this up to tutorial ui via script
diff --git a/net/inventory.json b/net/inventory.json
index de89e98e..c02d9021 100644
--- a/net/inventory.json
+++ b/net/inventory.json
@@ -24,6 +24,14 @@
{
"name" : "containerType",
"type" : "FIXED_INT"
+ },
+ {
+ "name" : "itemActionCode",
+ "type" : "FIXED_INT"
+ },
+ {
+ "name" : "itemActionCodeState",
+ "type" : "FIXED_INT"
}
],
"messageTypes" : [
@@ -81,6 +89,15 @@
"data" : [
"equipPointId"
]
+ },
+ {
+ "messageName" : "clientRequestPerformItemAction",
+ "description" : "Requests that the server have the entity perform its equipped item's action for the given equip point",
+ "data" : [
+ "equipPointId",
+ "itemActionCode",
+ "itemActionCodeState"
+ ]
}
]
}
diff --git a/src/main/java/electrosphere/client/item/ItemActions.java b/src/main/java/electrosphere/client/item/ItemActions.java
new file mode 100644
index 00000000..1516dce5
--- /dev/null
+++ b/src/main/java/electrosphere/client/item/ItemActions.java
@@ -0,0 +1,40 @@
+package electrosphere.client.item;
+
+import electrosphere.engine.Globals;
+import electrosphere.net.parser.net.message.InventoryMessage;
+
+/**
+ * Utilities for telling the server to perform actions with an item that the player has equipped
+ */
+public class ItemActions {
+
+ //the item action code for left clicking
+ public static final int ITEM_ACTION_CODE_PRIMARY = 0;
+ //the item action code for right clicking
+ public static final int ITEM_ACTION_CODE_SECONDARY = 1;
+
+ //the state for performing the item action code
+ public static final int ITEM_ACTION_CODE_STATE_ON = 1;
+
+ //the state for releasing the item action code
+ public static final int ITEM_ACTION_CODE_STATE_OFF = 0;
+
+ /**
+ * Attempts to perform the secondary item action
+ */
+ public static void attemptSecondaryItemAction(){
+ //tell the server we want the secondary hand item to START doing something
+ Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage("handRight", ITEM_ACTION_CODE_SECONDARY, ITEM_ACTION_CODE_STATE_ON));
+ //TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server)
+ }
+
+ /**
+ * Releases the secondary item action
+ */
+ public static void releaseSecondaryItemAction(){
+ //tell the server we want the secondary hand item to STOP doing something
+ Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage("handRight", ITEM_ACTION_CODE_SECONDARY, ITEM_ACTION_CODE_STATE_OFF));
+ //TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server)
+ }
+
+}
diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java
index ee8ef12c..d2f80519 100644
--- a/src/main/java/electrosphere/controls/ControlHandler.java
+++ b/src/main/java/electrosphere/controls/ControlHandler.java
@@ -71,6 +71,7 @@ import org.joml.Vector3d;
import org.joml.Vector3f;
import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
+import electrosphere.client.item.ItemActions;
import electrosphere.client.targeting.crosshair.Crosshair;
import electrosphere.client.terrain.editing.TerrainEditing;
import electrosphere.collision.CollisionEngine;
@@ -85,7 +86,6 @@ import electrosphere.entity.state.attack.ShooterTree;
import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
-import electrosphere.entity.state.ironsight.IronSightTree;
import electrosphere.entity.state.movement.JumpTree;
import electrosphere.entity.state.movement.SprintTree;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
@@ -130,7 +130,7 @@ public class ControlHandler {
public static final String INPUT_CODE_DROP = "drop";
public static final String INPUT_CODE_INVENTORY_OPEN = "inventoryOpen";
public static final String INPUT_CODE_CHARACTER_OPEN = "characterOpen";
- public static final String INPUT_CODE_IRON_SIGHT = "ironSight";
+ public static final String ITEM_SECONDARY = "actionItemSecondary";
public static final String INPUT_CODE_PLACE_TERRAIN = "placeTerrain";
public static final String INPUT_CODE_REMOVE_TERRAIN = "removeTerrain";
@@ -312,7 +312,7 @@ public class ControlHandler {
handler.addControl(INPUT_CODE_DROP, new Control(ControlType.KEY,GLFW_KEY_Y));
handler.addControl(INPUT_CODE_INVENTORY_OPEN, new Control(ControlType.KEY,GLFW_KEY_I));
handler.addControl(INPUT_CODE_CHARACTER_OPEN, new Control(ControlType.KEY,GLFW_KEY_C));
- handler.addControl(INPUT_CODE_IRON_SIGHT, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_RIGHT));
+ handler.addControl(ITEM_SECONDARY, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_RIGHT));
/*
Map the menu navigation controls
@@ -837,22 +837,12 @@ public class ControlHandler {
}
}});
- mainGameControlList.add(controls.get(INPUT_CODE_IRON_SIGHT));
- controls.get(INPUT_CODE_IRON_SIGHT).setOnPress(new ControlMethod() {public void execute() {
- if(Globals.playerEntity != null){
- IronSightTree ironSightTree = IronSightTree.getIronSightTree(Globals.playerEntity);
- if(ironSightTree != null){
- ironSightTree.start();
- }
- }
+ mainGameControlList.add(controls.get(ITEM_SECONDARY));
+ controls.get(ITEM_SECONDARY).setOnPress(new ControlMethod() {public void execute() {
+ ItemActions.attemptSecondaryItemAction();
}});
- controls.get(INPUT_CODE_IRON_SIGHT).setOnRelease(new ControlMethod() {public void execute() {
- if(Globals.playerEntity != null){
- IronSightTree ironSightTree = IronSightTree.getIronSightTree(Globals.playerEntity);
- if(ironSightTree != null){
- ironSightTree.release();
- }
- }
+ controls.get(ITEM_SECONDARY).setOnRelease(new ControlMethod() {public void execute() {
+ ItemActions.releaseSecondaryItemAction();
}});
/*
diff --git a/src/main/java/electrosphere/engine/Main.java b/src/main/java/electrosphere/engine/Main.java
index 400ee7ae..2777bf5e 100644
--- a/src/main/java/electrosphere/engine/Main.java
+++ b/src/main/java/electrosphere/engine/Main.java
@@ -20,6 +20,7 @@ import electrosphere.game.server.world.MacroData;
import electrosphere.logger.LoggerInterface;
import electrosphere.menu.debug.ImGuiWindowMacros;
import electrosphere.renderer.RenderingEngine;
+import electrosphere.server.MainServerFunctions;
import electrosphere.server.simulation.MacroSimulation;
@@ -319,21 +320,10 @@ public class Main {
///
- /// S E R V E R M I C R O S I M U L A T I O N
+ /// S E R V E R M A I N R O U T I N E S
///
- Globals.profiler.beginCpuSample("Server simulation");
- LoggerInterface.loggerEngine.DEBUG("Begin server micro simulation");
- if(Globals.realmManager != null){
- Globals.realmManager.simulate();
- }
-
- ///
- /// M A C R O S I M U L A T I O N S T U F F
- ///
- LoggerInterface.loggerEngine.DEBUG("Begin server macro simulation");
- if(Globals.macroSimulation != null && Globals.macroSimulation.isReady()){
- Globals.macroSimulation.simulate();
- }
+ Globals.profiler.beginCpuSample("Main Server Functions");
+ MainServerFunctions.simulate();
Globals.profiler.endCpuSample();
}
diff --git a/src/main/java/electrosphere/entity/EntityDataStrings.java b/src/main/java/electrosphere/entity/EntityDataStrings.java
index 19cacca8..d85d2778 100644
--- a/src/main/java/electrosphere/entity/EntityDataStrings.java
+++ b/src/main/java/electrosphere/entity/EntityDataStrings.java
@@ -272,6 +272,12 @@ public class EntityDataStrings {
*/
public static final String IRON_SIGHT_TREE = "ironSightTree";
+ /*
+ * Block trees
+ */
+ public static final String TREE_CLIENTBLOCKTREE = "treeClientBlockTree";
+ public static final String TREE_SERVERBLOCKTREE = "treeServerBlockTree";
+
/*
AI stuff
*/
diff --git a/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java b/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java
index 427a03f5..9c93e7c9 100644
--- a/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java
+++ b/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java
@@ -1,27 +1,224 @@
package electrosphere.entity.state.block;
+
+import electrosphere.engine.Globals;
+import electrosphere.entity.Entity;
+import electrosphere.entity.EntityDataStrings;
+import electrosphere.entity.EntityUtils;
+import electrosphere.entity.btree.BehaviorTree;
+import electrosphere.game.data.creature.type.block.BlockSystem;
+import electrosphere.net.synchronization.BehaviorTreeIdEnums;
+
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
+import electrosphere.renderer.actor.Actor;
@SynchronizedBehaviorTree(name = "clientBlockTree", isServer = false, correspondingTree="serverBlockTree")
/**
* Client block tree
*/
-public class ClientBlockTree {
+public class ClientBlockTree implements BehaviorTree {
@SynchronizableEnum
/**
* The state of the block tree
*/
public enum BlockState {
+ WIND_UP,
BLOCKING,
+ COOLDOWN,
NOT_BLOCKING,
}
@SyncedField
- BlockState state;
+ BlockState state = BlockState.NOT_BLOCKING; //the current state
+
+ //the parent entity to this tree
+ Entity parent;
+
+ @SyncedField
+ String currentBlockVariant = null; //The current block variant (depends on equipped items)
+
+ //The data for block animations
+ BlockSystem blockSystem;
+
+ /**
+ * Constructor
+ */
+ private ClientBlockTree(Entity parent, BlockSystem blockSystem){
+ this.parent = parent;
+ this.blockSystem = blockSystem;
+ }
+
+ @Override
+ public void simulate(float deltaTime) {
+ Actor actor = EntityUtils.getActor(parent);
+ switch(state){
+ case WIND_UP: {
+ if(actor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
+ String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getWindUpAnimation();
+ if(
+ !actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationToPlay)
+ ){
+ actor.playAnimation(animationToPlay,1);
+ actor.incrementAnimationTime(0.0001);
+ }
+ }
+ } break;
+ case BLOCKING: {
+ if(actor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
+ String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getMainAnimation();
+ if(
+ !actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationToPlay)
+ ){
+ actor.playAnimation(animationToPlay,1);
+ actor.incrementAnimationTime(0.0001);
+ }
+ }
+ } break;
+ case COOLDOWN: {
+ if(actor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
+ String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getCooldownAnimation();
+ if(
+ !actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationToPlay)
+ ){
+ actor.playAnimation(animationToPlay,1);
+ actor.incrementAnimationTime(0.0001);
+ }
+ }
+ } break;
+ case NOT_BLOCKING: {
+
+ } break;
+ }
+ }
+ /**
+ *
Automatically generated
+ *
+ * Gets state.
+ *
+ */
+ public BlockState getState(){
+ return state;
+ }
+ /**
+ * Automatically generated
+ *
+ * Sets state and handles the synchronization logic for it.
+ *
+ * @param state The value to set state to.
+ */
+ public void setState(BlockState state){
+ this.state = state;
+ }
+ /**
+ * (initially) Automatically generated
+ * More parameters can be safely added to this method
+ *
+ * Attaches this tree to the entity.
+ *
+ * @param entity The entity to attach to
+ * @param tree The behavior tree to attach
+ */
+ public static ClientBlockTree attachTree(Entity parent, BlockSystem blockSystem){
+ ClientBlockTree rVal = new ClientBlockTree(parent, blockSystem);
+ //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_CLIENTBLOCKTREE, rVal);
+ Globals.clientSceneWrapper.getScene().registerBehaviorTree(rVal);
+ Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_CLIENTBLOCKTREE_ID);
+ return rVal;
+ }
+ /**
+ * Automatically generated
+ *
+ * Detatches this tree from the entity.
+ *
+ * @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_CLIENTBLOCKTREE_ID);
+ }
+ /**
+ *
+ * Gets the ClientBlockTree of the entity
+ *
+ * @param entity the entity
+ * @return The ClientBlockTree
+ */
+ public static ClientBlockTree getClientBlockTree(Entity entity){
+ return (ClientBlockTree)entity.getData(EntityDataStrings.TREE_CLIENTBLOCKTREE);
+ }
+ /**
+ * Automatically generated
+ *
+ * Converts this enum type to an equivalent short value
+ *
+ * @param enumVal The enum value
+ * @return The short value
+ */
+ public static short getBlockStateEnumAsShort(BlockState enumVal){
+ switch(enumVal){
+ case WIND_UP:
+ return 0;
+ case BLOCKING:
+ return 1;
+ case COOLDOWN:
+ return 2;
+ case NOT_BLOCKING:
+ return 3;
+ default:
+ return 0;
+ }
+ }
+ /**
+ * Automatically generated
+ *
+ * Converts a short to the equivalent enum value
+ *
+ * @param shortVal The short value
+ * @return The enum value
+ */
+ public static BlockState getBlockStateShortAsEnum(short shortVal){
+ switch(shortVal){
+ case 0:
+ return BlockState.WIND_UP;
+ case 1:
+ return BlockState.BLOCKING;
+ case 2:
+ return BlockState.COOLDOWN;
+ case 3:
+ return BlockState.NOT_BLOCKING;
+ default:
+ return BlockState.WIND_UP;
+ }
+ }
+
+ /**
+ * Automatically generated
+ *
+ * Gets currentBlockVariant.
+ *
+ */
+ public String getCurrentBlockVariant(){
+ return currentBlockVariant;
+ }
+ /**
+ * Automatically generated
+ *
+ * Sets currentBlockVariant and handles the synchronization logic for it.
+ *
+ * @param currentBlockVariant The value to set currentBlockVariant to.
+ */
+ public void setCurrentBlockVariant(String currentBlockVariant){
+ this.currentBlockVariant = currentBlockVariant;
+ }
}
diff --git a/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java b/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java
index afb31283..ff9ddf2b 100644
--- a/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java
+++ b/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java
@@ -1,6 +1,21 @@
package electrosphere.entity.state.block;
+
+import electrosphere.engine.Globals;
+import electrosphere.entity.Entity;
+import electrosphere.entity.EntityDataStrings;
+import electrosphere.entity.EntityUtils;
+import electrosphere.entity.btree.BehaviorTree;
+import electrosphere.net.synchronization.BehaviorTreeIdEnums;
+
+import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
+import electrosphere.server.poseactor.PoseActor;
+import electrosphere.net.parser.net.message.SynchronizationMessage;
+
+import electrosphere.server.datacell.utils.DataCellSearchUtils;
+
import electrosphere.entity.state.block.ClientBlockTree.BlockState;
+import electrosphere.game.data.creature.type.block.BlockSystem;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
@@ -8,9 +23,175 @@ import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
/**
* Server block tree
*/
-public class ServerBlockTree {
+public class ServerBlockTree implements BehaviorTree {
@SyncedField
- BlockState state;
+ BlockState state = BlockState.NOT_BLOCKING; //the current state of the tree
+
+ //the parent entity to this tree
+ Entity parent;
+
+ @SyncedField
+ String currentBlockVariant = null; //The current block variant (depends on equipped items)
+
+ //The data for block animations
+ BlockSystem blockSystem;
+
+ /**
+ * Constructor
+ */
+ private ServerBlockTree(Entity parent, BlockSystem blockSystem){
+ this.parent = parent;
+ this.blockSystem = blockSystem;
+ }
+
+ /**
+ * Starts the block tree
+ */
+ public void start(){
+ setState(BlockState.WIND_UP);
+ }
+
+ /**
+ * Stops the block tree
+ */
+ public void stop(){
+ setState(BlockState.COOLDOWN);
+ }
+
+ @Override
+ public void simulate(float deltaTime) {
+ PoseActor poseActor = EntityUtils.getPoseActor(parent);
+ switch(state){
+ case WIND_UP: {
+ if(poseActor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
+ String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getWindUpAnimation();
+ if(
+ !poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay)
+ ){
+ poseActor.playAnimation(animationToPlay,1);
+ poseActor.incrementAnimationTime(0.0001);
+ }
+ }
+ } break;
+ case BLOCKING: {
+ if(poseActor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
+ String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getMainAnimation();
+ if(
+ !poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay)
+ ){
+ poseActor.playAnimation(animationToPlay,1);
+ poseActor.incrementAnimationTime(0.0001);
+ }
+ }
+ } break;
+ case COOLDOWN: {
+ if(poseActor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
+ String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getCooldownAnimation();
+ if(
+ !poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay)
+ ){
+ poseActor.playAnimation(animationToPlay,1);
+ poseActor.incrementAnimationTime(0.0001);
+ }
+ }
+ } break;
+ case NOT_BLOCKING: {
+
+ } break;
+ }
+ }
+
+ /**
+ * Gets the block system data for this tree
+ * @return the data if it exists, otherwise null
+ */
+ public BlockSystem getBlockSystem(){
+ return this.blockSystem;
+ }
+ /**
+ * Automatically generated
+ *
+ * Gets state.
+ *
+ */
+ public BlockState getState(){
+ return state;
+ }
+ /**
+ * Automatically generated
+ *
+ * Sets state and handles the synchronization logic for it.
+ *
+ * @param state The value to set state to.
+ */
+ public void setState(BlockState state){
+ this.state = state;
+ int value = ClientBlockTree.getBlockStateEnumAsShort(state);
+ DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 3, 8, value));
+ }
+ /**
+ * (initially) Automatically generated
+ * More parameters can be safely added to this method
+ *
+ * Attaches this tree to the entity.
+ *
+ * @param entity The entity to attach to
+ * @param tree The behavior tree to attach
+ */
+ public static ServerBlockTree attachTree(Entity parent, BlockSystem blockSystem){
+ ServerBlockTree rVal = new ServerBlockTree(parent, blockSystem);
+ //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_SERVERBLOCKTREE, rVal);
+ Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_SERVERBLOCKTREE_ID);
+ return rVal;
+ }
+ /**
+ * Automatically generated
+ *
+ * Detatches this tree from the entity.
+ *
+ * @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_SERVERBLOCKTREE_ID);
+ }
+ /**
+ *
+ * Gets the ServerBlockTree of the entity
+ *
+ * @param entity the entity
+ * @return The ServerBlockTree
+ */
+ public static ServerBlockTree getServerBlockTree(Entity entity){
+ return (ServerBlockTree)entity.getData(EntityDataStrings.TREE_SERVERBLOCKTREE);
+ }
+
+ /**
+ * Automatically generated
+ *
+ * Gets currentBlockVariant.
+ *
+ */
+ public String getCurrentBlockVariant(){
+ return currentBlockVariant;
+ }
+ /**
+ * Automatically generated
+ *
+ * Sets currentBlockVariant and handles the synchronization logic for it.
+ *
+ * @param currentBlockVariant The value to set currentBlockVariant to.
+ */
+ public void setCurrentBlockVariant(String currentBlockVariant){
+ this.currentBlockVariant = currentBlockVariant;
+ DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStringStateMessage(parent.getId(), 3, 9, currentBlockVariant));
+ }
}
diff --git a/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java b/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java
index 4b4eee3c..15663018 100644
--- a/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java
+++ b/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java
@@ -107,8 +107,11 @@ public class ClientEquipState implements BehaviorTree {
List pointEquipClassList = point.getEquipClassWhitelist();
boolean itemIsInPointWhitelist = pointEquipClassList.contains(equipItemClass);
if(!hasEquipped && targetIsItem && !targetIsAttached && itemIsInPointWhitelist){
+
+ //
+ //visual transforms
if(targetHasWhitelist){
- //by attaching are we going to be replacing meshes?
+ //depends on the type of creature, must be replacing a mesh
String parentCreatureId = CreatureUtils.getType(parent);
List whitelist = ItemUtils.getEquipWhitelist(toEquip);
for(EquipWhitelist whitelistItem : whitelist){
@@ -141,7 +144,7 @@ public class ClientEquipState implements BehaviorTree {
}
}
} else {
- //since we're not replacing meshes we must be attaching to a bone
+ //does not depend on the type of creature, must be attaching to a bone
equipMap.put(point.getEquipPointId(),toEquip);
if(Globals.controlHandler.cameraIsThirdPerson()){
AttachUtils.clientAttachEntityToEntityAtBone(parent, toEquip, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
@@ -284,8 +287,11 @@ public class ClientEquipState implements BehaviorTree {
Entity equipped = equipMap.remove(pointId);
if(equipped != null){
boolean targetHasWhitelist = ItemUtils.hasEquipList(equipped);
+
+ //
+ //visual transforms
if(targetHasWhitelist){
- //by attaching are we going to be replacing meshes?
+ //depends on the type of creature, must be replacing meshes
String parentCreatureId = CreatureUtils.getType(parent);
List whitelist = ItemUtils.getEquipWhitelist(equipped);
for(EquipWhitelist whitelistItem : whitelist){
@@ -304,6 +310,7 @@ public class ClientEquipState implements BehaviorTree {
}
}
} else {
+ //does not depend on the type of creature
AttachUtils.clientDetatchEntityFromEntityAtBone(parent, equipped);
EntityUtils.cleanUpEntity(equipped);
}
diff --git a/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java b/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java
index b2cc1752..2cf2c422 100644
--- a/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java
+++ b/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java
@@ -21,6 +21,7 @@ import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
+import electrosphere.entity.state.block.ServerBlockTree;
import electrosphere.entity.state.gravity.GravityUtils;
import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.entity.state.inventory.RelationalInventoryState;
@@ -28,6 +29,8 @@ import electrosphere.entity.state.inventory.UnrelationalInventoryState;
import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils;
+import electrosphere.game.data.creature.type.block.BlockSystem;
+import electrosphere.game.data.creature.type.block.BlockVariant;
import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.game.data.item.type.EquipWhitelist;
import electrosphere.net.parser.net.message.InventoryMessage;
@@ -46,9 +49,12 @@ import electrosphere.server.datacell.utils.ServerEntityTagUtils;
*/
public class ServerEquipState implements BehaviorTree {
+ //the parent entity of this equip state
Entity parent;
+ //the list of available equip points
List equipPoints = new LinkedList();
+ //the map of equip point id -> entity equipped at said point
Map equipMap = new HashMap();
public ServerEquipState(Entity parent, List equipPoints){
@@ -76,6 +82,11 @@ public class ServerEquipState implements BehaviorTree {
}
}
+ /**
+ * Attempts to equip an item
+ * @param inInventoryEntity The item to equip
+ * @param point The point to equip to
+ */
public void serverAttemptEquip(Entity inInventoryEntity, EquipPoint point){
boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId());
boolean targetIsItem = ItemUtils.isItem(inInventoryEntity);
@@ -91,8 +102,10 @@ public class ServerEquipState implements BehaviorTree {
//bind in world with in inventory
ItemUtils.setRealWorldEntity(inInventoryEntity, inWorldItem);
+ //
+ //Visual transforms
if(targetHasWhitelist){
- //by attaching are we going to be replacing meshes?
+ //depends on the type of creature
String parentCreatureId = CreatureUtils.getType(parent);
List whitelist = ItemUtils.getEquipWhitelist(inWorldItem);
for(EquipWhitelist whitelistItem : whitelist){
@@ -117,7 +130,7 @@ public class ServerEquipState implements BehaviorTree {
}
}
} else {
- //since we're not replacing meshes we must be attaching to a bone
+ //does not depend on the type of creature
equipMap.put(point.getEquipPointId(),inWorldItem);
AttachUtils.serverAttachEntityToEntityAtBone(parent, inWorldItem, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
if(inWorldItem.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && inWorldItem.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){
@@ -128,6 +141,11 @@ public class ServerEquipState implements BehaviorTree {
ServerEntityTagUtils.removeTagFromEntity(inWorldItem, EntityTags.TARGETABLE);
GravityUtils.serverAttemptDeactivateGravity(inWorldItem);
}
+
+ //
+ //update block state based on what we have equipped
+ this.updateBlockVariant();
+
//we need to send two packets
//1) Remove item from original inventory
//2) Add item with ID to "equipped" inventory
@@ -171,6 +189,11 @@ public class ServerEquipState implements BehaviorTree {
}
}
+ /**
+ * Gets an equip point by its name
+ * @param name The name of the equip point
+ * @return The equip point if it exists, null otherwise
+ */
public EquipPoint getEquipPoint(String name){
for(EquipPoint point : equipPoints){
if(point.getEquipPointId().equals(name)){
@@ -180,6 +203,11 @@ public class ServerEquipState implements BehaviorTree {
return null;
}
+ /**
+ * Gets the item equipped at a point
+ * @param point The point id
+ * @return The item if it exists, null otherwise
+ */
public Entity getEquippedItemAtPoint(String point){
return equipMap.get(point);
}
@@ -223,6 +251,10 @@ public class ServerEquipState implements BehaviorTree {
// }
// }
+ /**
+ * Commands the equip state to unequip an item at a given equip point
+ * @param pointId The equip point
+ */
public void commandAttemptUnequip(String pointId){
boolean hasEquipped = hasEquippedAtPoint(pointId);
if(hasEquipped){
@@ -278,10 +310,17 @@ public class ServerEquipState implements BehaviorTree {
// inventory.addItem(item);
}
+ /**
+ * Performs the transform to unequip an item from an equip point
+ * @param pointId The equip point id
+ */
public void serverTransformUnequipPoint(String pointId){
Entity equipped = equipMap.remove(pointId);
if(equipped != null){
boolean targetHasWhitelist = ItemUtils.hasEquipList(equipped);
+
+ //
+ //Visual transforms
if(targetHasWhitelist){
//have to do fancy mesh removal nonsense
//basically the reverse of below
@@ -319,13 +358,50 @@ public class ServerEquipState implements BehaviorTree {
AttachUtils.serverDetatchEntityFromEntityAtBone(parent, equipped);
EntityUtils.cleanUpEntity(equipped);
}
+
+ //
+ //update block state based on what we have equipped
+ this.updateBlockVariant();
}
}
+ /**
+ * Gets whether an item is equipped at a point or not
+ * @param point THe point to check
+ * @return true if an item is equipped at the point, false otherwise
+ */
public boolean hasEquippedAtPoint(String point){
return equipMap.containsKey(point);
}
+ /**
+ * Updates the server block variant based on what item is equipped
+ */
+ private void updateBlockVariant(){
+ ServerBlockTree blockTree = ServerBlockTree.getServerBlockTree(parent);
+ if(blockTree != null){
+
+ List pointsThatCanBlock = new LinkedList();
+ for(EquipPoint point : equipPoints){
+ if(point.getCanBlock()){
+ pointsThatCanBlock.add(point);
+ }
+ }
+
+ BlockSystem blockData = blockTree.getBlockSystem();
+ for(EquipPoint point : pointsThatCanBlock){
+ Entity item = getEquippedItemAtPoint(point.getEquipPointId());
+ if(item != null){
+ BlockVariant blockVariant = blockData.getVariantForPointWithItem(point.getEquipPointId(),ItemUtils.getEquipClass(item));
+
+ //TODO: refactor to allow sending more than one variant at a time
+ //ie if you have two items equipped and you want to block with both
+ blockTree.setCurrentBlockVariant(blockVariant.getVariantId());
+ }
+ }
+ }
+ }
+
@Override
public void simulate(float deltaTime) {
}
diff --git a/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java b/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java
index 3f1a7197..51ce5c25 100644
--- a/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java
+++ b/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java
@@ -215,7 +215,7 @@ public class ServerGravityTree implements BehaviorTree {
public void setState(GravityTreeState state){
this.state = state;
int value = ClientGravityTree.getGravityTreeStateEnumAsShort(state);
- DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 5, 7, value));
+ DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 7, 11, value));
}
/**
* (initially) Automatically generated
diff --git a/src/main/java/electrosphere/entity/state/idle/ClientIdleTree.java b/src/main/java/electrosphere/entity/state/idle/ClientIdleTree.java
index cc567f65..6054f1d3 100644
--- a/src/main/java/electrosphere/entity/state/idle/ClientIdleTree.java
+++ b/src/main/java/electrosphere/entity/state/idle/ClientIdleTree.java
@@ -215,4 +215,14 @@ public class ClientIdleTree implements BehaviorTree {
public void setState(IdleTreeState state){
this.state = state;
}
+ /**
+ *
+ * Gets the ClientIdleTree of the entity
+ *
+ * @param entity the entity
+ * @return The ClientIdleTree
+ */
+ public static ClientIdleTree getClientIdleTree(Entity entity){
+ return (ClientIdleTree)entity.getData(EntityDataStrings.TREE_IDLE);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/electrosphere/entity/state/idle/ServerIdleTree.java b/src/main/java/electrosphere/entity/state/idle/ServerIdleTree.java
index 5867cd92..a58fb8ac 100644
--- a/src/main/java/electrosphere/entity/state/idle/ServerIdleTree.java
+++ b/src/main/java/electrosphere/entity/state/idle/ServerIdleTree.java
@@ -190,7 +190,7 @@ public class ServerIdleTree implements BehaviorTree {
public void setState(IdleTreeState state){
this.state = state;
int value = ClientIdleTree.getIdleTreeStateEnumAsShort(state);
- DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 7, 9, value));
+ DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 9, 13, value));
}
/**
diff --git a/src/main/java/electrosphere/entity/state/ironsight/IronSightTree.java b/src/main/java/electrosphere/entity/state/ironsight/IronSightTree.java
deleted file mode 100644
index 6207052d..00000000
--- a/src/main/java/electrosphere/entity/state/ironsight/IronSightTree.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package electrosphere.entity.state.ironsight;
-
-import org.joml.Vector3f;
-
-import electrosphere.engine.Globals;
-import electrosphere.entity.Entity;
-import electrosphere.entity.EntityDataStrings;
-import electrosphere.entity.btree.BehaviorTree;
-import electrosphere.entity.types.camera.CameraEntityUtils;
-
-public class IronSightTree implements BehaviorTree {
-
- static enum IronSightTreeState {
- ACTIVE,
- INACTIVE,
- }
-
- IronSightTreeState state = IronSightTreeState.INACTIVE;
- boolean cameraZoomedIn = false;
-
- float regularRadius = 1.0f;
- float zoomedInRadius = 0.1f;
- Vector3f offcenterOffset = new Vector3f(-0.1f,1,0);
-
-
- public void start(){
- state = IronSightTreeState.ACTIVE;
- }
-
- public void release(){
- state = IronSightTreeState.INACTIVE;
- }
-
- @Override
- public void simulate(float deltaTime) {
- switch(state){
- case ACTIVE:
- if(!cameraZoomedIn){
- cameraZoomedIn = true;
- CameraEntityUtils.setOrbitalCameraDistance(Globals.playerCamera, zoomedInRadius);
- Globals.cameraHandler.updateRadialOffset(new Vector3f(0,1,0.5f));
- Globals.cameraHandler.updateGlobalCamera();
- }
- break;
- case INACTIVE:
- if(cameraZoomedIn){
- cameraZoomedIn = false;
- CameraEntityUtils.setOrbitalCameraDistance(Globals.playerCamera, regularRadius);
- Globals.cameraHandler.updateRadialOffset(new Vector3f(0,1,0));
- Globals.cameraHandler.updateGlobalCamera();
- }
- break;
- }
- }
-
- public static IronSightTree getIronSightTree(Entity creature){
- Object rVal;
- if((rVal = creature.getData(EntityDataStrings.IRON_SIGHT_TREE)) != null && rVal instanceof IronSightTree){
- return (IronSightTree) rVal;
- }
- return null;
- }
-
- public static void attachIronSightTree(Entity player){
- IronSightTree ironSightTree = new IronSightTree();
- player.putData(EntityDataStrings.IRON_SIGHT_TREE, ironSightTree);
- Globals.clientSceneWrapper.getScene().registerBehaviorTree(ironSightTree);
- }
-
-}
diff --git a/src/main/java/electrosphere/entity/state/movement/groundmove/ServerGroundMovementTree.java b/src/main/java/electrosphere/entity/state/movement/groundmove/ServerGroundMovementTree.java
index d2ff7452..fbe2e500 100644
--- a/src/main/java/electrosphere/entity/state/movement/groundmove/ServerGroundMovementTree.java
+++ b/src/main/java/electrosphere/entity/state/movement/groundmove/ServerGroundMovementTree.java
@@ -1,6 +1,8 @@
package electrosphere.entity.state.movement.groundmove;
+import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
+
import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
@@ -676,7 +678,7 @@ public class ServerGroundMovementTree implements BehaviorTree {
public void setFacing(MovementRelativeFacing facing){
this.facing = facing;
int value = ClientGroundMovementTree.getMovementRelativeFacingEnumAsShort(facing);
- DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 9, 11, value));
+ DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 11, 15, value));
}
/**
diff --git a/src/main/java/electrosphere/entity/types/attach/AttachUtils.java b/src/main/java/electrosphere/entity/types/attach/AttachUtils.java
index 35affb4c..07c34f89 100644
--- a/src/main/java/electrosphere/entity/types/attach/AttachUtils.java
+++ b/src/main/java/electrosphere/entity/types/attach/AttachUtils.java
@@ -540,18 +540,42 @@ public class AttachUtils {
return (Matrix4f)e.getData(EntityDataStrings.ATTACH_TRANSFORM);
}
+ /**
+ * Checks if the parent entity has attached child entities
+ * @param e The parent entity
+ * @return true if there are attached child entities, false otherwise
+ */
public static boolean hasChildren(Entity e){
return e.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST) && !getChildrenList(e).isEmpty();
}
+ /**
+ * Gets the attached entity's posiiton offset
+ * @param e The attached entity
+ * @return The position offset
+ */
public static Vector3d getAttachPositionOffset(Entity e){
return (Vector3d)e.getData(EntityDataStrings.ATTACH_POSITION_OFFSET);
}
- public static LinkedList getChildrenList(Entity e){
- return (LinkedList)e.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
+ /**
+ * Gets the list of entities attached to this parent entity
+ *
+ * NOTE: This can return an empty list of an entity has been attached to this one prior
+ * EVEN if it has since been unattached
+ *
+ * @param parentEntity
+ * @return The list of entities that are attached to this parent entity, or null if undefined
+ */
+ public static LinkedList getChildrenList(Entity parentEntity){
+ return (LinkedList)parentEntity.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
}
+ /**
+ * Gets the equip point's rotation offset in quaterniond form
+ * @param values The list of raw float values
+ * @return The quaterniond containing those values or an identity quaterniond if no such values exist
+ */
public static Quaterniond getEquipPointRotationOffset(List values){
if(values.size() > 0){
return new Quaterniond(values.get(0),values.get(1),values.get(2),values.get(3));
diff --git a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java
index ce0b26b2..0a73a89d 100644
--- a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java
+++ b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java
@@ -24,6 +24,8 @@ import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.attack.ClientAttackTree;
import electrosphere.entity.state.attack.ServerAttackTree;
import electrosphere.entity.state.attack.ShooterTree;
+import electrosphere.entity.state.block.ClientBlockTree;
+import electrosphere.entity.state.block.ServerBlockTree;
import electrosphere.entity.state.collidable.ClientCollidableTree;
import electrosphere.entity.state.collidable.ServerCollidableTree;
import electrosphere.entity.state.equip.ClientEquipState;
@@ -229,6 +231,9 @@ public class CreatureUtils {
ClientEquipState.attachTree(rVal, rawType.getEquipPoints());
rVal.putData(EntityDataStrings.EQUIP_INVENTORY, RelationalInventoryState.buildRelationalInventoryStateFromEquipList(rawType.getEquipPoints()));
}
+ if(rawType.getBlockSystem() != null){
+ ClientBlockTree.attachTree(rVal, rawType.getBlockSystem());
+ }
for(String token : rawType.getTokens()){
switch(token){
case "BLENDER_TRANSFORM":
@@ -517,6 +522,9 @@ public class CreatureUtils {
ServerEquipState.setEquipState(rVal, new ServerEquipState(rVal,rawType.getEquipPoints()));
rVal.putData(EntityDataStrings.EQUIP_INVENTORY, RelationalInventoryState.buildRelationalInventoryStateFromEquipList(rawType.getEquipPoints()));
}
+ if(rawType.getBlockSystem() != null){
+ ServerBlockTree.attachTree(rVal, rawType.getBlockSystem());
+ }
for(String token : rawType.getTokens()){
switch(token){
case "BLENDER_TRANSFORM": {
diff --git a/src/main/java/electrosphere/game/data/creature/type/CreatureType.java b/src/main/java/electrosphere/game/data/creature/type/CreatureType.java
index 9d92b50c..8aa4799f 100644
--- a/src/main/java/electrosphere/game/data/creature/type/CreatureType.java
+++ b/src/main/java/electrosphere/game/data/creature/type/CreatureType.java
@@ -4,6 +4,7 @@ import electrosphere.game.data.collidable.CollidableTemplate;
import electrosphere.game.data.collidable.HitboxData;
import electrosphere.game.data.creature.type.attack.AttackMove;
import electrosphere.game.data.creature.type.attack.AttackMoveResolver;
+import electrosphere.game.data.creature.type.block.BlockSystem;
import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.game.data.creature.type.movement.MovementSystem;
import electrosphere.game.data.creature.type.rotator.RotatorSystem;
@@ -29,6 +30,7 @@ public class CreatureType {
String modelPath;
ViewModelData viewModelData;
IdleData idleData;
+ BlockSystem blockSystem;
AttackMoveResolver attackMoveResolver;
@@ -95,6 +97,10 @@ public class CreatureType {
public IdleData getIdleData(){
return idleData;
}
+
+ public BlockSystem getBlockSystem(){
+ return blockSystem;
+ }
}
diff --git a/src/main/java/electrosphere/game/data/creature/type/block/BlockSystem.java b/src/main/java/electrosphere/game/data/creature/type/block/BlockSystem.java
new file mode 100644
index 00000000..1c8df725
--- /dev/null
+++ b/src/main/java/electrosphere/game/data/creature/type/block/BlockSystem.java
@@ -0,0 +1,56 @@
+package electrosphere.game.data.creature.type.block;
+
+import java.util.List;
+
+/**
+ * Stores data related to an entity blocking attacks
+ */
+public class BlockSystem {
+
+ //blocking with a weapon equipped in the right hand
+ //NOTE: the names provided here should line up with the actual field names on this object
+ public static final String BLOCK_VARIANT_WEAPON_RIGHT = "blockWeaponRight";
+
+ //the list of block variants
+ List variants;
+
+ /**
+ * Gets the list of block variants
+ * @return the list
+ */
+ public List getAllVariants(){
+ return variants;
+ }
+
+ /**
+ * Gets a block variant from its variant string
+ * @param variantString The variant string
+ * @return The block variant if it exists, null otherwise
+ */
+ public BlockVariant getBlockVariant(String variantString){
+ for(BlockVariant variant : variants){
+ if(variant.variantId.equals(variantString)){
+ return variant;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the block variant that is default for the provided equip point when the provided item class is equipped to that point
+ * @param equipPoint The equip point
+ * @param itemClass The item class
+ * @return The block variant if it exists, null otherwise
+ */
+ public BlockVariant getVariantForPointWithItem(String equipPoint, String itemClass){
+ for(BlockVariant variant : variants){
+ for(VariantDefaults variantDefault : variant.getDefaults()){
+ if(variantDefault.equipPoint.equals(equipPoint) && variantDefault.itemClassEquipped.equals(itemClass)){
+ return variant;
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/electrosphere/game/data/creature/type/block/BlockVariant.java b/src/main/java/electrosphere/game/data/creature/type/block/BlockVariant.java
new file mode 100644
index 00000000..2d87a748
--- /dev/null
+++ b/src/main/java/electrosphere/game/data/creature/type/block/BlockVariant.java
@@ -0,0 +1,67 @@
+package electrosphere.game.data.creature.type.block;
+
+import java.util.List;
+
+/**
+ * A variant of data that can be loaded into the block system. Variants are for different types of equip states.
+ * IE: holding just a sword in your right hand will have a different block animation vs a shield in your right
+ * hand vs two handing a sword with your right hand.
+ */
+public class BlockVariant {
+
+ //The id of the block variant
+ String variantId;
+
+ //the animation to play when winding up
+ String windUpAnimation;
+
+ //the main animation to play while blocking
+ String mainAnimation;
+
+ //the animation to play when cooling down
+ String cooldownAnimation;
+
+ //the list of default equipment cases that this variant should be used for
+ List defaults;
+
+ /**
+ * The id of the block variant
+ * @return
+ */
+ public String getVariantId(){
+ return variantId;
+ }
+
+ /**
+ * The animation to play when winding up
+ * @return
+ */
+ public String getWindUpAnimation(){
+ return windUpAnimation;
+ }
+
+ /**
+ * The main animation to play while blocking
+ * @return
+ */
+ public String getMainAnimation(){
+ return mainAnimation;
+ }
+
+ /**
+ * The animation to play when cooling down
+ * @return
+ */
+ public String getCooldownAnimation(){
+ return cooldownAnimation;
+ }
+
+ /**
+ * the list of default equipment cases that this variant should be used for
+ * @return
+ */
+ public List getDefaults(){
+ return defaults;
+ }
+
+}
diff --git a/src/main/java/electrosphere/game/data/creature/type/block/VariantDefaults.java b/src/main/java/electrosphere/game/data/creature/type/block/VariantDefaults.java
new file mode 100644
index 00000000..ced619ed
--- /dev/null
+++ b/src/main/java/electrosphere/game/data/creature/type/block/VariantDefaults.java
@@ -0,0 +1,34 @@
+package electrosphere.game.data.creature.type.block;
+
+/**
+ * Equip point cases that this variant is used as the default for
+ * IE, if you create a variant default for "handRight, weapon",
+ * that means this should be used as the default variant for when
+ * the handRight equip point has a weapon equipped and the block
+ * tree is triggered
+ */
+public class VariantDefaults {
+
+ //the equip point
+ String equipPoint;
+
+ //the class of item equipped to that equip point
+ String itemClassEquipped;
+
+ /**
+ * the equip point
+ * @return
+ */
+ public String getEquipPoint(){
+ return equipPoint;
+ }
+
+ /**
+ * the class of item equipped to that equip point
+ * @return
+ */
+ public String getItemClassEquipped(){
+ return itemClassEquipped;
+ }
+
+}
diff --git a/src/main/java/electrosphere/game/data/creature/type/equip/EquipPoint.java b/src/main/java/electrosphere/game/data/creature/type/equip/EquipPoint.java
index e48fbc63..7e0fd4de 100644
--- a/src/main/java/electrosphere/game/data/creature/type/equip/EquipPoint.java
+++ b/src/main/java/electrosphere/game/data/creature/type/equip/EquipPoint.java
@@ -17,6 +17,8 @@ public class EquipPoint {
List offsetVector;
//the rotation to apply to the items that are attached to the bone
List offsetRotation;
+ //signals that this equip point can block
+ boolean canBlock;
//the equip classes that are whitelisted for this equip point
List equipClassWhitelist;
@@ -68,6 +70,14 @@ public class EquipPoint {
this.offsetRotation = offsetRotation;
}
+ /**
+ * Signals that this equip point can block
+ * @return true if can block, false otherwise
+ */
+ public boolean getCanBlock(){
+ return canBlock;
+ }
+
/**
* Gets the equip classes that are whitelisted for this equip point
* @return the classes
diff --git a/src/main/java/electrosphere/game/data/item/type/Item.java b/src/main/java/electrosphere/game/data/item/type/Item.java
index eb95a696..c9b44ee5 100644
--- a/src/main/java/electrosphere/game/data/item/type/Item.java
+++ b/src/main/java/electrosphere/game/data/item/type/Item.java
@@ -4,50 +4,97 @@ import electrosphere.game.data.collidable.CollidableTemplate;
import java.util.List;
+/**
+ * Data on a given item
+ */
public class Item {
+ //the id of the item
String itemId;
+ //the model path of the item
String modelPath;
+ //tokens associated with this item type
List tokens;
+ //the collidable data for the item
CollidableTemplate collidable;
+ //the equip whitelist for this item (what creatures can equip this item?)
List equipWhitelist;
+ //the idle animation for the item
String idleAnim;
+ //the path for the icon texture for this item
String iconPath;
+ //the class of item
String equipClass;
+ //weapon data for this item if it is an item
WeaponData weaponData;
+ /**
+ * the id of the item
+ * @return
+ */
public String getItemId() {
return itemId;
}
+ /**
+ * the model path of the item
+ * @return
+ */
public String getModelPath() {
return modelPath;
}
+ /*
+ * tokens associated with this item type
+ */
public List getTokens() {
return tokens;
}
+ /**
+ * the collidable data for the item
+ * @return
+ */
public CollidableTemplate getCollidable(){
return collidable;
}
+ /**
+ * the equip whitelist for this item (what creatures can equip this item?)
+ * @return
+ */
public List getEquipWhitelist(){
return equipWhitelist;
}
+ /**
+ * the idle animation for the item
+ * @return
+ */
public String getIdleAnim(){
return idleAnim;
}
+ /**
+ * the path for the icon texture for this item
+ * @return
+ */
public String getIconPath(){
return iconPath;
}
+ /**
+ * the class of item
+ * @return
+ */
public String getEquipClass(){
return equipClass;
}
+ /**
+ * weapon data for this item if it is an item
+ * @return
+ */
public WeaponData getWeaponData(){
return weaponData;
}
diff --git a/src/main/java/electrosphere/net/client/protocol/ClientProtocol.java b/src/main/java/electrosphere/net/client/protocol/ClientProtocol.java
index ae20aa1c..849c9b92 100644
--- a/src/main/java/electrosphere/net/client/protocol/ClientProtocol.java
+++ b/src/main/java/electrosphere/net/client/protocol/ClientProtocol.java
@@ -1,14 +1,6 @@
package electrosphere.net.client.protocol;
-import electrosphere.client.scene.ClientWorldData;
import electrosphere.engine.Globals;
-import electrosphere.engine.Main;
-import electrosphere.entity.Entity;
-import electrosphere.entity.EntityUtils;
-import electrosphere.entity.types.creature.CreatureUtils;
-import electrosphere.entity.types.attach.AttachUtils;
-import electrosphere.entity.types.item.ItemUtils;
-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;
@@ -19,8 +11,6 @@ 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;
public class ClientProtocol {
diff --git a/src/main/java/electrosphere/net/client/protocol/InventoryProtocol.java b/src/main/java/electrosphere/net/client/protocol/InventoryProtocol.java
index b86d70dc..9737b5af 100644
--- a/src/main/java/electrosphere/net/client/protocol/InventoryProtocol.java
+++ b/src/main/java/electrosphere/net/client/protocol/InventoryProtocol.java
@@ -5,7 +5,6 @@ import electrosphere.entity.Entity;
import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.inventory.ClientInventoryState;
import electrosphere.entity.state.inventory.InventoryUtils;
-import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.InventoryMessage;
@@ -70,6 +69,7 @@ public class InventoryProtocol {
}
}
break;
+ case CLIENTREQUESTPERFORMITEMACTION:
case CLIENTREQUESTUNEQUIPITEM:
case CLIENTREQUESTEQUIPITEM:
//silently ignore
diff --git a/src/main/java/electrosphere/net/parser/net/message/InventoryMessage.java b/src/main/java/electrosphere/net/parser/net/message/InventoryMessage.java
index 9f2e9d69..a26c647a 100644
--- a/src/main/java/electrosphere/net/parser/net/message/InventoryMessage.java
+++ b/src/main/java/electrosphere/net/parser/net/message/InventoryMessage.java
@@ -15,6 +15,7 @@ public class InventoryMessage extends NetworkMessage {
SERVERCOMMANDEQUIPITEM,
SERVERCOMMANDUNEQUIPITEM,
CLIENTREQUESTUNEQUIPITEM,
+ CLIENTREQUESTPERFORMITEMACTION,
}
InventoryMessageType messageType;
@@ -23,6 +24,8 @@ public class InventoryMessage extends NetworkMessage {
int entityId;
int equipperId;
int containerType;
+ int itemActionCode;
+ int itemActionCodeState;
InventoryMessage(InventoryMessageType messageType){
this.type = MessageType.INVENTORY_MESSAGE;
@@ -73,6 +76,22 @@ public class InventoryMessage extends NetworkMessage {
this.containerType = containerType;
}
+ public int getitemActionCode() {
+ return itemActionCode;
+ }
+
+ public void setitemActionCode(int itemActionCode) {
+ this.itemActionCode = itemActionCode;
+ }
+
+ public int getitemActionCodeState() {
+ return itemActionCodeState;
+ }
+
+ public void setitemActionCodeState(int itemActionCodeState) {
+ this.itemActionCodeState = itemActionCodeState;
+ }
+
static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteBuffer.read(2);
}
@@ -97,6 +116,8 @@ public class InventoryMessage extends NetworkMessage {
return InventoryMessage.canParseserverCommandUnequipItemMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM:
return InventoryMessage.canParseclientRequestUnequipItemMessage(byteBuffer);
+ case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION:
+ return InventoryMessage.canParseclientRequestPerformItemActionMessage(byteBuffer);
}
return false;
}
@@ -363,6 +384,49 @@ public class InventoryMessage extends NetworkMessage {
return rVal;
}
+ public static boolean canParseclientRequestPerformItemActionMessage(CircularByteBuffer byteBuffer){
+ int currentStreamLength = byteBuffer.getRemaining();
+ List temporaryByteQueue = new LinkedList();
+ int equipPointIdSize = 0;
+ if(currentStreamLength < 6){
+ return false;
+ } else {
+ temporaryByteQueue.add(byteBuffer.peek(2 + 0));
+ temporaryByteQueue.add(byteBuffer.peek(2 + 1));
+ temporaryByteQueue.add(byteBuffer.peek(2 + 2));
+ temporaryByteQueue.add(byteBuffer.peek(2 + 3));
+ equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
+ }
+ if(currentStreamLength < 6 + equipPointIdSize){
+ return false;
+ }
+ if(currentStreamLength < 10 + equipPointIdSize){
+ return false;
+ }
+ if(currentStreamLength < 14 + equipPointIdSize){
+ return false;
+ }
+ return true;
+ }
+
+ public static InventoryMessage parseclientRequestPerformItemActionMessage(CircularByteBuffer byteBuffer){
+ InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTPERFORMITEMACTION);
+ stripPacketHeader(byteBuffer);
+ rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
+ rVal.setitemActionCode(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
+ rVal.setitemActionCodeState(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
+ return rVal;
+ }
+
+ public static InventoryMessage constructclientRequestPerformItemActionMessage(String equipPointId,int itemActionCode,int itemActionCodeState){
+ InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTPERFORMITEMACTION);
+ rVal.setequipPointId(equipPointId);
+ rVal.setitemActionCode(itemActionCode);
+ rVal.setitemActionCodeState(itemActionCodeState);
+ rVal.serialize();
+ return rVal;
+ }
+
@Override
void serialize(){
byte[] intValues = new byte[8];
@@ -505,6 +569,29 @@ public class InventoryMessage extends NetworkMessage {
rawBytes[6+i] = stringBytes[i];
}
break;
+ case CLIENTREQUESTPERFORMITEMACTION:
+ rawBytes = new byte[2+4+equipPointId.length()+4+4];
+ //message header
+ rawBytes[0] = TypeBytes.MESSAGE_TYPE_INVENTORY;
+ //entity messaage header
+ rawBytes[1] = TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION;
+ intValues = ByteStreamUtils.serializeIntToBytes(equipPointId.length());
+ for(int i = 0; i < 4; i++){
+ rawBytes[2+i] = intValues[i];
+ }
+ stringBytes = equipPointId.getBytes();
+ for(int i = 0; i < equipPointId.length(); i++){
+ rawBytes[6+i] = stringBytes[i];
+ }
+ intValues = ByteStreamUtils.serializeIntToBytes(itemActionCode);
+ for(int i = 0; i < 4; i++){
+ rawBytes[6+equipPointId.length()+i] = intValues[i];
+ }
+ intValues = ByteStreamUtils.serializeIntToBytes(itemActionCodeState);
+ for(int i = 0; i < 4; i++){
+ rawBytes[10+equipPointId.length()+i] = intValues[i];
+ }
+ break;
}
serialized = true;
}
diff --git a/src/main/java/electrosphere/net/parser/net/message/NetworkMessage.java b/src/main/java/electrosphere/net/parser/net/message/NetworkMessage.java
index a60edba8..49e4cfb6 100644
--- a/src/main/java/electrosphere/net/parser/net/message/NetworkMessage.java
+++ b/src/main/java/electrosphere/net/parser/net/message/NetworkMessage.java
@@ -311,6 +311,11 @@ SYNCHRONIZATION_MESSAGE,
rVal = InventoryMessage.parseclientRequestUnequipItemMessage(byteBuffer);
}
break;
+ case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION:
+ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
+ rVal = InventoryMessage.parseclientRequestPerformItemActionMessage(byteBuffer);
+ }
+ break;
}
break;
case TypeBytes.MESSAGE_TYPE_SYNCHRONIZATION:
diff --git a/src/main/java/electrosphere/net/parser/net/message/TypeBytes.java b/src/main/java/electrosphere/net/parser/net/message/TypeBytes.java
index c72e05ba..c6be057e 100644
--- a/src/main/java/electrosphere/net/parser/net/message/TypeBytes.java
+++ b/src/main/java/electrosphere/net/parser/net/message/TypeBytes.java
@@ -133,6 +133,7 @@ Message categories
public static final byte INVENTORY_MESSAGE_TYPE_SERVERCOMMANDEQUIPITEM = 4;
public static final byte INVENTORY_MESSAGE_TYPE_SERVERCOMMANDUNEQUIPITEM = 5;
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM = 6;
+ public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION = 7;
/*
Inventory packet sizes
*/
diff --git a/src/main/java/electrosphere/net/server/Server.java b/src/main/java/electrosphere/net/server/Server.java
index 3c5fc8e0..5b65445d 100644
--- a/src/main/java/electrosphere/net/server/Server.java
+++ b/src/main/java/electrosphere/net/server/Server.java
@@ -5,41 +5,45 @@ import electrosphere.engine.Main;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.NetUtils;
import electrosphere.net.parser.net.message.NetworkMessage;
-import electrosphere.server.saves.SaveUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.BindException;
-import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
/**
- *
- * @author amaterasu
+ * Lowest level networking class for the server
*/
public class Server implements Runnable{
+ //the port the server is running on
int port;
+ //the socket for the server
ServerSocket serverSocket;
+ //the map of ip->connection handler
Map clientMap = new HashMap();
+ /**
+ * Inits the server
+ */
void initServer(){
// clientMap = new HashMap();
}
-
+ /**
+ * Constructor
+ * @param port The port to run the server on
+ */
public Server(int port){
this.port = port;
}
@@ -76,7 +80,19 @@ public class Server implements Runnable{
}
}
}
+
+ /**
+ * Synchronously handles queued packets for each client connection
+ */
+ public void synchronousPacketHandling(){
+ for(ServerConnectionHandler connectionHandler : this.clientMap.values()){
+ connectionHandler.handleSynchronousPacketQueue();
+ }
+ }
+ /**
+ * Closes the server socket
+ */
public void close(){
try {
if(serverSocket != null){
@@ -87,6 +103,10 @@ public class Server implements Runnable{
}
}
+ /**
+ * Broadcasts a message to all clients
+ * @param message The message to broadcast
+ */
public void broadcastMessage(NetworkMessage message){
for(ServerConnectionHandler client : clientMap.values()){
if(Globals.clientPlayer == null || client.playerID != Globals.clientPlayer.getId()){
@@ -95,6 +115,12 @@ public class Server implements Runnable{
}
}
+ /**
+ * Adds a connection created manually by two streams instead of receiving the streams from the server socket
+ * @param serverInputStream The input stream
+ * @param serverOutputStream The output stream
+ * @return The connection object for the provided streams
+ */
public ServerConnectionHandler addLocalPlayer(InputStream serverInputStream, OutputStream serverOutputStream){
ServerConnectionHandler newClient = new ServerConnectionHandler(serverInputStream,serverOutputStream);
clientMap.put("127.0.0.1", newClient);
diff --git a/src/main/java/electrosphere/net/server/ServerConnectionHandler.java b/src/main/java/electrosphere/net/server/ServerConnectionHandler.java
index 2762c752..1a6d3087 100644
--- a/src/main/java/electrosphere/net/server/ServerConnectionHandler.java
+++ b/src/main/java/electrosphere/net/server/ServerConnectionHandler.java
@@ -1,21 +1,12 @@
package electrosphere.net.server;
import electrosphere.entity.types.creature.CreatureTemplate;
-import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.engine.Globals;
import electrosphere.engine.Main;
-import electrosphere.entity.Entity;
-import electrosphere.entity.EntityUtils;
-import electrosphere.entity.state.ironsight.IronSightTree;
-import electrosphere.entity.types.item.ItemUtils;
-import electrosphere.entity.types.attach.AttachUtils;
-import electrosphere.entity.types.collision.CollisionObjUtils;
+import electrosphere.entity.ServerEntityUtils;
import electrosphere.logger.LoggerInterface;
-import electrosphere.net.NetUtils;
import electrosphere.net.parser.net.message.AuthMessage;
-import electrosphere.net.parser.net.message.EntityMessage;
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.raw.NetworkParser;
import electrosphere.net.server.player.Player;
@@ -24,30 +15,20 @@ import electrosphere.net.server.protocol.ServerProtocol;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.math.BigInteger;
import java.net.Socket;
import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.security.spec.RSAKeyGenParameterSpec;
import java.util.LinkedList;
import java.util.List;
-import java.util.Properties;
-import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.joml.Vector3d;
-import org.joml.Vector3f;
/**
- *
- * @author satellite
+ * A connection to the server
*/
public class ServerConnectionHandler implements Runnable {
+ //the player id associated with this connection
static int playerIdIncrementer = 0;
//local carrier variables
@@ -55,17 +36,30 @@ public class ServerConnectionHandler implements Runnable {
//socket carrier variables
Socket socket;
+
+ //the streams for the connection
// CryptoInputStream inputStream;
// CryptoOutputStream outputStream;
InputStream inputStream;
OutputStream outputStream;
- boolean initialized;
- boolean isAuthenticated = false;
+
+ //the network parser for the streams
NetworkParser networkParser;
+
+ //initialized status
+ boolean initialized;
+ //authentication status
+ boolean isAuthenticated = false;
+
+ //the player id
int playerID;
- int playerCharacterID;
+ //the player's entity id
+ int playerEntityID;
+
+ //the creature template associated with this player
CreatureTemplate currentCreatureTemplate;
+ //the server protocol object associated with this player
ServerProtocol serverProtocol;
//thresholds for determining when to send pings and when a client has disconnected
@@ -82,13 +76,27 @@ public class ServerConnectionHandler implements Runnable {
String netMonitorHandle;
//Used to copy messages from network parser to NetMonitor
List netMonitorCache = new LinkedList();
+
+ //the lock used for synchronizing the synchronous message queue
+ Semaphore synchronousMessageLock = new Semaphore(1);
+ //the queue of synchonous network messages
+ List synchronousMessageQueue = new CopyOnWriteArrayList();
+ /**
+ * Constructs a connection from a socket
+ * @param socket the socket
+ */
public ServerConnectionHandler(Socket socket) {
this.socket = socket;
playerID = getNewPlayerID();
LoggerInterface.loggerNetworking.INFO("Player ID: " + playerID);
}
+ /**
+ * Constructs a connection from an arbitrary input and output stream
+ * @param serverInputStream the input stream
+ * @param serverOutputStream the output stream
+ */
public ServerConnectionHandler(InputStream serverInputStream, OutputStream serverOutputStream){
this.local = true;
playerID = getNewPlayerID();
@@ -114,6 +122,8 @@ public class ServerConnectionHandler implements Runnable {
} catch (SocketException ex) {
ex.printStackTrace();
}
+
+ //TODO: use this commented block of code as a reference for implementing encryption on top of the game connection
// final SecretKeySpec key = new SecretKeySpec(("1234567890123456").getBytes(),"AES");
// final Properties properties = new Properties();
// final RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(4096, BigInteger.probablePrime(4000, new Random()));
@@ -210,7 +220,13 @@ public class ServerConnectionHandler implements Runnable {
//ponder incoming messages
while(networkParser.hasIncomingMessaage()){
NetworkMessage message = networkParser.popIncomingMessage();
- serverProtocol.handleMessage(message);
+ 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();
+ }
}
if(Globals.netMonitor != null){
@@ -231,6 +247,18 @@ public class ServerConnectionHandler implements Runnable {
ex.printStackTrace();
}
}
+
+ /**
+ * Handles synchronous packets in the queue
+ */
+ public void handleSynchronousPacketQueue(){
+ synchronousMessageLock.acquireUninterruptibly();
+ for(NetworkMessage message : synchronousMessageQueue){
+ this.serverProtocol.handleSynchronousMessage(message);
+ }
+ synchronousMessageQueue.clear();
+ synchronousMessageLock.release();
+ }
public void setPlayerId(int id){
playerID = id;
@@ -245,12 +273,12 @@ public class ServerConnectionHandler implements Runnable {
return playerIdIncrementer;
}
- public void setPlayerCharacterId(int id){
- playerCharacterID = id;
+ public void setPlayerEntityId(int id){
+ playerEntityID = id;
}
- public int getPlayerCharacterId(){
- return playerCharacterID;
+ public int getPlayerEntityId(){
+ return playerEntityID;
}
public String getIPAddress(){
@@ -266,7 +294,7 @@ public class ServerConnectionHandler implements Runnable {
}
boolean isConnectionPlayerEntity(int id){
- return id == this.playerCharacterID;
+ return id == this.playerEntityID;
}
/**
@@ -303,13 +331,8 @@ public class ServerConnectionHandler implements Runnable {
}
//figure out what player we are
Player playerObject = Globals.playerManager.getPlayerFromId(getPlayerId());
- //get player entity & position
- Entity playerEntity = playerObject.getPlayerEntity();
- Vector3d position = EntityUtils.getPosition(playerEntity);
- //deregister entity
- EntityUtils.cleanUpEntity(playerObject.getPlayerEntity());
- //TODO: tell all clients to destroy the entity
- EntityUtils.cleanUpEntity(playerEntity);
+ //tell all clients to destroy the entity
+ ServerEntityUtils.destroyEntity(playerObject.getPlayerEntity());
}
}
diff --git a/src/main/java/electrosphere/net/server/protocol/AuthProtocol.java b/src/main/java/electrosphere/net/server/protocol/AuthProtocol.java
index 3c4807d8..29dcf2fc 100644
--- a/src/main/java/electrosphere/net/server/protocol/AuthProtocol.java
+++ b/src/main/java/electrosphere/net/server/protocol/AuthProtocol.java
@@ -39,4 +39,20 @@ public class AuthProtocol {
}
}
+ /**
+ * 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){
+ switch(message.getMessageSubtype()){
+ case AUTHDETAILS:
+ case AUTHFAILURE:
+ case AUTHREQUEST:
+ case AUTHSUCCESS:
+ //silently ignore
+ break;
+ }
+ }
+
}
diff --git a/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java b/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java
index ef65c795..8f29cb32 100644
--- a/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java
+++ b/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java
@@ -37,6 +37,25 @@ 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
diff --git a/src/main/java/electrosphere/net/server/protocol/EntityProtocol.java b/src/main/java/electrosphere/net/server/protocol/EntityProtocol.java
index e2842581..f96288e1 100644
--- a/src/main/java/electrosphere/net/server/protocol/EntityProtocol.java
+++ b/src/main/java/electrosphere/net/server/protocol/EntityProtocol.java
@@ -52,5 +52,29 @@ 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:
+ //silently ignore
+ break;
+ }
+ }
}
diff --git a/src/main/java/electrosphere/net/server/protocol/InventoryProtocol.java b/src/main/java/electrosphere/net/server/protocol/InventoryProtocol.java
index 4e8b9142..ea11b800 100644
--- a/src/main/java/electrosphere/net/server/protocol/InventoryProtocol.java
+++ b/src/main/java/electrosphere/net/server/protocol/InventoryProtocol.java
@@ -1,54 +1,88 @@
package electrosphere.net.server.protocol;
-import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
-import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.inventory.InventoryUtils;
-import electrosphere.entity.state.inventory.UnrelationalInventoryState;
-import electrosphere.entity.types.creature.CreatureUtils;
-import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.server.datacell.utils.EntityLookupUtils;
+import electrosphere.server.player.PlayerActions;
+/**
+ * Server protocol for dealing with inventory messages
+ */
public class InventoryProtocol {
+
+ //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;
- protected static void handleInventoryMessage(ServerConnectionHandler connectionHandler, InventoryMessage message){
- Entity characterEntity;
+ /**
+ * 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){
Entity target;
switch(message.getMessageSubtype()){
case ADDITEMTOINVENTORY:
LoggerInterface.loggerNetworking.DEBUG("[SERVER] ADD ITEM TO INVENTORY " + message.getentityId());
- target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerCharacterId());
+ target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
if(InventoryUtils.hasNaturalInventory(target)){
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
}
break;
case REMOVEITEMFROMINVENTORY:
LoggerInterface.loggerNetworking.DEBUG("[SERVER] REMOVE ITEM FROM INVENTORY " + message.getentityId());
- target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerCharacterId());
+ target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
if(InventoryUtils.hasNaturalInventory(target)){
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
}
break;
case CLIENTREQUESTEQUIPITEM:
LoggerInterface.loggerNetworking.DEBUG("[SERVER] REQUEST EQUIP ITEM " + message.getentityId());
- target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerCharacterId());
+ target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
if(InventoryUtils.hasNaturalInventory(target)){
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
}
break;
case CLIENTREQUESTUNEQUIPITEM:
LoggerInterface.loggerNetworking.DEBUG("[SERVER] REQUEST UNEQUIP ITEM " + message.getentityId());
- target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerCharacterId());
+ target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
if(InventoryUtils.hasNaturalInventory(target)){
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:
diff --git a/src/main/java/electrosphere/net/server/protocol/LoreProtocol.java b/src/main/java/electrosphere/net/server/protocol/LoreProtocol.java
index f1dd3e30..ae04b3b5 100644
--- a/src/main/java/electrosphere/net/server/protocol/LoreProtocol.java
+++ b/src/main/java/electrosphere/net/server/protocol/LoreProtocol.java
@@ -22,5 +22,19 @@ public class LoreProtocol {
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 handleSynchronousLoreMessage(ServerConnectionHandler connectionHandler, LoreMessage message){
+ switch(message.getMessageSubtype()){
+ case REQUESTRACES:
+ case RESPONSERACES:
+ //silently ignore
+ break;
+ }
+ }
}
diff --git a/src/main/java/electrosphere/net/server/protocol/PlayerProtocol.java b/src/main/java/electrosphere/net/server/protocol/PlayerProtocol.java
index ed997f7b..26fbac79 100644
--- a/src/main/java/electrosphere/net/server/protocol/PlayerProtocol.java
+++ b/src/main/java/electrosphere/net/server/protocol/PlayerProtocol.java
@@ -3,11 +3,36 @@ package electrosphere.net.server.protocol;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.server.ServerConnectionHandler;
+/**
+ * Player protocol handling
+ */
public class PlayerProtocol {
-
+ /**
+ * Handles a player network message
+ * @param connectionHandler The connection handler
+ * @param message The player message
+ */
protected static void handlePlayerMessage(ServerConnectionHandler connectionHandler, PlayerMessage message){
switch(message.getMessageSubtype()){
+ case SETINITIALDISCRETEPOSITION:
+ case SET_ID:
+ //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 handleSynchronousPlayerMessage(ServerConnectionHandler connectionHandler, PlayerMessage message){
+ switch(message.getMessageSubtype()){
+ case SETINITIALDISCRETEPOSITION:
+ case SET_ID:
+ //silently ignore
+ break;
}
}
diff --git a/src/main/java/electrosphere/net/server/protocol/ServerProtocol.java b/src/main/java/electrosphere/net/server/protocol/ServerProtocol.java
index 72513fb0..6d611cea 100644
--- a/src/main/java/electrosphere/net/server/protocol/ServerProtocol.java
+++ b/src/main/java/electrosphere/net/server/protocol/ServerProtocol.java
@@ -1,18 +1,6 @@
package electrosphere.net.server.protocol;
-import org.joml.Vector3f;
-
-import electrosphere.engine.Globals;
-import electrosphere.engine.Main;
-import electrosphere.entity.Entity;
-import electrosphere.entity.EntityUtils;
-import electrosphere.entity.state.ironsight.IronSightTree;
-import electrosphere.entity.types.attach.AttachUtils;
-import electrosphere.entity.types.collision.CollisionObjUtils;
-import electrosphere.entity.types.creature.CreatureUtils;
-import electrosphere.entity.types.item.ItemUtils;
import electrosphere.logger.LoggerInterface;
-import electrosphere.net.NetUtils;
import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.EntityMessage;
@@ -25,53 +13,110 @@ import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.parser.net.message.NetworkMessage.MessageType;
import electrosphere.net.parser.net.message.ServerMessage.ServerMessageType;
import electrosphere.net.server.ServerConnectionHandler;
-import electrosphere.net.server.player.Player;
-import electrosphere.server.terrain.manager.ServerTerrainChunk;
-import electrosphere.server.terrain.models.TerrainModification;
+/**
+ * The server's protocol for handling a message
+ */
public class ServerProtocol {
+ //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;
}
- public void handleMessage(NetworkMessage message){
+ /**
+ * 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:
+ case ENTITY_MESSAGE: {
EntityProtocol.handleEntityMessage(connectionHandler, (EntityMessage)message);
- break;
- case TERRAIN_MESSAGE:
+ } break;
+ case TERRAIN_MESSAGE: {
TerrainProtocol.handleTerrainMessage(connectionHandler, (TerrainMessage)message);
- break;
- case PLAYER_MESSAGE:
+ } break;
+ case PLAYER_MESSAGE: {
PlayerProtocol.handlePlayerMessage(connectionHandler, (PlayerMessage)message);
- break;
- case AUTH_MESSAGE:
+ } break;
+ case AUTH_MESSAGE: {
AuthProtocol.handleAuthenticationMessage(connectionHandler, (AuthMessage)message);
- break;
- case SERVER_MESSAGE:
+ } break;
+ case SERVER_MESSAGE: {
handleServerMessage((ServerMessage)message);
- break;
- case CHARACTER_MESSAGE:
+ } break;
+ case CHARACTER_MESSAGE: {
CharacterProtocol.handleCharacterMessage(connectionHandler, (CharacterMessage)message);
- break;
- case LORE_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;
- case INVENTORY_MESSAGE:
- InventoryProtocol.handleInventoryMessage(connectionHandler, (InventoryMessage)message);
+ }
+ 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){
switch(message.getMessageSubtype()){
case PING:
@@ -83,6 +128,20 @@ public class ServerProtocol {
}
}
+ /**
+ * 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){
+ switch(message.getMessageSubtype()){
+ case PING:
+ case PONG:
+ //silently ignore
+ break;
+ }
+ }
+
/**
* Print out the network message type, this only prints ping and pong if echoPings is true
*/
diff --git a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java
index ac481491..efd5b45f 100644
--- a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java
+++ b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java
@@ -6,20 +6,25 @@ import java.nio.IntBuffer;
import org.joml.Vector3d;
-import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.TerrainMessage;
-import electrosphere.net.server.Server;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.Realm;
import electrosphere.server.fluid.manager.ServerFluidChunk;
import electrosphere.server.terrain.editing.TerrainEditing;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
-import electrosphere.server.terrain.models.TerrainModification;
+/**
+ * Server handling for terrain network messages
+ */
public class TerrainProtocol {
+ /**
+ * Handles a terrain message
+ * @param connectionHandler The connection handler
+ * @param message The terrain message
+ */
protected static void handleTerrainMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){
switch(message.getMessageSubtype()){
case REQUESTMETADATA:
@@ -53,6 +58,36 @@ public class TerrainProtocol {
}
}
+ /**
+ * 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
+ * @param worldX the world x
+ * @param worldY the world y
+ * @param worldZ the world z
+ */
static void sendWorldSubChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ){
/*
int locationX,
@@ -200,6 +235,13 @@ public class TerrainProtocol {
}
+ /**
+ * Sends a fluid sub chunk to the client
+ * @param connectionHandler The connection handler
+ * @param worldX the world x
+ * @param worldY the world y
+ * @param worldZ the world z
+ */
static void sendWorldFluidSubChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ){
// System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY());
@@ -213,6 +255,10 @@ public class TerrainProtocol {
}
+ /**
+ * Sends world metadata to the client
+ * @param connectionHandler The connection handler
+ */
static void sendWorldMetadata(ServerConnectionHandler connectionHandler){
//world metadata
connectionHandler.addMessagetoOutgoingQueue(
@@ -233,7 +279,8 @@ public class TerrainProtocol {
* @param message The message containing the edit request
*/
static void attemptTerrainEdit(ServerConnectionHandler connectionHandler, TerrainMessage message){
- Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
+ // Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
+ throw new UnsupportedOperationException();
}
/**
diff --git a/src/main/java/electrosphere/net/synchronization/BehaviorTreeIdEnums.java b/src/main/java/electrosphere/net/synchronization/BehaviorTreeIdEnums.java
index 731a1339..29be61e2 100644
--- a/src/main/java/electrosphere/net/synchronization/BehaviorTreeIdEnums.java
+++ b/src/main/java/electrosphere/net/synchronization/BehaviorTreeIdEnums.java
@@ -7,13 +7,15 @@ public class BehaviorTreeIdEnums {
public static final int BTREE_CLIENTATTACKTREE_ID = 0;
public static final int BTREE_SERVERATTACKTREE_ID = 1;
- public static final int BTREE_CLIENTEQUIPSTATE_ID = 2;
- public static final int BTREE_SERVEREQUIPSTATE_ID = 3;
- public static final int BTREE_GRAVITY_ID = 4;
- public static final int BTREE_SERVERGRAVITY_ID = 5;
- public static final int BTREE_IDLE_ID = 6;
- public static final int BTREE_SERVERIDLE_ID = 7;
- public static final int BTREE_CLIENTGROUNDMOVEMENTTREE_ID = 8;
- public static final int BTREE_SERVERGROUNDMOVEMENTTREE_ID = 9;
+ public static final int BTREE_CLIENTBLOCKTREE_ID = 2;
+ public static final int BTREE_SERVERBLOCKTREE_ID = 3;
+ public static final int BTREE_CLIENTEQUIPSTATE_ID = 4;
+ public static final int BTREE_SERVEREQUIPSTATE_ID = 5;
+ public static final int BTREE_GRAVITY_ID = 6;
+ public static final int BTREE_SERVERGRAVITY_ID = 7;
+ public static final int BTREE_IDLE_ID = 8;
+ public static final int BTREE_SERVERIDLE_ID = 9;
+ public static final int BTREE_CLIENTGROUNDMOVEMENTTREE_ID = 10;
+ public static final int BTREE_SERVERGROUNDMOVEMENTTREE_ID = 11;
}
diff --git a/src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java b/src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java
index e9e0c233..f12efd62 100644
--- a/src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java
+++ b/src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java
@@ -1,6 +1,10 @@
package electrosphere.net.synchronization;
+import electrosphere.entity.state.block.ClientBlockTree;
+
+import electrosphere.entity.state.block.ServerBlockTree;
+
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
import electrosphere.entity.state.movement.groundmove.ServerGroundMovementTree;
@@ -110,13 +114,25 @@ public class ClientSynchronizationManager {
} break;
}
} break;
+ case BehaviorTreeIdEnums.BTREE_SERVERBLOCKTREE_ID: {
+ switch(message.getfieldId()){
+ case 8:{
+ ClientBlockTree tree = ClientBlockTree.getClientBlockTree(entity);
+ tree.setState(ClientBlockTree.getBlockStateShortAsEnum((short)message.getbTreeValue()));
+ } break;
+ case 9:{
+ ClientBlockTree tree = ClientBlockTree.getClientBlockTree(entity);
+ tree.setCurrentBlockVariant(message.getstringValue());
+ } break;
+ }
+ } break;
case BehaviorTreeIdEnums.BTREE_SERVEREQUIPSTATE_ID: {
switch(message.getfieldId()){
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGRAVITY_ID: {
switch(message.getfieldId()){
- case 7:{
+ case 11:{
ClientGravityTree tree = ClientGravityTree.getClientGravityTree(entity);
tree.setState(ClientGravityTree.getGravityTreeStateShortAsEnum((short)message.getbTreeValue()));
} break;
@@ -124,15 +140,15 @@ public class ClientSynchronizationManager {
} break;
case BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID: {
switch(message.getfieldId()){
- case 9:{
- ClientIdleTree tree = ClientIdleTree.getIdleTree(entity);
+ case 13:{
+ ClientIdleTree tree = ClientIdleTree.getClientIdleTree(entity);
tree.setState(ClientIdleTree.getIdleTreeStateShortAsEnum((short)message.getbTreeValue()));
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGROUNDMOVEMENTTREE_ID: {
switch(message.getfieldId()){
- case 11:{
+ case 15:{
ClientGroundMovementTree tree = ClientGroundMovementTree.getClientGroundMovementTree(entity);
tree.setFacing(ClientGroundMovementTree.getMovementRelativeFacingShortAsEnum((short)message.getbTreeValue()));
} break;
diff --git a/src/main/java/electrosphere/renderer/pipelines/DebugContentPipeline.java b/src/main/java/electrosphere/renderer/pipelines/DebugContentPipeline.java
index 7c1aee3c..2e24189b 100644
--- a/src/main/java/electrosphere/renderer/pipelines/DebugContentPipeline.java
+++ b/src/main/java/electrosphere/renderer/pipelines/DebugContentPipeline.java
@@ -116,7 +116,12 @@ public class DebugContentPipeline implements RenderPipeline {
modelTransformMatrix.translate(cameraModifiedPosition);
//since you're directly accessing the quat from the body, need to adjust it to be in the correct orientation
modelTransformMatrix.rotate(PhysicsUtils.odeQuatToJomlQuat(capsuleView.getQuaternion()).mul(new Quaterniond(0.707,0,0,0.707)));
- modelTransformMatrix.scale(capsuleView.getRadius(),capsuleView.getLength(),capsuleView.getRadius());
+ //the ode4j capsule's end caps are always at least radius length, the length only controls the distance between the two caps.
+ //unfortunately that won't be easy to replicate with rendering tech currently; instead, run logic below
+ double radius = capsuleView.getRadius();
+ double length = capsuleView.getLength();
+ if(length < radius) length = radius;
+ modelTransformMatrix.scale(radius,length,radius);
hitboxModel.setModelMatrix(modelTransformMatrix);
hitboxModel.draw(renderPipelineState,openGLState);
}
@@ -220,7 +225,12 @@ public class DebugContentPipeline implements RenderPipeline {
modelTransformMatrix.translate(cameraModifiedPosition);
//since you're directly accessing the quat from the body, need to adjust it to be in the correct orientation
modelTransformMatrix.rotate(PhysicsUtils.odeQuatToJomlQuat(capsuleView.getQuaternion()).mul(new Quaterniond(0.707,0,0,0.707)));
- modelTransformMatrix.scale(capsuleView.getRadius(),capsuleView.getLength(),capsuleView.getRadius());
+ //the ode4j capsule's end caps are always at least radius length, the length only controls the distance between the two caps.
+ //unfortunately that won't be easy to replicate with rendering tech currently; instead, run logic below
+ double radius = capsuleView.getRadius();
+ double length = capsuleView.getLength();
+ if(length < radius) length = radius;
+ modelTransformMatrix.scale(radius,length,radius);
hitboxModel.setModelMatrix(modelTransformMatrix);
hitboxModel.draw(renderPipelineState,openGLState);
}
diff --git a/src/main/java/electrosphere/server/MainServerFunctions.java b/src/main/java/electrosphere/server/MainServerFunctions.java
new file mode 100644
index 00000000..2245b47e
--- /dev/null
+++ b/src/main/java/electrosphere/server/MainServerFunctions.java
@@ -0,0 +1,41 @@
+package electrosphere.server;
+
+import electrosphere.engine.Globals;
+import electrosphere.logger.LoggerInterface;
+
+/**
+ * Functions that should be fired every server frame
+ */
+public class MainServerFunctions {
+
+ /**
+ * Calls the main server routines that should fire each frame
+ */
+ public static void simulate(){
+
+ //
+ //Synchronous player message parsing\
+ Globals.profiler.beginCpuSample("Server synchronous packet parsing");
+ if(Globals.server != null){
+ Globals.server.synchronousPacketHandling();
+ }
+ Globals.profiler.endCpuSample();
+
+ //
+ //Micro simulation (ie simulating each scene on the server)
+ Globals.profiler.beginCpuSample("Server micro simulation");
+ LoggerInterface.loggerEngine.DEBUG("Begin server micro simulation");
+ if(Globals.realmManager != null){
+ Globals.realmManager.simulate();
+ }
+
+ //
+ //Macro simulation (ie simulating the larger world macro data)
+ LoggerInterface.loggerEngine.DEBUG("Server macro simulation");
+ if(Globals.macroSimulation != null && Globals.macroSimulation.isReady()){
+ Globals.macroSimulation.simulate();
+ }
+ Globals.profiler.endCpuSample();
+ }
+
+}
diff --git a/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java b/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java
index 084f3846..969f07b1 100644
--- a/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java
+++ b/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java
@@ -30,7 +30,7 @@ public class PlayerCharacterCreation {
Realm realm = Globals.realmManager.getRealms().iterator().next();
Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,new Vector3d(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z),raceName,template);
int playerCharacterId = newPlayerEntity.getId();
- connectionHandler.setPlayerCharacterId(playerCharacterId);
+ connectionHandler.setPlayerEntityId(playerCharacterId);
CreatureUtils.setControllerPlayerId(newPlayerEntity, connectionHandler.getPlayerId());
//custom player btrees
addPlayerServerBTrees(newPlayerEntity);
diff --git a/src/main/java/electrosphere/server/player/PlayerActions.java b/src/main/java/electrosphere/server/player/PlayerActions.java
new file mode 100644
index 00000000..59f2cbd2
--- /dev/null
+++ b/src/main/java/electrosphere/server/player/PlayerActions.java
@@ -0,0 +1,35 @@
+package electrosphere.server.player;
+
+import electrosphere.client.item.ItemActions;
+import electrosphere.entity.Entity;
+import electrosphere.entity.state.block.ServerBlockTree;
+import electrosphere.net.parser.net.message.InventoryMessage;
+import electrosphere.net.server.ServerConnectionHandler;
+import electrosphere.server.datacell.utils.EntityLookupUtils;
+
+/**
+ * Class for handling
+ */
+public class PlayerActions {
+
+ /**
+ * Attempts to perform an action a player requested
+ * @param connectionHandler The player's connection handler
+ * @param message The network message that encapsulates the requested action
+ */
+ public static void attemptPlayerAction(ServerConnectionHandler connectionHandler, InventoryMessage message){
+ Entity playerEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
+
+ if(message.getitemActionCode() == ItemActions.ITEM_ACTION_CODE_SECONDARY){
+ ServerBlockTree serverBlockTree = ServerBlockTree.getServerBlockTree(playerEntity);
+ if(serverBlockTree != null){
+ if(message.getitemActionCodeState() == ItemActions.ITEM_ACTION_CODE_STATE_ON){
+ serverBlockTree.start();
+ } else {
+ serverBlockTree.stop();
+ }
+ }
+ }
+ }
+
+}