diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 5f285ea8..8f944bb0 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -2067,6 +2067,7 @@ Delete ActorShaderMask Fix string carousels Fix sprint animation data Color uniform on meshes +Fall and gravity tree fixes diff --git a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java index 0bda9f13..c06f2f37 100644 --- a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java +++ b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java @@ -21,6 +21,8 @@ import electrosphere.entity.state.collidable.ClientCollidableTree; import electrosphere.entity.state.collidable.MultiShapeTriGeomData; import electrosphere.entity.state.collidable.ServerCollidableTree; import electrosphere.entity.state.collidable.TriGeomData; +import electrosphere.entity.state.gravity.ClientGravityTree; +import electrosphere.entity.state.gravity.ServerGravityTree; import electrosphere.entity.state.physicssync.ClientPhysicsSyncTree; import electrosphere.entity.state.physicssync.ServerPhysicsSyncTree; import electrosphere.server.datacell.Realm; @@ -369,6 +371,9 @@ public class PhysicsEntityUtils { //if we successfully attached the body, add a sync tree if(rigidBody != null){ ClientPhysicsSyncTree.attachTree(rVal); + if(ClientGravityTree.hasClientGravityTree(rVal)){ + ClientGravityTree.getClientGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal)); + } } } CollisionEngine.unlockOde(); @@ -693,6 +698,9 @@ public class PhysicsEntityUtils { //if we successfully attached the body, add a sync tree if(rigidBody != null){ ServerPhysicsSyncTree.attachTree(rVal); + if(ServerGravityTree.hasServerGravityTree(rVal)){ + ServerGravityTree.getServerGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal)); + } } } CollisionEngine.unlockOde(); diff --git a/src/main/java/electrosphere/entity/state/gravity/ClientGravityTree.java b/src/main/java/electrosphere/entity/state/gravity/ClientGravityTree.java index 8fda34b6..48a4341b 100644 --- a/src/main/java/electrosphere/entity/state/gravity/ClientGravityTree.java +++ b/src/main/java/electrosphere/entity/state/gravity/ClientGravityTree.java @@ -89,13 +89,13 @@ public class ClientGravityTree implements BehaviorTree { //state machine switch(state){ case ACTIVE: - if(this.hadGroundCollision() || !this.bodyIsActive()){ + if(this.hadGroundCollision() || !this.bodyIsActive() || this.body == null){ ClientJumpTree jumpTree; - if((jumpTree = ClientJumpTree.getClientJumpTree(parent))!=null){ + if((jumpTree = ClientJumpTree.getClientJumpTree(parent))!=null && jumpTree.isJumping()){ jumpTree.land(); } ClientFallTree fallTree; - if((fallTree = ClientFallTree.getFallTree(parent))!=null){ + if((fallTree = ClientFallTree.getFallTree(parent))!=null && fallTree.isFalling()){ fallTree.land(); } frameCurrent = 0; @@ -108,7 +108,6 @@ public class ClientGravityTree implements BehaviorTree { } } frameCurrent++; - } break; case NOT_ACTIVE: @@ -151,6 +150,24 @@ public class ClientGravityTree implements BehaviorTree { } return rVal; } + + /** + * Checks if the physics on the tree is valid + * @return true if it is valid, false otherwise + */ + public boolean physicsIsValid(){ + return collidable != null && body != null; + } + + /** + * Updates the physics pair in this tree + * @param collidable The collidable + * @param body The rigid body + */ + public void updatePhysicsPair(Collidable collidable, DBody body){ + this.collidable = collidable; + this.body = body; + } /** *
(initially) Automatically generated
diff --git a/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java b/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java index 1a2707ab..4cd07c26 100644 --- a/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java +++ b/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java @@ -173,6 +173,24 @@ public class ServerGravityTree implements BehaviorTree { } return rVal; } + + /** + * Checks if the physics on the tree is valid + * @return true if it is valid, false otherwise + */ + public boolean physicsIsValid(){ + return collidable != null && body != null; + } + + /** + * Updates the physics pair in this tree + * @param collidable The collidable + * @param body The rigid body + */ + public void updatePhysicsPair(Collidable collidable, DBody body){ + this.collidable = collidable; + this.body = body; + } /** *Automatically generated
diff --git a/src/main/java/electrosphere/entity/state/movement/fall/ClientFallTree.java b/src/main/java/electrosphere/entity/state/movement/fall/ClientFallTree.java index 1af795c9..c44351a8 100644 --- a/src/main/java/electrosphere/entity/state/movement/fall/ClientFallTree.java +++ b/src/main/java/electrosphere/entity/state/movement/fall/ClientFallTree.java @@ -2,6 +2,8 @@ package electrosphere.entity.state.movement.fall; import electrosphere.audio.movement.MovementAudioService.InteractionType; import electrosphere.client.terrain.sampling.ClientVoxelSampler; +import electrosphere.collision.PhysicsEntityUtils; +import electrosphere.collision.collidable.Collidable; import electrosphere.data.entity.creature.movement.FallMovementSystem; import electrosphere.engine.Globals; import electrosphere.entity.Entity; @@ -12,6 +14,7 @@ import electrosphere.entity.btree.StateTransitionUtil; import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem; import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.client.firstPerson.FirstPersonTree; +import electrosphere.entity.state.collidable.Impulse; import electrosphere.entity.state.gravity.ClientGravityTree; import electrosphere.entity.state.movement.jump.ClientJumpTree; import electrosphere.renderer.actor.Actor; @@ -125,11 +128,29 @@ public class ClientFallTree implements BehaviorTree { boolean rVal = frameCurrent > ServerFallTree.MIN_FRAMES_BEFORE_ACTIVATION_SCAN && ClientGravityTree.getClientGravityTree(parent).isActive() && - !isPlayingJump + !isPlayingJump && + !this.hadGroundCollision() ; return rVal; } + /** + * Checks if the entity had a collision with the ground this frame + * @return true if it had a collision with the ground, false otherwise + */ + public boolean hadGroundCollision(){ + boolean rVal = false; + if(PhysicsEntityUtils.getCollidable(parent) != null){ + for(Impulse impulse : PhysicsEntityUtils.getCollidable(parent).getImpulses()){ + if(impulse.getType().equals(Collidable.TYPE_STATIC)){ + rVal = true; + break; + } + } + } + return rVal; + } + /** * Triggers the falling tree to land */ diff --git a/src/test/java/electrosphere/collision/collision/PhysicsEntityUtilsTests.java b/src/test/java/electrosphere/collision/collision/PhysicsEntityUtilsTests.java new file mode 100644 index 00000000..0f7f1fd2 --- /dev/null +++ b/src/test/java/electrosphere/collision/collision/PhysicsEntityUtilsTests.java @@ -0,0 +1,43 @@ +package electrosphere.collision.collision; + +import static electrosphere.test.testutils.Assertions.assertEventually; + +import org.joml.Vector3d; + +import electrosphere.collision.PhysicsEntityUtils; +import electrosphere.engine.Globals; +import electrosphere.entity.Entity; +import electrosphere.entity.types.EntityTypes.EntityType; +import electrosphere.entity.types.creature.CreatureUtils; +import electrosphere.entity.types.creature.ObjectTemplate; +import electrosphere.test.annotations.IntegrationTest; +import electrosphere.test.template.EntityTestTemplate; +import electrosphere.test.testutils.TestEngineUtils; + +/** + * Tests for physics entity utils + */ +public class PhysicsEntityUtilsTests extends EntityTestTemplate { + + @IntegrationTest + public void test_server_RigidBody_NotNull(){ + Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human")); + + //warm up engine + TestEngineUtils.simulateFrames(3); + + assertEventually(() -> PhysicsEntityUtils.getDBody(serverEntity) != null); + } + + @IntegrationTest + public void test_client_RigidBody_NotNull(){ + Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human")); + Entity clientEntity = TestEngineUtils.getClientEquivalent(serverEntity); + + //warm up engine + TestEngineUtils.simulateFrames(3); + + assertEventually(() -> PhysicsEntityUtils.getDBody(clientEntity) != null); + } + +} diff --git a/src/test/java/electrosphere/entity/state/gravity/ClientGravityTreeTests.java b/src/test/java/electrosphere/entity/state/gravity/ClientGravityTreeTests.java index de45c199..2f811844 100644 --- a/src/test/java/electrosphere/entity/state/gravity/ClientGravityTreeTests.java +++ b/src/test/java/electrosphere/entity/state/gravity/ClientGravityTreeTests.java @@ -29,6 +29,15 @@ public class ClientGravityTreeTests extends EntityTestTemplate { assertEquals(false, clientGravityTree.isActive()); } + @IntegrationTest + public void physicsIsValid_eventually_true(){ + Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human")); + Entity clientEntity = TestEngineUtils.getClientEquivalent(serverEntity); + + ClientGravityTree clientGravityTree = ClientGravityTree.getClientGravityTree(clientEntity); + assertEventually(() -> clientGravityTree.physicsIsValid()); + } + @IntegrationTest public void activates_on_jump(){ Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human")); diff --git a/src/test/java/electrosphere/entity/state/gravity/ServerGravityTreeTests.java b/src/test/java/electrosphere/entity/state/gravity/ServerGravityTreeTests.java index ccb5416c..cb26e130 100644 --- a/src/test/java/electrosphere/entity/state/gravity/ServerGravityTreeTests.java +++ b/src/test/java/electrosphere/entity/state/gravity/ServerGravityTreeTests.java @@ -29,6 +29,14 @@ public class ServerGravityTreeTests extends EntityTestTemplate { assertTrue(serverGravityTree.isActive()); } + @IntegrationTest + public void physicsIsValid_eventually_true(){ + Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human")); + + ServerGravityTree serverGravityTree = ServerGravityTree.getServerGravityTree(serverEntity); + assertEventually(() -> serverGravityTree.physicsIsValid()); + } + @IntegrationTest public void isActive_AfterOneFrame_false(){ Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human"));