From 3b521e31978b4b1fe5f1ceb8b636a95481976068 Mon Sep 17 00:00:00 2001 From: austin Date: Tue, 22 Oct 2024 11:29:14 -0400 Subject: [PATCH] editor entity --- assets/Data/entity/creatures.json | 3 +- assets/Data/entity/creatures/editor.json | 76 +++ docs/src/progress/currenttarget.md | 55 +- docs/src/progress/renderertodo.md | 41 ++ .../client/sim/ClientSimulation.java | 6 +- .../menu/script/ScriptLevelEditorUtils.java | 88 +-- .../controls/ControlHandler.java | 104 ++++ .../java/electrosphere/engine/Globals.java | 1 + .../loadingthreads/DebugSPWorldLoading.java | 2 +- .../loadingthreads/LevelEditorLoading.java | 3 +- .../engine/loadingthreads/LevelLoading.java | 2 +- .../engine/loadingthreads/LoadingUtils.java | 9 +- .../entity/EntityDataStrings.java | 2 + .../editor/ClientEditorMovementTree.java | 568 ++++++++++++++++++ .../editor/ServerEditorMovementTree.java | 541 +++++++++++++++++ .../types/common/CommonEntityUtils.java | 9 + .../type/movement/EditorMovementSystem.java | 25 + .../movement/MovementSystemSerializer.java | 28 +- .../client/ClientSynchronizationManager.java | 9 + .../enums/BehaviorTreeIdEnums.java | 2 + .../synchronization/enums/FieldIdEnums.java | 2 + .../transport/StateCollection.java | 14 + .../electrosphere/server/datacell/Realm.java | 6 +- 23 files changed, 1499 insertions(+), 97 deletions(-) create mode 100644 assets/Data/entity/creatures/editor.json create mode 100644 src/main/java/electrosphere/entity/state/movement/editor/ClientEditorMovementTree.java create mode 100644 src/main/java/electrosphere/entity/state/movement/editor/ServerEditorMovementTree.java create mode 100644 src/main/java/electrosphere/game/data/creature/type/movement/EditorMovementSystem.java diff --git a/assets/Data/entity/creatures.json b/assets/Data/entity/creatures.json index 469c4bad..ad6e8e7b 100644 --- a/assets/Data/entity/creatures.json +++ b/assets/Data/entity/creatures.json @@ -5,7 +5,8 @@ ], "files" : [ "Data/entity/creatures/human.json", - "Data/entity/creatures/skeleton.json" + "Data/entity/creatures/skeleton.json", + "Data/entity/creatures/editor.json" ] } diff --git a/assets/Data/entity/creatures/editor.json b/assets/Data/entity/creatures/editor.json new file mode 100644 index 00000000..48bc8f18 --- /dev/null +++ b/assets/Data/entity/creatures/editor.json @@ -0,0 +1,76 @@ +{ + "creatures" : [ + { + "id" : "editor", + "hitboxes" : [], + "tokens" : [ + "TARGETABLE", + "CAN_EQUIP", + "INVENTORY", + "OUTLINE", + "PLAYABLE", + "UNIT_CONTROLS", + "EDITOR" + ], + "visualAttributes" : [], + "movementSystems" : [ + { + "type": "EDITOR" + } + ], + "equipPoints" : [ + { + "equipPointId" : "handRight", + "bone" : "Hand.R", + "firstPersonBone" : "hand.R", + "offsetVectorFirstPerson" : [-0.01,-0.05,-0.10], + "offsetVectorThirdPerson" : [0.02,-0.06,0], + "offsetRotationThirdPerson" : [-0.334,0.145,-0.28,0.89], + "offsetRotationFirstPerson" : [0.02,-0.977,-0.211,-0.005], + "canBlock" : true, + "equipClassWhitelist" : [ + "tool", + "weapon", + "item" + ], + "equippedAnimation" : { + "nameThirdPerson" : "Idle1", + "nameFirstPerson" : "Idle", + "priorityCategory" : "MODIFIER_HIGH", + "boneGroups" : ["handRight"] + }, + "isToolbarSlot": true + } + ], + "toolbarData" : { + "primarySlot" : "handRight", + "combinedSlot" : "handsCombined" + }, + "attackMoves" : [], + "healthSystem" : { + "maxHealth" : 100, + "onDamageIFrames" : 30 + }, + "graphicsTemplate": { + "model": { + "path" : "Models/creatures/person2/person2_1.glb" + } + }, + "viewModelData" : { + "heightFromOrigin" : 1.3, + "cameraViewDirOffsetY" : -0.3, + "cameraViewDirOffsetZ" : 0.0, + "firstPersonModelPath" : "Models/creatures/viewmodel.glb" + }, + "cameraData" : { + "thirdPersonCameraOffset": { + "x": 0.0, + "y": 1.5, + "z": 0.0 + } + }, + "boneGroups" : [] + } + ], + "files" : [] +} \ No newline at end of file diff --git a/docs/src/progress/currenttarget.md b/docs/src/progress/currenttarget.md index cfc653a4..f8b734b2 100644 --- a/docs/src/progress/currenttarget.md +++ b/docs/src/progress/currenttarget.md @@ -1,37 +1,33 @@ @page currenttarget Current Target -+ client fires up and there's a menu that takes you to the demo - Demo menu -+ spawn into the world -+ there is a sword lying on the ground -+ when you grab the sword, a tutorial popup appears to tell you how to use in -+ on clearing the tutorial, continue the game when the sword is equipped, create another popup to teach sword controls. it pauses the game -+ when popup is accepted, spawn an enemy with an effect - Script engine ability to spawn entities ++ Upgrade editor + - Position & Rotation gismo tools ++ Spawn underground + - Script engine ability to play effects + - Script engine ability to play animations on an actor + - Script engine ability to apply cameras + - Script engine ability to show/hide ui ++ Lock first room behind interacting with a door + - Tutorial hint for interacting with things + - Implement doors ++ Lock second room behind picking up an old sword and hitting a switch + - Old sword item + - Switch that requires being hit + - Door that can be locked ++ Lock third room behind climbing + - Climbing ++ Portal to tutorial hub area + - Portals + - Switching realms + - Loading realms on demand + rearchitecture + fix the vibes Ticketed randomizer node for BTs to more heavily weight attacking and waiting ++ non-feedback requirements + + feedback driven requirements - Implement gadgets - - Chemistry System - - Emitters - - Subscribers - - Dedicated collision engine on server - - Trap - - Bear - - Freeze - - Flame - - Bomb (to be thrown) - - Regular (Deals damage, ignites) - - Air (high push coeff) - - Flash (dazes) - - Sleep (puts enemies to sleep) - - Smoke (creates LOS blockers) - - Decoy (creates a decoy) - - Torch - - Throwable potions Crouching Model clothing, hair for the human particles, light on sword collision @@ -41,12 +37,5 @@ - Spawn player in a town with a quest to complete a nearby dungeon + bug fixes - Fix light cluster mapping for foliage shader - Fix foliage placement - Fix lights not being deleted - - Not sending a "light count" var to light calculations, so the data stays in buffer even though it is not being updated - Fix block tree preventing initiating an attack - Fix return to title menu synchronization bug - Fix particles not spawning in correct positions + unreproducible bugs diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 4e02ba45..e50bb056 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -883,12 +883,44 @@ Fix movement audio service when audio engine disabled Fix idle animations (for katana) Fix equipping sword on toolbar Add punching/unarmed combat +Fix script spawning NPE + +(10/22/2024) +Editor movement system + editor entity +Ability to disable physics # TODO + + +Implement gadgets + - Chemistry System + - Emitters + - Subscribers + - Dedicated collision engine on server + - Trap + - Bear + - Freeze + - Flame + - Bomb (to be thrown) + - Regular (Deals damage, ignites) + - Air (high push coeff) + - Flash (dazes) + - Sleep (puts enemies to sleep) + - Smoke (creates LOS blockers) + - Decoy (creates a decoy) + - Torch + - Throwable potions + Crafting + - Crafting Menu + - Recipe definitions + - Reagent items + - Hover-over Tooltip for items in inventory + + Ability to fully reload game engine state without exiting client - Back out to main menu and load a new level without any values persisting - Receive a teleport packet from server and flush all game state before requesting state from server again @@ -900,6 +932,15 @@ Bug Fixes - Calculate bounding sphere for meshes by deforming vertices with bone default pose instead of no bone deform - Fix character creation menu - Fix threads not synchronizing when returning to main menu (rendering still running when player entity deleted, race condition) + - Fix light cluster mapping for foliage shader + - Fix foliage placement + - Fix lights not being deleted + - Not sending a "light count" var to light calculations, so the data stays in buffer even though it is not being updated + - Fix block tree preventing initiating an attack + - Fix return to title menu synchronization bug + - Fix particles not spawning in correct positions + - Fix level creation menu button alignment + - Fix spawn palette menu alignment Startup Performance - Cache loaded typescript diff --git a/src/main/java/electrosphere/client/sim/ClientSimulation.java b/src/main/java/electrosphere/client/sim/ClientSimulation.java index 9803dd6a..95d26e62 100644 --- a/src/main/java/electrosphere/client/sim/ClientSimulation.java +++ b/src/main/java/electrosphere/client/sim/ClientSimulation.java @@ -54,8 +54,10 @@ public class ClientSimulation { Globals.profiler.endCpuSample(); // //simulate bullet physics engine step - Globals.clientSceneWrapper.getCollisionEngine().simulatePhysics((float)Globals.timekeeper.getSimFrameTime()); - Globals.clientSceneWrapper.getCollisionEngine().updateDynamicObjectTransforms(); + if(Globals.RUN_PHYSICS){ + Globals.clientSceneWrapper.getCollisionEngine().simulatePhysics((float)Globals.timekeeper.getSimFrameTime()); + Globals.clientSceneWrapper.getCollisionEngine().updateDynamicObjectTransforms(); + } //update actor animations Globals.profiler.beginCpuSample("update actor animations"); diff --git a/src/main/java/electrosphere/client/ui/menu/script/ScriptLevelEditorUtils.java b/src/main/java/electrosphere/client/ui/menu/script/ScriptLevelEditorUtils.java index 7304fe1a..a67227a3 100644 --- a/src/main/java/electrosphere/client/ui/menu/script/ScriptLevelEditorUtils.java +++ b/src/main/java/electrosphere/client/ui/menu/script/ScriptLevelEditorUtils.java @@ -31,49 +31,51 @@ public class ScriptLevelEditorUtils { */ @Export public static void spawnEntity(){ - if(Globals.selectedSpawntype instanceof CreatureData){ - LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!"); - Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); - Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); - Realm realm = Globals.realmManager.getRealms().iterator().next(); - CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); - if(cursorPos != null){ - cursorPos = cursorPos.add(cursorVerticalOffset); - CreatureUtils.serverSpawnBasicCreature(realm, cursorPos, Globals.selectedSpawntype.getId(), null); - } - } else if(Globals.selectedSpawntype instanceof Item){ - LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!"); - Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); - Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); - Realm realm = Globals.realmManager.getRealms().iterator().next(); - CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); - if(cursorPos != null){ - cursorPos = cursorPos.add(cursorVerticalOffset); - ItemUtils.serverSpawnBasicItem(realm, cursorPos, Globals.selectedSpawntype.getId()); - } - } else if(Globals.selectedSpawntype instanceof FoliageType){ - LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!"); - Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); - Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); - Realm realm = Globals.realmManager.getRealms().iterator().next(); - CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); - if(cursorPos != null){ - cursorPos = cursorPos.add(cursorVerticalOffset); - FoliageUtils.serverSpawnTreeFoliage(realm, cursorPos, Globals.selectedSpawntype.getId(), new Random().nextLong()); - } - } else { - LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!"); - Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); - Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); - Realm realm = Globals.realmManager.getRealms().iterator().next(); - CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); - if(cursorPos != null){ - cursorPos = cursorPos.add(cursorVerticalOffset); - CommonEntityUtils.serverSpawnBasicObject(realm, cursorPos, Globals.selectedSpawntype.getId()); + if(Globals.selectedSpawntype != null){ + if(Globals.selectedSpawntype instanceof CreatureData){ + LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!"); + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Realm realm = Globals.realmManager.getRealms().iterator().next(); + CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + if(cursorPos != null){ + cursorPos = cursorPos.add(cursorVerticalOffset); + CreatureUtils.serverSpawnBasicCreature(realm, cursorPos, Globals.selectedSpawntype.getId(), null); + } + } else if(Globals.selectedSpawntype instanceof Item){ + LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!"); + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Realm realm = Globals.realmManager.getRealms().iterator().next(); + CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + if(cursorPos != null){ + cursorPos = cursorPos.add(cursorVerticalOffset); + ItemUtils.serverSpawnBasicItem(realm, cursorPos, Globals.selectedSpawntype.getId()); + } + } else if(Globals.selectedSpawntype instanceof FoliageType){ + LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!"); + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Realm realm = Globals.realmManager.getRealms().iterator().next(); + CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + if(cursorPos != null){ + cursorPos = cursorPos.add(cursorVerticalOffset); + FoliageUtils.serverSpawnTreeFoliage(realm, cursorPos, Globals.selectedSpawntype.getId(), new Random().nextLong()); + } + } else { + LoggerInterface.loggerEngine.INFO("spawn " + Globals.selectedSpawntype.getId() + "!"); + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Realm realm = Globals.realmManager.getRealms().iterator().next(); + CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + if(cursorPos != null){ + cursorPos = cursorPos.add(cursorVerticalOffset); + CommonEntityUtils.serverSpawnBasicObject(realm, cursorPos, Globals.selectedSpawntype.getId()); + } } } } diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java index 6f3730ce..4e39e869 100644 --- a/src/main/java/electrosphere/controls/ControlHandler.java +++ b/src/main/java/electrosphere/controls/ControlHandler.java @@ -94,6 +94,7 @@ import electrosphere.entity.state.equip.ClientEquipState; import electrosphere.entity.state.equip.ClientToolbarState; import electrosphere.entity.state.inventory.InventoryUtils; import electrosphere.entity.state.inventory.UnrelationalInventoryState; +import electrosphere.entity.state.movement.editor.ClientEditorMovementTree; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementRelativeFacing; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementTreeState; @@ -133,6 +134,7 @@ public class ControlHandler { public static final String DATA_STRING_INPUT_CODE_LOCK_CROSSHAIR = "crosshairLock"; public static final String INPUT_CODE_SPRINT = "sprint"; public static final String INPUT_CODE_WALK = "walk"; + public static final String INPUT_CODE_SINK = "sink"; public static final String INPUT_CODE_INTERACT = "interact"; public static final String INPUT_CODE_DROP = "drop"; public static final String INPUT_CODE_INVENTORY_OPEN = "inventoryOpen"; @@ -324,6 +326,7 @@ public class ControlHandler { handler.addControl(DATA_STRING_INPUT_CODE_LOCK_CROSSHAIR, new Control(ControlType.KEY,GLFW_KEY_CAPS_LOCK,false,"Lock On","Locks the camera onto the target")); handler.addControl(INPUT_CODE_SPRINT, new Control(ControlType.KEY,GLFW_KEY_LEFT_SHIFT,false,"Sprint (hold)","Causes the player to sprint")); handler.addControl(INPUT_CODE_WALK, new Control(ControlType.KEY,GLFW_KEY_LEFT_ALT,false,"Walk (hold)","Causes the player to walk")); + handler.addControl(INPUT_CODE_SINK, new Control(ControlType.KEY,GLFW_KEY_LEFT_CONTROL,true,"Sink","Sinks the entity")); handler.addControl(INPUT_CODE_INTERACT, new Control(ControlType.KEY,GLFW_KEY_E,false,"Interact","Interacts with whatever is targeted currently")); handler.addControl(INPUT_CODE_DROP, new Control(ControlType.KEY,GLFW_KEY_Y,false,"Drop","Drops the currently equipped item")); handler.addControl(INPUT_CODE_INVENTORY_OPEN, new Control(ControlType.KEY,GLFW.GLFW_KEY_TAB,false,"Inventory","Opens the player's inventory")); @@ -538,6 +541,10 @@ public class ControlHandler { CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); groundTree.start(MovementRelativeFacing.FORWARD); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.FORWARD); } } }}); @@ -556,6 +563,10 @@ public class ControlHandler { CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); groundTree.start(MovementRelativeFacing.FORWARD); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.FORWARD); } } }}); @@ -565,6 +576,9 @@ public class ControlHandler { if(movementTree instanceof ClientGroundMovementTree){ ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree; groundTree.slowdown(); + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.slowdown(); } } }}); @@ -588,6 +602,10 @@ public class ControlHandler { CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); groundTree.start(MovementRelativeFacing.BACKWARD); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.BACKWARD); } } }}); @@ -607,6 +625,10 @@ public class ControlHandler { CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); groundTree.start(MovementRelativeFacing.BACKWARD); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.BACKWARD); } } }}); @@ -616,6 +638,9 @@ public class ControlHandler { if(movementTree instanceof ClientGroundMovementTree){ ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree; groundTree.slowdown(); + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.slowdown(); } } }}); @@ -636,6 +661,11 @@ public class ControlHandler { CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(Math.PI/2.0).normalize()); groundTree.start(MovementRelativeFacing.FORWARD); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera); + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(Math.PI/2.0).normalize()); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.FORWARD); } } }}); @@ -652,6 +682,11 @@ public class ControlHandler { CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(Math.PI/2.0).normalize()); groundTree.start(MovementRelativeFacing.FORWARD); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera); + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(Math.PI/2.0).normalize()); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.FORWARD); } } }}); @@ -661,6 +696,9 @@ public class ControlHandler { if(movementTree instanceof ClientGroundMovementTree){ ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree; groundTree.slowdown(); + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.slowdown(); } } }}); @@ -681,6 +719,11 @@ public class ControlHandler { CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(-Math.PI/2.0).normalize()); groundTree.start(MovementRelativeFacing.FORWARD); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera); + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(-Math.PI/2.0).normalize()); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.FORWARD); } } }}); @@ -697,6 +740,11 @@ public class ControlHandler { CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(-Math.PI/2.0).normalize()); groundTree.start(MovementRelativeFacing.FORWARD); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera); + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).rotateY(-Math.PI/2.0).normalize()); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.FORWARD); } } }}); @@ -706,6 +754,9 @@ public class ControlHandler { if(movementTree instanceof ClientGroundMovementTree){ ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree; groundTree.slowdown(); + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.slowdown(); } } }}); @@ -735,6 +786,10 @@ public class ControlHandler { ){ groundTree.start(MovementRelativeFacing.LEFT); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.LEFT); } } }}); @@ -751,6 +806,10 @@ public class ControlHandler { ){ groundTree.start(MovementRelativeFacing.LEFT); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.LEFT); } } }}); @@ -760,6 +819,9 @@ public class ControlHandler { if(movementTree instanceof ClientGroundMovementTree){ ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree; groundTree.slowdown(); + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.slowdown(); } } }}); @@ -780,6 +842,10 @@ public class ControlHandler { ){ groundTree.start(MovementRelativeFacing.RIGHT); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.RIGHT); } } }}); @@ -796,6 +862,10 @@ public class ControlHandler { ){ groundTree.start(MovementRelativeFacing.RIGHT); } + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + CreatureUtils.setFacingVector(Globals.playerEntity, CameraEntityUtils.getFacingVec(Globals.playerCamera)); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.RIGHT); } } }}); @@ -805,6 +875,9 @@ public class ControlHandler { if(movementTree instanceof ClientGroundMovementTree){ ClientGroundMovementTree groundTree = (ClientGroundMovementTree) movementTree; groundTree.slowdown(); + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.slowdown(); } } }}); @@ -818,6 +891,37 @@ public class ControlHandler { ClientJumpTree jumpTree = ClientJumpTree.getClientJumpTree(Globals.playerEntity); if(jumpTree != null){ jumpTree.start(); + } else if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.UP); + } + } + }}); + controls.get(DATA_STRING_INPUT_CODE_MOVEMENT_JUMP).setOnRelease(new ControlMethod(){public void execute(){ + if(Globals.playerEntity != null){ + if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.slowdown(); + } + } + }}); + /** + * Sink + */ + mainGameControlList.add(controls.get(INPUT_CODE_SINK)); + controls.get(INPUT_CODE_SINK).setOnPress(new ControlMethod(){public void execute(){ + if(Globals.playerEntity != null){ + if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.start(electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing.DOWN); + } + } + }}); + controls.get(INPUT_CODE_SINK).setOnRelease(new ControlMethod(){public void execute(){ + if(Globals.playerEntity != null){ + if(ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity) != null){ + ClientEditorMovementTree clientEditorMovementTree = ClientEditorMovementTree.getClientEditorMovementTree(Globals.playerEntity); + clientEditorMovementTree.slowdown(); } } }}); diff --git a/src/main/java/electrosphere/engine/Globals.java b/src/main/java/electrosphere/engine/Globals.java index 735ac874..bdbebe92 100644 --- a/src/main/java/electrosphere/engine/Globals.java +++ b/src/main/java/electrosphere/engine/Globals.java @@ -163,6 +163,7 @@ public class Globals { public static boolean RUN_HIDDEN = false; //glfw session will be created with hidden window public static boolean RUN_AUDIO = false; public static boolean RUN_SCRIPTS = true; + public static boolean RUN_PHYSICS = true; //toggles whether physics is run or not public static int clientCharacterID; public static NetConfig netConfig = null; diff --git a/src/main/java/electrosphere/engine/loadingthreads/DebugSPWorldLoading.java b/src/main/java/electrosphere/engine/loadingthreads/DebugSPWorldLoading.java index eb862b13..11b84fd9 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/DebugSPWorldLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/DebugSPWorldLoading.java @@ -73,7 +73,7 @@ public class DebugSPWorldLoading { } //spawn player character - LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection); + LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection, false); //request terrain data Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage()); diff --git a/src/main/java/electrosphere/engine/loadingthreads/LevelEditorLoading.java b/src/main/java/electrosphere/engine/loadingthreads/LevelEditorLoading.java index 7ad077a4..9c12b4bd 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/LevelEditorLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/LevelEditorLoading.java @@ -51,6 +51,7 @@ public class LevelEditorLoading { // Globals.RUN_CLIENT = true; Globals.RUN_SERVER = true; + Globals.RUN_PHYSICS = false; Globals.aiManager.setActive(false); @@ -101,7 +102,7 @@ public class LevelEditorLoading { } //spawn player character - LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection); + LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection, true); //request terrain data Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage()); diff --git a/src/main/java/electrosphere/engine/loadingthreads/LevelLoading.java b/src/main/java/electrosphere/engine/loadingthreads/LevelLoading.java index 9780e4c8..36620aa7 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/LevelLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/LevelLoading.java @@ -72,7 +72,7 @@ public class LevelLoading { } //spawn player character - LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection); + LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection, false); //request terrain data Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage()); diff --git a/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java b/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java index f93ebd54..08bbe173 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java +++ b/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java @@ -154,13 +154,16 @@ public class LoadingUtils { /** * Spawns the character, and sets server side connection player object values to the appropriate chunk */ - static void spawnLocalPlayerTestEntity(ServerConnectionHandler serverPlayerConnection){ + static void spawnLocalPlayerTestEntity(ServerConnectionHandler serverPlayerConnection, boolean isEditor){ // //Create entity // //send default template back - List races = Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces(); - String race = races.get(new Random().nextInt(races.size())); + String race = "editor"; + if(!isEditor){ + List races = Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces(); + race = races.get(new Random().nextInt(races.size())); + } CreatureData type = Globals.gameConfigCurrent.getCreatureTypeLoader().getType(race); CreatureTemplate template = CreatureTemplate.create(race); for(VisualAttribute attribute : type.getVisualAttributes()){ diff --git a/src/main/java/electrosphere/entity/EntityDataStrings.java b/src/main/java/electrosphere/entity/EntityDataStrings.java index 2c186de5..610edd52 100644 --- a/src/main/java/electrosphere/entity/EntityDataStrings.java +++ b/src/main/java/electrosphere/entity/EntityDataStrings.java @@ -63,6 +63,8 @@ public class EntityDataStrings { public static final String SERVER_MOVEMENT_BT = "serverMovementBT"; public static final String TREE_CLIENTGROUNDMOVEMENTTREE = "treeClientGroundMovementTree"; public static final String TREE_SERVERGROUNDMOVEMENTTREE = "treeServerGroundMovementTree"; + public static final String TREE_CLIENTEDITORMOVEMENTTREE = "treeClientEditorMovementTree"; + public static final String TREE_SERVEREDITORMOVEMENTTREE = "treeServerEditorMovementTree"; public static final String TREE_CLIENTSPRINTTREE = "treeClientSprintTree"; public static final String TREE_SERVERSPRINTTREE = "treeServerSprintTree"; public static final String DATA_STRING_FACING_VECTOR = "facingVector"; diff --git a/src/main/java/electrosphere/entity/state/movement/editor/ClientEditorMovementTree.java b/src/main/java/electrosphere/entity/state/movement/editor/ClientEditorMovementTree.java new file mode 100644 index 00000000..6ce89296 --- /dev/null +++ b/src/main/java/electrosphere/entity/state/movement/editor/ClientEditorMovementTree.java @@ -0,0 +1,568 @@ +package electrosphere.entity.state.movement.editor; + + +import electrosphere.entity.state.gravity.GravityUtils; +import electrosphere.engine.Globals; +import electrosphere.entity.types.collision.CollisionObjUtils; +import electrosphere.entity.types.creature.CreatureUtils; +import electrosphere.game.data.creature.type.movement.EditorMovementSystem; +import electrosphere.entity.Entity; +import electrosphere.entity.EntityDataStrings; +import electrosphere.entity.EntityUtils; +import electrosphere.entity.btree.BehaviorTree; +import electrosphere.entity.state.attack.ClientAttackTree; +import electrosphere.entity.state.movement.fall.ClientFallTree; +import electrosphere.entity.state.movement.jump.ClientJumpTree; +import electrosphere.entity.state.movement.sprint.ClientSprintTree; +import electrosphere.entity.state.movement.walk.ClientWalkTree; +import electrosphere.net.parser.net.message.EntityMessage; +import electrosphere.net.synchronization.annotation.SyncedField; +import electrosphere.net.synchronization.annotation.SynchronizableEnum; +import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; +import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums; +import electrosphere.renderer.anim.Animation; +import electrosphere.util.math.MathUtils; + +import java.util.concurrent.CopyOnWriteArrayList; + +import org.joml.Quaterniond; +import org.joml.Vector3d; + +@SynchronizedBehaviorTree(name = "clientEditorMovementTree", isServer = false, correspondingTree="serverEditorMovementTree") +/* +Behavior tree for movement in an entity +*/ +public class ClientEditorMovementTree implements BehaviorTree { + + /** + * The state of the editor movement tree + */ + public static enum MovementTreeState { + STARTUP, + MOVE, + SLOWDOWN, + IDLE, + } + + /** + * The relative facing of the character to its rotation + * (ie is it strafing, moveing straight forward, backpedaling, etc) + */ + @SynchronizableEnum + public static enum MovementRelativeFacing { + FORWARD, + LEFT, + RIGHT, + BACKWARD, + FORWARD_LEFT, + FORWARD_RIGHT, + BACKWARD_LEFT, + BACKWARD_RIGHT, + UP, + DOWN, + } + + static final double STATE_DIFFERENCE_HARD_UPDATE_THRESHOLD = 1.0; + static final double STATE_DIFFERENCE_SOFT_UPDATE_THRESHOLD = 0.1; + static final double SOFT_UPDATE_MULTIPLIER = 0.3; + static final double STATE_DIFFERENCE_CREEP_MULTIPLIER = 0.001; //while the movement tree is idle, slowly creep the position of the entity towards the true server position by this amount + static final double STATE_DIFFERENCE_CREEP_CUTOFF = 0.01; //the cutoff for creep when we say it's "close enough" + + public static final float EDITOR_MAX_VELOCITY = 1.0f; + public static final float EDITOR_ACCEL = 1.0f; + + String animationStartUp = Animation.ANIMATION_MOVEMENT_STARTUP; + String animationMain = Animation.ANIMATION_MOVEMENT_MOVE; + String animationSlowDown = Animation.ANIMATION_MOVEMENT_MOVE; + String animationSprintStart = Animation.ANIMATION_SPRINT_STARTUP; + String animationSprint = Animation.ANIMATION_SPRINT; + String animationSprintWindDown = Animation.ANIMATION_SPRINT_WINDDOWN; + + MovementTreeState state; + @SyncedField + MovementRelativeFacing facing = MovementRelativeFacing.FORWARD; + + ClientSprintTree sprintTree; + ClientJumpTree jumpTree; + ClientFallTree fallTree; + + EditorMovementSystem editorMovementData; + + Entity parent; + + CopyOnWriteArrayList networkMessageQueue = new CopyOnWriteArrayList(); + + //the last frame we got an update on true position from the server + long lastUpdateTime = 0; + //the last position reported by the server + Vector3d lastServerPosition = null; + + //the vector controling the direction the entity will move in + Vector3d movementVector = new Vector3d(1,0,0); + + //Tracks whether footstep audio has been played or not + boolean playedFootstepFirst = false; + boolean playedFootstepSecond = false; + + /** + * Constructor + * @param e The parent entity + */ + private ClientEditorMovementTree(Entity e, Object ... params){ + //Collidable collidable, EditorMovementSystem editorMovementData + if(params.length < 1){ + throw new IllegalArgumentException("Tried to create a client editor movement tree without providing both mandatory parameters"); + } + state = MovementTreeState.IDLE; + parent = e; + this.editorMovementData = (EditorMovementSystem)params[0]; + } + + /** + * Gets the state of the tree + * @return The state + */ + public MovementTreeState getState(){ + return state; + } + + /** + * Requests to the server that the entity start moving + * @param facing The facing relative to the view direction that the entity should move in (ie strafe right vs walk straight forward) + */ + public void start(MovementRelativeFacing facing){ + if(canStartMoving()){ + setFacing(facing); + state = MovementTreeState.STARTUP; + //if we aren't the server, alert the server we intend to walk forward + Vector3d position = EntityUtils.getPosition(parent); + Quaterniond rotation = EntityUtils.getRotation(parent); + float velocity = CreatureUtils.getVelocity(parent); + if(this.parent == Globals.playerEntity){ + Globals.clientConnection.queueOutgoingMessage( + EntityMessage.constructmoveUpdateMessage( + Globals.clientSceneWrapper.mapClientToServerId(parent.getId()), + Globals.timekeeper.getNumberOfSimFramesElapsed(), + position.x, + position.y, + position.z, + rotation.x, + rotation.y, + rotation.z, + rotation.w, + velocity, + ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(facing), + 0 //magic number corresponding to state startup + ) + ); + } + } + } + + /** + * Requests to the server that the movetree stop + */ + public void slowdown(){ + state = MovementTreeState.SLOWDOWN; + //if we aren't the server, alert the server we intend to slow down + Vector3d position = EntityUtils.getPosition(parent); + Quaterniond rotation = EntityUtils.getRotation(parent); + float velocity = CreatureUtils.getVelocity(parent); + if(this.parent == Globals.playerEntity){ + Globals.clientConnection.queueOutgoingMessage( + EntityMessage.constructmoveUpdateMessage( + Globals.clientSceneWrapper.mapClientToServerId(parent.getId()), + Globals.timekeeper.getNumberOfSimFramesElapsed(), + position.x, + position.y, + position.z, + rotation.x, + rotation.y, + rotation.z, + rotation.w, + velocity, + ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(facing), + 2 //magic number corresponding to state slowdown + ) + ); + } + } + + @Override + public void simulate(float deltaTime){ + Vector3d position = EntityUtils.getPosition(parent); + Vector3d facingVector = CreatureUtils.getFacingVector(parent); + float maxNaturalVelocity = EDITOR_MAX_VELOCITY; + + // + //rotation update + if(this.state != MovementTreeState.IDLE){ + this.movementVector.set(facingVector); + switch(facing){ + case FORWARD: + movementVector.normalize(); + break; + case LEFT: + movementVector.rotateY((float)(90 * Math.PI / 180)).normalize(); + break; + case RIGHT: + movementVector.rotateY((float)(-90 * Math.PI / 180)).normalize(); + break; + case BACKWARD: + movementVector.x = -movementVector.x; + movementVector.z = -movementVector.z; + movementVector.normalize(); + break; + case FORWARD_LEFT: + movementVector.rotateY((float)(45 * Math.PI / 180)).normalize(); + break; + case FORWARD_RIGHT: + movementVector.rotateY((float)(-45 * Math.PI / 180)).normalize(); + break; + case BACKWARD_LEFT: + movementVector.rotateY((float)(135 * Math.PI / 180)).normalize(); + break; + case BACKWARD_RIGHT: + movementVector.rotateY((float)(-135 * Math.PI / 180)).normalize(); + break; + case UP: { + movementVector = MathUtils.getUpVector(); + } break; + case DOWN: { + movementVector = MathUtils.getUpVector().mul(-1); + } break; + } + } + Quaterniond movementQuaternion = new Quaterniond().rotationTo(MathUtils.getOriginVector(), new Vector3d(facingVector.x,0,facingVector.z)).normalize(); + Quaterniond rotation = EntityUtils.getRotation(parent); + + //parse attached network messages + for(EntityMessage message : networkMessageQueue){ + networkMessageQueue.remove(message); + long updateTime = message.gettime(); +// System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ()); + switch(message.getMessageSubtype()){ + case MOVEUPDATE: + if(updateTime >= lastUpdateTime){ + lastUpdateTime = updateTime; + switch(message.gettreeState()){ + case 0: + state = MovementTreeState.STARTUP; + // System.out.println("Set state STARTUP"); + GravityUtils.clientAttemptActivateGravity(parent); + break; + case 1: + state = MovementTreeState.MOVE; + // System.out.println("Set state MOVE"); + GravityUtils.clientAttemptActivateGravity(parent); + break; + case 2: + state = MovementTreeState.SLOWDOWN; + // System.out.println("Set state SLOWDOWN"); + GravityUtils.clientAttemptActivateGravity(parent); + break; + case 3: + state = MovementTreeState.IDLE; + // System.out.println("Set state IDLE"); + break; + } + //this should only fire on the client, we don't want the server snap updating due to client position reporting + lastServerPosition = new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()); + if(position.distance(lastServerPosition) > STATE_DIFFERENCE_HARD_UPDATE_THRESHOLD){ + EntityUtils.getPosition(parent).set(lastServerPosition); + } else if(position.distance(lastServerPosition) > STATE_DIFFERENCE_SOFT_UPDATE_THRESHOLD){ + EntityUtils.getPosition(parent).lerp(lastServerPosition,SOFT_UPDATE_MULTIPLIER); + } + //we want to always update the server facing vector with where the client says they're facing + EntityUtils.getRotation(parent).set(message.getrotationX(),message.getrotationY(),message.getrotationZ(),message.getrotationW()); + CollisionObjUtils.clientPositionCharacter(parent, position, rotation); + // CreatureUtils.setFacingVector(parent, new Vector3d(message.getrotationX(),message.getrotationY(),message.getrotationZ())); + break; + } + break; + default: + break; + } + } + + // System.out.println(movementVector + " " + velocity * Main.deltaTime); + + //state machine + switch(state){ + case STARTUP: { + //update rotation + rotation.set(movementQuaternion); + + this.updateVelocity(); + float velocity = this.getModifiedVelocity(); + //check if can transition state + if(velocity >= maxNaturalVelocity){ + velocity = maxNaturalVelocity; + state = MovementTreeState.MOVE; + } + CreatureUtils.setVelocity(parent, velocity); + //actually update + rotation.set(movementQuaternion); + position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity))); + + GravityUtils.clientAttemptActivateGravity(parent); + } break; + case MOVE: { + //update rotation + rotation.set(movementQuaternion); + + + this.updateVelocity(); + float velocity = this.getModifiedVelocity(); + rotation.set(movementQuaternion); + position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity))); + + GravityUtils.clientAttemptActivateGravity(parent); + } break; + case SLOWDOWN: { + //update rotation + rotation.set(movementQuaternion); + + //velocity stuff + this.updateVelocity(); + float velocity = this.getModifiedVelocity(); + //check if can transition state + if(velocity <= 0){ + velocity = 0; + state = MovementTreeState.IDLE; + CreatureUtils.setVelocity(parent, velocity); + } + rotation.set(movementQuaternion); + position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity))); + + GravityUtils.clientAttemptActivateGravity(parent); + } break; + case IDLE: { + Vector3d playerPos = EntityUtils.getPosition(parent); + if(lastServerPosition != null && lastServerPosition.distance(playerPos) > STATE_DIFFERENCE_CREEP_CUTOFF){ + playerPos.lerp(lastServerPosition,STATE_DIFFERENCE_CREEP_MULTIPLIER); + } + } break; + } + } + + public void addNetworkMessage(EntityMessage networkMessage) { + networkMessageQueue.add(networkMessage); + } + + public boolean canStartMoving(){ + boolean rVal = true; + return rVal; + } + + public void setAnimationStartUp(String animationStartUp) { + this.animationStartUp = animationStartUp; + } + + public void setAnimationMain(String animationMain) { + this.animationMain = animationMain; + } + + public void setAnimationSlowDown(String animationSlowDown) { + this.animationSlowDown = animationSlowDown; + } + + public void setAnimationSprintStartUp(String animationSprintStartUp){ + this.animationSprintStart = animationSprintStartUp; + } + + public void setAnimationSprint(String animationSprint){ + this.animationSprint = animationSprint; + } + + public void setAnimationSprintWindDown(String animationSprintWindDown){ + this.animationSprintWindDown = animationSprintWindDown; + } + + public void setSprintTree(ClientSprintTree sprintTree){ + this.sprintTree = sprintTree; + } + + public void setClientJumpTree(ClientJumpTree jumpTree){ + this.jumpTree = jumpTree; + } + + public void setClientFallTree(ClientFallTree fallTree){ + this.fallTree = fallTree; + } + + /** + * Updates the velocity and acceleration + */ + private void updateVelocity(){ + float velocity = CreatureUtils.getVelocity(parent); + float acceleration = EDITOR_ACCEL; + float maxNaturalVelocity = EDITOR_MAX_VELOCITY; + switch(this.state){ + case IDLE: { + } break; + case STARTUP: { + //run startup code + velocity = velocity + acceleration * (float)Globals.timekeeper.getSimFrameTime(); + CreatureUtils.setVelocity(parent, velocity); + } break; + case MOVE: { + if(velocity != maxNaturalVelocity){ + velocity = maxNaturalVelocity; + CreatureUtils.setVelocity(parent, velocity); + } + } break; + case SLOWDOWN: { + //velocity stuff + velocity = velocity - acceleration * (float)Globals.timekeeper.getSimFrameTime(); + CreatureUtils.setVelocity(parent, velocity); + } break; + } + } + + /** + * Gets the velocity to move at + * @return The velocity + */ + private float getModifiedVelocity(){ + float velocity = CreatureUtils.getVelocity(parent); + float sprintModifier = 1.0f; + float walkModifier = 1.0f; + float attackModifier = 1.0f; + if(ClientWalkTree.getClientWalkTree(parent) != null && ClientWalkTree.getClientWalkTree(parent).isWalking()){ + walkModifier = ClientWalkTree.getClientWalkTree(parent).getModifier(); + } + if(ClientSprintTree.getClientSprintTree(parent) != null && ClientSprintTree.getClientSprintTree(parent).isSprinting()){ + sprintModifier = ClientSprintTree.getClientSprintTree(parent).getSprintSystem().getModifier(); + } + if(ClientAttackTree.getClientAttackTree(parent) != null){ + attackModifier = (float)ClientAttackTree.getClientAttackTree(parent).getMovementPenalty(); + } + return velocity * sprintModifier * walkModifier * attackModifier; + } + + /** + *

Automatically generated

+ *

+ * Gets facing. + *

+ */ + public MovementRelativeFacing getFacing(){ + return facing; + } + + + /** + *

Automatically generated

+ *

+ * Sets facing and handles the synchronization logic for it. + *

+ * @param facing The value to set facing to. + */ + public void setFacing(MovementRelativeFacing facing){ + this.facing = facing; + } + + + /** + *

+ * Gets the ClientEditorMovementTree of the entity + *

+ * @param entity the entity + * @return The ClientEditorMovementTree + */ + public static ClientEditorMovementTree getClientEditorMovementTree(Entity entity){ + return (ClientEditorMovementTree)entity.getData(EntityDataStrings.TREE_CLIENTEDITORMOVEMENTTREE); + } + /** + *

Automatically generated

+ *

+ * Converts this enum type to an equivalent short value + *

+ * @param enumVal The enum value + * @return The short value + */ + public static short getMovementRelativeFacingEnumAsShort(MovementRelativeFacing enumVal){ + switch(enumVal){ + case FORWARD: + return 0; + case LEFT: + return 1; + case RIGHT: + return 2; + case BACKWARD: + return 3; + case FORWARD_LEFT: + return 4; + case FORWARD_RIGHT: + return 5; + case BACKWARD_LEFT: + return 6; + case BACKWARD_RIGHT: + return 7; + default: + return 0; + } + } + /** + *

Automatically generated

+ *

+ * Converts a short to the equivalent enum value + *

+ * @param shortVal The short value + * @return The enum value + */ + public static MovementRelativeFacing getMovementRelativeFacingShortAsEnum(short shortVal){ + switch(shortVal){ + case 0: + return MovementRelativeFacing.FORWARD; + case 1: + return MovementRelativeFacing.LEFT; + case 2: + return MovementRelativeFacing.RIGHT; + case 3: + return MovementRelativeFacing.BACKWARD; + case 4: + return MovementRelativeFacing.FORWARD_LEFT; + case 5: + return MovementRelativeFacing.FORWARD_RIGHT; + case 6: + return MovementRelativeFacing.BACKWARD_LEFT; + case 7: + return MovementRelativeFacing.BACKWARD_RIGHT; + default: + return MovementRelativeFacing.FORWARD; + } + } + /** + *

(initially) Automatically generated

+ *

+ * Attaches this tree to the entity. + *

+ * @param entity The entity to attach to + * @param tree The behavior tree to attach + * @param params Optional parameters that will be provided to the constructor + */ + public static ClientEditorMovementTree attachTree(Entity parent, Object ... params){ + ClientEditorMovementTree rVal = new ClientEditorMovementTree(parent,params); + //!!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_CLIENTEDITORMOVEMENTTREE, rVal); + Globals.clientSceneWrapper.getScene().registerBehaviorTree(rVal); + Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_CLIENTEDITORMOVEMENTTREE_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_CLIENTEDITORMOVEMENTTREE_ID); + } + +} diff --git a/src/main/java/electrosphere/entity/state/movement/editor/ServerEditorMovementTree.java b/src/main/java/electrosphere/entity/state/movement/editor/ServerEditorMovementTree.java new file mode 100644 index 00000000..300e7627 --- /dev/null +++ b/src/main/java/electrosphere/entity/state/movement/editor/ServerEditorMovementTree.java @@ -0,0 +1,541 @@ +package electrosphere.entity.state.movement.editor; + + +import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; +import electrosphere.net.parser.net.message.SynchronizationMessage; +import electrosphere.entity.state.gravity.GravityUtils; +import electrosphere.client.entity.camera.CameraEntityUtils; +import electrosphere.engine.Globals; +import electrosphere.entity.types.creature.CreatureUtils; +import electrosphere.game.data.creature.type.movement.EditorMovementSystem; +import electrosphere.entity.Entity; +import electrosphere.entity.EntityDataStrings; +import electrosphere.entity.EntityUtils; +import electrosphere.entity.btree.BehaviorTree; +import electrosphere.entity.state.attack.ServerAttackTree; +import electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementRelativeFacing; +import electrosphere.entity.state.movement.editor.ClientEditorMovementTree.MovementTreeState; +import electrosphere.entity.state.movement.fall.ServerFallTree; +import electrosphere.entity.state.movement.jump.ServerJumpTree; +import electrosphere.entity.state.movement.sprint.ServerSprintTree; +import electrosphere.entity.state.movement.walk.ServerWalkTree; +import electrosphere.entity.state.server.ServerPlayerViewDirTree; +import electrosphere.net.parser.net.message.EntityMessage; +import electrosphere.net.synchronization.annotation.SyncedField; +import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; +import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums; +import electrosphere.net.synchronization.enums.FieldIdEnums; +import electrosphere.renderer.anim.Animation; +import electrosphere.script.utils.AccessTransforms; +import electrosphere.server.datacell.utils.DataCellSearchUtils; +import electrosphere.server.utils.ServerScriptUtils; +import electrosphere.util.math.MathUtils; + +import java.util.concurrent.CopyOnWriteArrayList; + +import org.joml.Quaterniond; +import org.joml.Vector3d; + +@SynchronizedBehaviorTree(name = "serverEditorMovementTree", isServer = true, correspondingTree="clientEditorMovementTree") +/* +Behavior tree for movement in an entity +*/ +public class ServerEditorMovementTree implements BehaviorTree { + + + String animationStartUp = Animation.ANIMATION_MOVEMENT_STARTUP; + String animationMain = Animation.ANIMATION_MOVEMENT_MOVE; + String animationSlowDown = Animation.ANIMATION_MOVEMENT_MOVE; + String animationSprintStart = Animation.ANIMATION_SPRINT_STARTUP; + String animationSprint = Animation.ANIMATION_SPRINT; + String animationSprintWindDown = Animation.ANIMATION_SPRINT_WINDDOWN; + + MovementTreeState state; + @SyncedField + MovementRelativeFacing facing; + + //The data for the movement system + EditorMovementSystem editorMovementSystem; + + ServerSprintTree sprintTree; + ServerJumpTree jumpTree; + ServerFallTree fallTree; + + Entity parent; + + CopyOnWriteArrayList networkMessageQueue = new CopyOnWriteArrayList(); + + long lastUpdateTime = 0; + + //the vector organizing the direction the entity will move in + Vector3d movementVector = new Vector3d(1,0,0); + + + private ServerEditorMovementTree(Entity e, Object ... params){ + //EditorMovementSystem system + state = MovementTreeState.IDLE; + facing = MovementRelativeFacing.FORWARD; + parent = e; + this.editorMovementSystem = (EditorMovementSystem)params[0]; + } + + public MovementTreeState getState(){ + return state; + } + + /** + * Starts the server movement tree + * @param facing The facing dir to start with + */ + public void start(MovementRelativeFacing facing){ + if(canStartMoving()){ + setFacing(facing); + state = MovementTreeState.STARTUP; + //if we aren't the server, alert the server we intend to walk forward + Vector3d position = EntityUtils.getPosition(parent); + Quaterniond rotation = EntityUtils.getRotation(parent); + float velocity = CreatureUtils.getVelocity(parent); + DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( + EntityMessage.constructmoveUpdateMessage( + parent.getId(), + Globals.timekeeper.getNumberOfSimFramesElapsed(), + position.x, + position.y, + position.z, + rotation.x, + rotation.y, + rotation.z, + rotation.w, + velocity, + ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(facing), + 0 //magic number corresponding to state startup + ) + ); + } + } + + /** + * Interrupts the tree + */ + public void interrupt(){ + state = MovementTreeState.IDLE; + CreatureUtils.setVelocity(parent, 0); + } + + /** + * Triggers the move tree to slow down + */ + public void slowdown(){ + state = MovementTreeState.SLOWDOWN; + //if we aren't the server, alert the server we intend to slow down + Vector3d position = EntityUtils.getPosition(parent); + Quaterniond rotation = EntityUtils.getRotation(parent); + float velocity = CreatureUtils.getVelocity(parent); + DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( + EntityMessage.constructmoveUpdateMessage( + parent.getId(), + Globals.timekeeper.getNumberOfSimFramesElapsed(), + position.x, + position.y, + position.z, + rotation.x, + rotation.y, + rotation.z, + rotation.w, + velocity, + ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(facing), + 2 //magic number corresponding to state slowdown + ) + ); + } + + @Override + public void simulate(float deltaTime){ + float maxNaturalVelocity = 0; + if(CreatureUtils.hasVelocity(parent)){ + maxNaturalVelocity = ClientEditorMovementTree.EDITOR_MAX_VELOCITY; + } + Vector3d position = EntityUtils.getPosition(parent); + Vector3d facingVector = CreatureUtils.getFacingVector(parent); + if(ServerPlayerViewDirTree.hasTree(parent)){ + ServerPlayerViewDirTree serverViewTree =ServerPlayerViewDirTree.getTree(parent); + facingVector = CameraEntityUtils.getFacingVec(serverViewTree.getYaw(), serverViewTree.getPitch()); + } + + // + //rotation update + if(this.state != MovementTreeState.IDLE){ + this.movementVector.set(facingVector); + switch(facing){ + case FORWARD: + movementVector.normalize(); + break; + case LEFT: + movementVector.rotateY((float)(90 * Math.PI / 180)).normalize(); + break; + case RIGHT: + movementVector.rotateY((float)(-90 * Math.PI / 180)).normalize(); + break; + case BACKWARD: + movementVector.x = -movementVector.x; + movementVector.z = -movementVector.z; + movementVector.normalize(); + break; + case FORWARD_LEFT: + movementVector.rotateY((float)(45 * Math.PI / 180)).normalize(); + break; + case FORWARD_RIGHT: + movementVector.rotateY((float)(-45 * Math.PI / 180)).normalize(); + break; + case BACKWARD_LEFT: + movementVector.rotateY((float)(135 * Math.PI / 180)).normalize(); + break; + case BACKWARD_RIGHT: + movementVector.rotateY((float)(-135 * Math.PI / 180)).normalize(); + break; + case UP: { + movementVector = MathUtils.getUpVector(); + } break; + case DOWN: { + movementVector = MathUtils.getUpVector().mul(-1); + } break; + } + } + Quaterniond movementQuaternion = new Quaterniond().rotationTo(MathUtils.getOriginVector(), new Vector3d(facingVector.x,0,facingVector.z)).normalize(); + Quaterniond rotation = EntityUtils.getRotation(parent); + //TODO: optimize away and document (I know for the moment if this exception isn't here it will bite me in the ass later) + if(facingVector.length() == 0){ + throw new IllegalStateException("Facing vector length is 0. This will break ODE4J"); + } + + //parse attached network messages + for(EntityMessage message : networkMessageQueue){ + networkMessageQueue.remove(message); + long updateTime = message.gettime(); +// System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ()); + switch(message.getMessageSubtype()){ + case MOVEUPDATE: { + if(updateTime >= lastUpdateTime){ + lastUpdateTime = updateTime; + switch(message.gettreeState()){ + //0 is startup + case 0: { + // System.out.println("Receive move packet from client treestate " + message.gettreeState()); + start(ClientEditorMovementTree.getMovementRelativeFacingShortAsEnum((short)message.getpropertyValueInt())); + } break; + case 2: { + // System.out.println("Receive move packet from client treestate " + message.gettreeState()); + slowdown(); + } break; + default: { + + } break; + } + //we want to always update the server facing vector with where the client says they're facing + EntityUtils.getRotation(parent).set(message.getrotationX(),message.getrotationY(),message.getrotationZ(),message.getrotationW()); + break; + } + } break; + default: + break; + } + } + + // System.out.println(movementVector + " " + velocity * Main.deltaTime); + + //state machine + switch(state){ + case STARTUP: { + CreatureUtils.setFacingVector(parent, facingVector); + rotation.set(movementQuaternion); + //run startup code + this.updateVelocity(); + float velocity = this.getModifiedVelocity(); + //check if can transition state + if(velocity >= maxNaturalVelocity){ + velocity = maxNaturalVelocity; + state = MovementTreeState.MOVE; + CreatureUtils.setVelocity(parent, velocity); + } + position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity))); +// position.set(newPosition); + + GravityUtils.serverAttemptActivateGravity(parent); + + DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( + EntityMessage.constructmoveUpdateMessage( + parent.getId(), + Globals.timekeeper.getNumberOfSimFramesElapsed(), + position.x, + position.y, + position.z, + rotation.x, + rotation.y, + rotation.z, + rotation.w, + velocity, + ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(facing), + 0 + ) + ); + } break; + case MOVE: { + CreatureUtils.setFacingVector(parent, facingVector); + rotation.set(movementQuaternion); + this.updateVelocity(); + float velocity = this.getModifiedVelocity(); + position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity))); + + GravityUtils.serverAttemptActivateGravity(parent); + + DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( + EntityMessage.constructmoveUpdateMessage( + parent.getId(), + Globals.timekeeper.getNumberOfSimFramesElapsed(), + position.x, + position.y, + position.z, + rotation.x, + rotation.y, + rotation.z, + rotation.w, + velocity, + ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(facing), + 1 + ) + ); + + //tell script engine we moved + ServerScriptUtils.fireSignalOnEntity(parent, "entityGroundMove", AccessTransforms.getVector(position)); + } break; + case SLOWDOWN: { + CreatureUtils.setFacingVector(parent, facingVector); + rotation.set(movementQuaternion); + //velocity stuff + this.updateVelocity(); + float velocity = this.getModifiedVelocity(); + position.set(new Vector3d(position).add(new Vector3d(movementVector).mul(velocity))); + //check if can transition state + if(velocity <= 0){ + velocity = 0; + state = MovementTreeState.IDLE; + } + // PhysicsEntityUtils.getDBody(parent).addForce( + // movementVector.x * velocity * Globals.timekeeper.getSimFrameTime(), + // linearVelocity.get1(), + // movementVector.z * velocity * Globals.timekeeper.getSimFrameTime() + // ); +// position.set(newPosition); + + GravityUtils.serverAttemptActivateGravity(parent); + + DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( + EntityMessage.constructmoveUpdateMessage( + parent.getId(), + Globals.timekeeper.getNumberOfSimFramesElapsed(), + position.x, + position.y, + position.z, + rotation.x, + rotation.y, + rotation.z, + rotation.w, + velocity, + ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(facing), + 2 + ) + ); + } break; + case IDLE: { + } break; + } + } + + /** + * Updates the velocity and acceleration + */ + private void updateVelocity(){ + float velocity = CreatureUtils.getVelocity(parent); + float acceleration = ClientEditorMovementTree.EDITOR_ACCEL; + float maxNaturalVelocity = ClientEditorMovementTree.EDITOR_MAX_VELOCITY; + switch(this.state){ + case IDLE: { + } break; + case STARTUP: { + //run startup code + velocity = velocity + acceleration * (float)Globals.timekeeper.getSimFrameTime(); + CreatureUtils.setVelocity(parent, velocity); + } break; + case MOVE: { + if(velocity != maxNaturalVelocity){ + velocity = maxNaturalVelocity; + CreatureUtils.setVelocity(parent, velocity); + } + } break; + case SLOWDOWN: { + //velocity stuff + velocity = velocity - acceleration * (float)Globals.timekeeper.getSimFrameTime(); + CreatureUtils.setVelocity(parent, velocity); + } break; + } + } + + /** + * Gets the velocity to move at + * @return The velocity + */ + private float getModifiedVelocity(){ + float velocity = CreatureUtils.getVelocity(parent); + float sprintModifier = 1.0f; + float walkModifier = 1.0f; + float attackModifier = 1.0f; + if(ServerWalkTree.getServerWalkTree(parent) != null && ServerWalkTree.getServerWalkTree(parent).isWalking()){ + walkModifier = ServerWalkTree.getServerWalkTree(parent).getModifier(); + } + if(ServerSprintTree.getServerSprintTree(parent) != null && ServerSprintTree.getServerSprintTree(parent).isSprinting()){ + sprintModifier = ServerSprintTree.getServerSprintTree(parent).getSprintSystem().getModifier(); + } + if(ServerAttackTree.getServerAttackTree(parent) != null){ + attackModifier = (float)ServerAttackTree.getServerAttackTree(parent).getMovementPenalty(); + } + return velocity * sprintModifier * walkModifier * attackModifier; + } + + public void addNetworkMessage(EntityMessage networkMessage) { + networkMessageQueue.add(networkMessage); + } + + /** + * Checks if the tree is moving + * @return true if is moving, false otherwise + */ + public boolean isMoving(){ + return this.state != MovementTreeState.IDLE; + } + + /** + * Checks if the tree CAN start moving + * @return true if CAN start moving, false otherwise + */ + public boolean canStartMoving(){ + boolean rVal = true; + return rVal; + } + + public void setAnimationStartUp(String animationStartUp) { + this.animationStartUp = animationStartUp; + } + + public void setAnimationMain(String animationMain) { + this.animationMain = animationMain; + } + + public void setAnimationSlowDown(String animationSlowDown) { + this.animationSlowDown = animationSlowDown; + } + + public void setAnimationSprintStartUp(String animationSprintStartUp){ + this.animationSprintStart = animationSprintStartUp; + } + + public void setAnimationSprint(String animationSprint){ + this.animationSprint = animationSprint; + } + + public void setAnimationSprintWindDown(String animationSprintWindDown){ + this.animationSprintWindDown = animationSprintWindDown; + } + + public void setServerSprintTree(ServerSprintTree sprintTree){ + this.sprintTree = sprintTree; + } + + public void setServerJumpTree(ServerJumpTree jumpTree){ + this.jumpTree = jumpTree; + } + + public void setServerFallTree(ServerFallTree fallTree){ + this.fallTree = fallTree; + } + + /** + * Gets the maximum velocity of an entity + * @param entity + * @param editorMovementSystem + * @return + */ + public static float getMaximumVelocity(Entity entity, EditorMovementSystem editorMovementSystem, MovementRelativeFacing facing){ + float maxVelocity = ClientEditorMovementTree.EDITOR_MAX_VELOCITY; + return maxVelocity; + } + + /** + *

Automatically generated

+ *

+ * Gets facing. + *

+ */ + public MovementRelativeFacing getFacing(){ + return facing; + } + + + + /** + *

+ * Gets the ServerEditorMovementTree of the entity + *

+ * @param entity the entity + * @return The ServerEditorMovementTree + */ + public static ServerEditorMovementTree getServerEditorMovementTree(Entity entity){ + return (ServerEditorMovementTree)entity.getData(EntityDataStrings.TREE_SERVEREDITORMOVEMENTTREE); + } + + /** + *

(initially) Automatically generated

+ *

+ * Attaches this tree to the entity. + *

+ * @param entity The entity to attach to + * @param tree The behavior tree to attach + * @param params Optional parameters that will be provided to the constructor + */ + public static ServerEditorMovementTree attachTree(Entity parent, Object ... params){ + ServerEditorMovementTree rVal = new ServerEditorMovementTree(parent,params); + //!!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_SERVEREDITORMOVEMENTTREE, rVal); + Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_SERVEREDITORMOVEMENTTREE_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_SERVEREDITORMOVEMENTTREE_ID); + } + + /** + *

Automatically generated

+ *

+ * Sets facing and handles the synchronization logic for it. + *

+ * @param facing The value to set facing to. + */ + public void setFacing(MovementRelativeFacing facing){ + this.facing = facing; + int value = ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(facing); + if(DataCellSearchUtils.getEntityDataCell(parent) != null){ + DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), BehaviorTreeIdEnums.BTREE_SERVEREDITORMOVEMENTTREE_ID, FieldIdEnums.TREE_SERVEREDITORMOVEMENTTREE_SYNCEDFIELD_FACING_ID, value)); + } + } + +} diff --git a/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java b/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java index a1343258..8e11d8e6 100644 --- a/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java +++ b/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java @@ -38,6 +38,8 @@ import electrosphere.entity.state.inventory.UnrelationalInventoryState; import electrosphere.entity.state.life.ClientLifeTree; import electrosphere.entity.state.life.ServerLifeTree; import electrosphere.entity.state.light.ClientPointLightComponent; +import electrosphere.entity.state.movement.editor.ClientEditorMovementTree; +import electrosphere.entity.state.movement.editor.ServerEditorMovementTree; import electrosphere.entity.state.movement.fall.ClientFallTree; import electrosphere.entity.state.movement.fall.ServerFallTree; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree; @@ -61,6 +63,7 @@ import electrosphere.game.data.common.CommonEntityType; import electrosphere.game.data.creature.type.CreatureData; import electrosphere.game.data.creature.type.SprintSystem; import electrosphere.game.data.creature.type.attack.AttackMove; +import electrosphere.game.data.creature.type.movement.EditorMovementSystem; import electrosphere.game.data.creature.type.movement.FallMovementSystem; import electrosphere.game.data.creature.type.movement.GroundMovementSystem; import electrosphere.game.data.creature.type.movement.JumpMovementSystem; @@ -256,6 +259,9 @@ public class CommonEntityUtils { case WalkMovementSystem.WALK_MOVEMENT_SYSTEM: { ClientWalkTree.attachTree(entity, (WalkMovementSystem)movementSystem); } break; + case EditorMovementSystem.EDITOR_MOVEMENT_SYSTEM: { + ClientEditorMovementTree.attachTree(entity, (EditorMovementSystem)movementSystem); + } break; } } } @@ -548,6 +554,9 @@ public class CommonEntityUtils { case WalkMovementSystem.WALK_MOVEMENT_SYSTEM: { ServerWalkTree.attachTree(entity, (WalkMovementSystem)movementSystem); } break; + case EditorMovementSystem.EDITOR_MOVEMENT_SYSTEM: { + ServerEditorMovementTree.attachTree(entity, (EditorMovementSystem)movementSystem); + } break; } } } diff --git a/src/main/java/electrosphere/game/data/creature/type/movement/EditorMovementSystem.java b/src/main/java/electrosphere/game/data/creature/type/movement/EditorMovementSystem.java new file mode 100644 index 00000000..57166852 --- /dev/null +++ b/src/main/java/electrosphere/game/data/creature/type/movement/EditorMovementSystem.java @@ -0,0 +1,25 @@ +package electrosphere.game.data.creature.type.movement; + +/** + * Data about the editor movement system + */ +public class EditorMovementSystem implements MovementSystem { + + //move system type string + public static final String EDITOR_MOVEMENT_SYSTEM = "EDITOR"; + + //type of move system + String type; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + + + +} diff --git a/src/main/java/electrosphere/game/data/creature/type/movement/MovementSystemSerializer.java b/src/main/java/electrosphere/game/data/creature/type/movement/MovementSystemSerializer.java index f5500563..cd0ccb0d 100644 --- a/src/main/java/electrosphere/game/data/creature/type/movement/MovementSystemSerializer.java +++ b/src/main/java/electrosphere/game/data/creature/type/movement/MovementSystemSerializer.java @@ -13,16 +13,24 @@ public class MovementSystemSerializer implements JsonDeserializer