fall and gravity tree fixes
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-05-29 18:40:16 -04:00
parent ccd10c9665
commit bc29ea728e
8 changed files with 130 additions and 5 deletions

View File

@ -2067,6 +2067,7 @@ Delete ActorShaderMask
Fix string carousels Fix string carousels
Fix sprint animation data Fix sprint animation data
Color uniform on meshes Color uniform on meshes
Fall and gravity tree fixes

View File

@ -21,6 +21,8 @@ import electrosphere.entity.state.collidable.ClientCollidableTree;
import electrosphere.entity.state.collidable.MultiShapeTriGeomData; import electrosphere.entity.state.collidable.MultiShapeTriGeomData;
import electrosphere.entity.state.collidable.ServerCollidableTree; import electrosphere.entity.state.collidable.ServerCollidableTree;
import electrosphere.entity.state.collidable.TriGeomData; 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.ClientPhysicsSyncTree;
import electrosphere.entity.state.physicssync.ServerPhysicsSyncTree; import electrosphere.entity.state.physicssync.ServerPhysicsSyncTree;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
@ -369,6 +371,9 @@ public class PhysicsEntityUtils {
//if we successfully attached the body, add a sync tree //if we successfully attached the body, add a sync tree
if(rigidBody != null){ if(rigidBody != null){
ClientPhysicsSyncTree.attachTree(rVal); ClientPhysicsSyncTree.attachTree(rVal);
if(ClientGravityTree.hasClientGravityTree(rVal)){
ClientGravityTree.getClientGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal));
}
} }
} }
CollisionEngine.unlockOde(); CollisionEngine.unlockOde();
@ -693,6 +698,9 @@ public class PhysicsEntityUtils {
//if we successfully attached the body, add a sync tree //if we successfully attached the body, add a sync tree
if(rigidBody != null){ if(rigidBody != null){
ServerPhysicsSyncTree.attachTree(rVal); ServerPhysicsSyncTree.attachTree(rVal);
if(ServerGravityTree.hasServerGravityTree(rVal)){
ServerGravityTree.getServerGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal));
}
} }
} }
CollisionEngine.unlockOde(); CollisionEngine.unlockOde();

View File

@ -89,13 +89,13 @@ public class ClientGravityTree implements BehaviorTree {
//state machine //state machine
switch(state){ switch(state){
case ACTIVE: case ACTIVE:
if(this.hadGroundCollision() || !this.bodyIsActive()){ if(this.hadGroundCollision() || !this.bodyIsActive() || this.body == null){
ClientJumpTree jumpTree; ClientJumpTree jumpTree;
if((jumpTree = ClientJumpTree.getClientJumpTree(parent))!=null){ if((jumpTree = ClientJumpTree.getClientJumpTree(parent))!=null && jumpTree.isJumping()){
jumpTree.land(); jumpTree.land();
} }
ClientFallTree fallTree; ClientFallTree fallTree;
if((fallTree = ClientFallTree.getFallTree(parent))!=null){ if((fallTree = ClientFallTree.getFallTree(parent))!=null && fallTree.isFalling()){
fallTree.land(); fallTree.land();
} }
frameCurrent = 0; frameCurrent = 0;
@ -108,7 +108,6 @@ public class ClientGravityTree implements BehaviorTree {
} }
} }
frameCurrent++; frameCurrent++;
} }
break; break;
case NOT_ACTIVE: case NOT_ACTIVE:
@ -152,6 +151,24 @@ public class ClientGravityTree implements BehaviorTree {
return rVal; 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;
}
/** /**
* <p> (initially) Automatically generated </p> * <p> (initially) Automatically generated </p>
* <p> * <p>

View File

@ -174,6 +174,24 @@ public class ServerGravityTree implements BehaviorTree {
return rVal; 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;
}
/** /**
* <p> Automatically generated </p> * <p> Automatically generated </p>
* <p> * <p>

View File

@ -2,6 +2,8 @@ package electrosphere.entity.state.movement.fall;
import electrosphere.audio.movement.MovementAudioService.InteractionType; import electrosphere.audio.movement.MovementAudioService.InteractionType;
import electrosphere.client.terrain.sampling.ClientVoxelSampler; import electrosphere.client.terrain.sampling.ClientVoxelSampler;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.data.entity.creature.movement.FallMovementSystem; import electrosphere.data.entity.creature.movement.FallMovementSystem;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
@ -12,6 +14,7 @@ import electrosphere.entity.btree.StateTransitionUtil;
import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem; import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem;
import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.AnimationPriorities;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.gravity.ClientGravityTree; import electrosphere.entity.state.gravity.ClientGravityTree;
import electrosphere.entity.state.movement.jump.ClientJumpTree; import electrosphere.entity.state.movement.jump.ClientJumpTree;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
@ -125,11 +128,29 @@ public class ClientFallTree implements BehaviorTree {
boolean rVal = boolean rVal =
frameCurrent > ServerFallTree.MIN_FRAMES_BEFORE_ACTIVATION_SCAN && frameCurrent > ServerFallTree.MIN_FRAMES_BEFORE_ACTIVATION_SCAN &&
ClientGravityTree.getClientGravityTree(parent).isActive() && ClientGravityTree.getClientGravityTree(parent).isActive() &&
!isPlayingJump !isPlayingJump &&
!this.hadGroundCollision()
; ;
return rVal; 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 * Triggers the falling tree to land
*/ */

View File

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

View File

@ -29,6 +29,15 @@ public class ClientGravityTreeTests extends EntityTestTemplate {
assertEquals(false, clientGravityTree.isActive()); 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 @IntegrationTest
public void activates_on_jump(){ public void activates_on_jump(){
Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human")); Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human"));

View File

@ -29,6 +29,14 @@ public class ServerGravityTreeTests extends EntityTestTemplate {
assertTrue(serverGravityTree.isActive()); 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 @IntegrationTest
public void isActive_AfterOneFrame_false(){ public void isActive_AfterOneFrame_false(){
Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human")); Entity serverEntity = CreatureUtils.serverSpawnBasicCreature(Globals.serverState.realmManager.first(), new Vector3d(), "human", ObjectTemplate.createDefault(EntityType.CREATURE, "human"));