editor entity
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-10-22 11:29:14 -04:00
parent c8e3a251d5
commit 3b521e3197
23 changed files with 1499 additions and 97 deletions

View File

@ -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"
]
}

View File

@ -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" : []
}

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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());
}
}
}
}

View File

@ -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();
}
}
}});

View File

@ -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;

View File

@ -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());

View File

@ -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());

View File

@ -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());

View File

@ -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<String> races = Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces();
String race = races.get(new Random().nextInt(races.size()));
String race = "editor";
if(!isEditor){
List<String> 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()){

View File

@ -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";

View File

@ -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<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
//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;
}
/**
* <p> Automatically generated </p>
* <p>
* Gets facing.
* </p>
*/
public MovementRelativeFacing getFacing(){
return facing;
}
/**
* <p> Automatically generated </p>
* <p>
* Sets facing and handles the synchronization logic for it.
* </p>
* @param facing The value to set facing to.
*/
public void setFacing(MovementRelativeFacing facing){
this.facing = facing;
}
/**
* <p>
* Gets the ClientEditorMovementTree of the entity
* </p>
* @param entity the entity
* @return The ClientEditorMovementTree
*/
public static ClientEditorMovementTree getClientEditorMovementTree(Entity entity){
return (ClientEditorMovementTree)entity.getData(EntityDataStrings.TREE_CLIENTEDITORMOVEMENTTREE);
}
/**
* <p> Automatically generated </p>
* <p>
* Converts this enum type to an equivalent short value
* </p>
* @param enumVal The enum value
* @return The short value
*/
public static short 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;
}
}
/**
* <p> Automatically generated </p>
* <p>
* Converts a short to the equivalent enum value
* </p>
* @param shortVal The short value
* @return The enum value
*/
public static 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;
}
}
/**
* <p> (initially) Automatically generated </p>
* <p>
* Attaches this tree to the entity.
* </p>
* @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;
}
/**
* <p> Automatically generated </p>
* <p>
* Detatches this tree from the entity.
* </p>
* @param entity The entity to detach to
* @param tree The behavior tree to detach
*/
public static void detachTree(Entity entity, BehaviorTree tree){
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_CLIENTEDITORMOVEMENTTREE_ID);
}
}

View File

@ -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<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
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;
}
/**
* <p> Automatically generated </p>
* <p>
* Gets facing.
* </p>
*/
public MovementRelativeFacing getFacing(){
return facing;
}
/**
* <p>
* Gets the ServerEditorMovementTree of the entity
* </p>
* @param entity the entity
* @return The ServerEditorMovementTree
*/
public static ServerEditorMovementTree getServerEditorMovementTree(Entity entity){
return (ServerEditorMovementTree)entity.getData(EntityDataStrings.TREE_SERVEREDITORMOVEMENTTREE);
}
/**
* <p> (initially) Automatically generated </p>
* <p>
* Attaches this tree to the entity.
* </p>
* @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;
}
/**
* <p> Automatically generated </p>
* <p>
* Detatches this tree from the entity.
* </p>
* @param entity The entity to detach to
* @param tree The behavior tree to detach
*/
public static void detachTree(Entity entity, BehaviorTree tree){
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_SERVEREDITORMOVEMENTTREE_ID);
}
/**
* <p> Automatically generated </p>
* <p>
* Sets facing and handles the synchronization logic for it.
* </p>
* @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));
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -13,16 +13,24 @@ public class MovementSystemSerializer implements JsonDeserializer<MovementSystem
public MovementSystem deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
switch(json.getAsJsonObject().get("type").getAsString()){
case GroundMovementSystem.GROUND_MOVEMENT_SYSTEM:
return context.deserialize(json, GroundMovementSystem.class);
case JumpMovementSystem.JUMP_MOVEMENT_SYSTEM:
return context.deserialize(json, JumpMovementSystem.class);
case FallMovementSystem.FALL_MOVEMENT_SYSTEM:
return context.deserialize(json, FallMovementSystem.class);
case AirplaneMovementSystem.AIRPLANE_MOVEMENT_SYSTEM:
return context.deserialize(json, AirplaneMovementSystem.class);
case WalkMovementSystem.WALK_MOVEMENT_SYSTEM:
return context.deserialize(json, WalkMovementSystem.class);
case GroundMovementSystem.GROUND_MOVEMENT_SYSTEM: {
return context.deserialize(json, GroundMovementSystem.class);
}
case JumpMovementSystem.JUMP_MOVEMENT_SYSTEM: {
return context.deserialize(json, JumpMovementSystem.class);
}
case FallMovementSystem.FALL_MOVEMENT_SYSTEM: {
return context.deserialize(json, FallMovementSystem.class);
}
case AirplaneMovementSystem.AIRPLANE_MOVEMENT_SYSTEM: {
return context.deserialize(json, AirplaneMovementSystem.class);
}
case WalkMovementSystem.WALK_MOVEMENT_SYSTEM: {
return context.deserialize(json, WalkMovementSystem.class);
}
case EditorMovementSystem.EDITOR_MOVEMENT_SYSTEM: {
return context.deserialize(json, EditorMovementSystem.class);
}
}
return null;
}

View File

@ -1,6 +1,7 @@
package electrosphere.net.synchronization.client;
import electrosphere.entity.state.movement.editor.ClientEditorMovementTree;
import electrosphere.util.Utilities;
import electrosphere.entity.state.equip.ClientToolbarState;
import electrosphere.entity.state.stance.ClientStanceComponent;
@ -221,6 +222,14 @@ public class ClientSynchronizationManager {
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVEREDITORMOVEMENTTREE_ID: {
switch(message.getfieldId()){
case FieldIdEnums.TREE_SERVEREDITORMOVEMENTTREE_SYNCEDFIELD_FACING_ID:{
ClientEditorMovementTree tree = ClientEditorMovementTree.getClientEditorMovementTree(entity);
tree.setFacing(ClientEditorMovementTree.getMovementRelativeFacingShortAsEnum((short)message.getbTreeValue()));
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGROUNDMOVEMENTTREE_ID: {
switch(message.getfieldId()){
case FieldIdEnums.TREE_SERVERGROUNDMOVEMENTTREE_SYNCEDFIELD_FACING_ID:{

View File

@ -21,6 +21,8 @@ public class BehaviorTreeIdEnums {
public static final int BTREE_SERVERLIFETREE_ID = 13;
public static final int BTREE_CLIENTSTANCECOMPONENT_ID = 20;
public static final int BTREE_SERVERSTANCECOMPONENT_ID = 21;
public static final int BTREE_CLIENTEDITORMOVEMENTTREE_ID = 24;
public static final int BTREE_SERVEREDITORMOVEMENTTREE_ID = 25;
public static final int BTREE_CLIENTGROUNDMOVEMENTTREE_ID = 10;
public static final int BTREE_SERVERGROUNDMOVEMENTTREE_ID = 11;
public static final int BTREE_CLIENTJUMPTREE_ID = 14;

View File

@ -25,6 +25,8 @@ public class FieldIdEnums {
public static final int TREE_SERVERLIFETREE_SYNCEDFIELD_STATE_ID = 17;
public static final int TREE_CLIENTSTANCECOMPONENT_SYNCEDFIELD_STATE_ID = 28;
public static final int TREE_SERVERSTANCECOMPONENT_SYNCEDFIELD_STATE_ID = 29;
public static final int TREE_CLIENTEDITORMOVEMENTTREE_SYNCEDFIELD_FACING_ID = 32;
public static final int TREE_SERVEREDITORMOVEMENTTREE_SYNCEDFIELD_FACING_ID = 33;
public static final int TREE_CLIENTGROUNDMOVEMENTTREE_SYNCEDFIELD_FACING_ID = 14;
public static final int TREE_SERVERGROUNDMOVEMENTTREE_SYNCEDFIELD_FACING_ID = 15;
public static final int TREE_CLIENTJUMPTREE_SYNCEDFIELD_STATE_ID = 18;

View File

@ -1,6 +1,8 @@
package electrosphere.net.synchronization.transport;
import electrosphere.entity.state.movement.editor.ServerEditorMovementTree;
import electrosphere.entity.state.movement.editor.ClientEditorMovementTree;
import electrosphere.util.Utilities;
import electrosphere.entity.state.equip.ServerToolbarState;
import electrosphere.entity.state.equip.ClientToolbarState;
@ -102,6 +104,10 @@ public class StateCollection {
ServerStanceComponent tree = ServerStanceComponent.getServerStanceComponent(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVERSTANCECOMPONENT_ID,FieldIdEnums.TREE_SERVERSTANCECOMPONENT_SYNCEDFIELD_STATE_ID,ClientStanceComponent.getCombatStanceEnumAsShort(tree.getState())));
} break;
case BehaviorTreeIdEnums.BTREE_SERVEREDITORMOVEMENTTREE_ID: {
ServerEditorMovementTree tree = ServerEditorMovementTree.getServerEditorMovementTree(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVEREDITORMOVEMENTTREE_ID,FieldIdEnums.TREE_SERVEREDITORMOVEMENTTREE_SYNCEDFIELD_FACING_ID,ClientEditorMovementTree.getMovementRelativeFacingEnumAsShort(tree.getFacing())));
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGROUNDMOVEMENTTREE_ID: {
ServerGroundMovementTree tree = ServerGroundMovementTree.getServerGroundMovementTree(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVERGROUNDMOVEMENTTREE_ID,FieldIdEnums.TREE_SERVERGROUNDMOVEMENTTREE_SYNCEDFIELD_FACING_ID,ClientGroundMovementTree.getMovementRelativeFacingEnumAsShort(tree.getFacing())));
@ -202,6 +208,14 @@ public class StateCollection {
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVEREDITORMOVEMENTTREE_ID: {
ClientEditorMovementTree tree = ClientEditorMovementTree.getClientEditorMovementTree(entity);
switch(syncedValue.getFieldId()){
case(FieldIdEnums.TREE_SERVEREDITORMOVEMENTTREE_SYNCEDFIELD_FACING_ID): {
tree.setFacing(ClientEditorMovementTree.getMovementRelativeFacingShortAsEnum(((Double)syncedValue.getValue()).shortValue()));
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGROUNDMOVEMENTTREE_ID: {
ClientGroundMovementTree tree = ClientGroundMovementTree.getClientGroundMovementTree(entity);
switch(syncedValue.getFieldId()){

View File

@ -195,8 +195,10 @@ public class Realm {
protected void simulate(){
//
//simulate bullet physics engine step
collisionEngine.simulatePhysics((float)Globals.timekeeper.getSimFrameTime());
collisionEngine.updateDynamicObjectTransforms();
if(Globals.RUN_PHYSICS){
collisionEngine.simulatePhysics((float)Globals.timekeeper.getSimFrameTime());
collisionEngine.updateDynamicObjectTransforms();
}
//
//hitbox sim
hitboxManager.simulate();