work on moving hitboxes to ode4j handling

This commit is contained in:
austin 2024-06-07 17:50:49 -04:00
parent b1d79dbc16
commit a30ac75573
57 changed files with 1788 additions and 859 deletions

View File

@ -18,7 +18,8 @@
"renderResolutionX": 1920, "renderResolutionX": 1920,
"renderResolutionY": 1080, "renderResolutionY": 1080,
"graphicsDebugDrawCollisionSpheres" : false, "graphicsDebugDrawCollisionSpheresClient" : false,
"graphicsDebugDrawCollisionSpheresServer" : false,
"graphicsDebugDrawPhysicsObjects" : false, "graphicsDebugDrawPhysicsObjects" : false,
"graphicsDebugDrawMovementVectors" : false, "graphicsDebugDrawMovementVectors" : false,
"graphicsDebugDrawNavmesh" : false, "graphicsDebugDrawNavmesh" : false,

View File

@ -5,32 +5,37 @@
"hitboxes" : [ "hitboxes" : [
{ {
"type": "hurt", "type": "hurt",
"bone": "Bone.031", "bone": "Bicep.L",
"radius": 0.04 "radius": 0.04
}, },
{ {
"type": "hurt", "type": "hurt",
"bone": "Bone.012", "bone": "Bicep.R",
"radius": 0.04 "radius": 0.04
}, },
{ {
"type": "hurt", "type": "hurt",
"bone": "Bone.003", "bone": "Leg.L",
"radius": 0.04 "radius": 0.04
}, },
{ {
"type": "hurt", "type": "hurt",
"bone": "Bone.010", "bone": "Leg.R",
"radius": 0.04
},
{
"type": "hurt",
"bone": "Shoulder.L",
"radius": 0.06 "radius": 0.06
}, },
{ {
"type": "hurt", "type": "hurt",
"bone": "Bone.001", "bone": "Shoulder.R",
"radius": 0.06 "radius": 0.06
}, },
{ {
"type": "hurt", "type": "hurt",
"bone": "Bone.014", "bone": "Neck",
"radius": 0.06 "radius": 0.06
}, },
{ {
@ -40,13 +45,8 @@
}, },
{ {
"type": "hurt", "type": "hurt",
"bone": "Bone.014", "bone": "Head",
"radius": 0.06 "radius": 0.06
},
{
"type": "hurt",
"bone": "Bone.019",
"radius": 0.04
} }
], ],
"tokens" : [ "tokens" : [

Binary file not shown.

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file #maven.buildNumber.plugin properties file
#Sun May 19 19:34:37 EDT 2024 #Sat Jun 01 15:22:11 EDT 2024
buildNumber=132 buildNumber=134

View File

@ -310,14 +310,34 @@ Attaching items to hands in first person
Fix grass placement Fix grass placement
(05/25/2024) (05/26/2024)
VERY rudimentary first person documentation to give basic navigation to relevant files. VERY rudimentary first person documentation to give basic navigation to relevant files.
Fix attacking looping and freezing the character in place
- Was using delta real time (0.02ms) instead of delta frames in server and client attack trees (1 frame/simulate() call)
Document hitboxes
- Documented how it works currently and the architecture we want to move towards
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
- Need to have an object attached to creature that stores the rigid body
- When creating the creature, for each hitbox, create shapes for the rigid body
- Attach the overall object to the creature entity
(05/27/2024)
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
- Synchronize hitbox positions each frame
(05/31/2024)
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
- Write custom callback for the collision engine for just hitboxes
# TODO # TODO
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around) Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
- Introduce block hitbox (blockbox) type
Fix being able to walk off far side of the world (ie in level editor) Fix being able to walk off far side of the world (ie in level editor)
@ -349,6 +369,8 @@ More Debug menus
- Screen that shows the overall status of fluid cell manager - Screen that shows the overall status of fluid cell manager
- Screen that shows the overall status of realm 0 - Screen that shows the overall status of realm 0
- Screen that shows the overall status of realm manager - Screen that shows the overall status of realm manager
- Particularly, want a view of all entities in the scene, and the ability to click on a single entity to get an overview of everything on the entity
- For each behavior tree, ability to click into the tree and view fine details about its state (both pure state variable as well as other relevant variables)
Revisit first attempt at instancing (its really laggy lol) Revisit first attempt at instancing (its really laggy lol)
- Maybe have draw call happen on top level entity and immediately queue all children recursively - Maybe have draw call happen on top level entity and immediately queue all children recursively

View File

@ -310,6 +310,17 @@
"positionY", "positionY",
"positionZ" "positionZ"
] ]
},
{
"messageName" : "updateEntityViewDir",
"data" : [
"entityID",
"time",
"positionX",
"positionY",
"positionZ",
"propertyValueInt"
]
} }

View File

@ -1,19 +1,20 @@
package electrosphere.client.scene; package electrosphere.client.scene;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.ode4j.ode.DContactGeom;
import electrosphere.collision.CollisionEngine; import electrosphere.collision.CollisionEngine;
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.hitbox.HitboxManager;
import electrosphere.collision.hitbox.HitboxUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.Scene; import electrosphere.entity.Scene;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
/** /**
* Wrapper around the scene object to provide lots of much needed client-specific utility * Wrapper around the scene object to provide lots of much needed client-specific utility
@ -31,9 +32,18 @@ public class ClientSceneWrapper {
//The engine used to back physics collision checks in client //The engine used to back physics collision checks in client
CollisionEngine collisionEngine; CollisionEngine collisionEngine;
//The hitbox manager
HitboxManager hitboxManager;
/**
* Constructor
* @param scene The scene
* @param collisionEngine The collision engine
*/
public ClientSceneWrapper(Scene scene, CollisionEngine collisionEngine){ public ClientSceneWrapper(Scene scene, CollisionEngine collisionEngine){
this.scene = scene; this.scene = scene;
this.collisionEngine = collisionEngine; this.collisionEngine = collisionEngine;
this.hitboxManager = new HitboxManager(resolutionCallback);
} }
/** /**
@ -110,6 +120,14 @@ public class ClientSceneWrapper {
return collisionEngine; return collisionEngine;
} }
/**
* Gets the hitbox manager for the client
* @return The hitbox manager
*/
public HitboxManager getHitboxManager(){
return hitboxManager;
}
/** /**
* Destroys all entities outside simulation range * Destroys all entities outside simulation range
*/ */
@ -129,4 +147,15 @@ public class ClientSceneWrapper {
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }
/**
* The resolution callback that is invoked once a collision has occurred
*/
CollisionResolutionCallback resolutionCallback = new CollisionResolutionCallback() {
@Override
public void resolve(DContactGeom geom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) {
HitboxUtils.clientDamageHitboxColision(impactor.getParent(), receiver.getParent());
}
};
} }

View File

@ -6,11 +6,7 @@ import electrosphere.client.fluid.manager.ClientFluidManager;
import electrosphere.client.instancing.InstanceUpdater; import electrosphere.client.instancing.InstanceUpdater;
import electrosphere.client.targeting.crosshair.Crosshair; import electrosphere.client.targeting.crosshair.Crosshair;
import electrosphere.client.terrain.manager.ClientTerrainManager; import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.hitbox.HitboxUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityTags; import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
@ -44,6 +40,7 @@ public class ClientSimulation {
public void simulate(){ public void simulate(){
Globals.profiler.beginCpuSample("simulate"); Globals.profiler.beginCpuSample("simulate");
//
//load terrain //load terrain
if(isLoadingTerrain()){ if(isLoadingTerrain()){
loadTerrain(); loadTerrain();
@ -53,10 +50,11 @@ public class ClientSimulation {
Globals.profiler.beginCpuSample("clientSynchronizationManager.processMessages"); Globals.profiler.beginCpuSample("clientSynchronizationManager.processMessages");
Globals.clientSynchronizationManager.processMessages(); Globals.clientSynchronizationManager.processMessages();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
//
//simulate bullet physics engine step //simulate bullet physics engine step
Globals.clientSceneWrapper.getCollisionEngine().simulatePhysics((float)Globals.timekeeper.getSimFrameTime()); Globals.clientSceneWrapper.getCollisionEngine().simulatePhysics((float)Globals.timekeeper.getSimFrameTime());
Globals.clientSceneWrapper.getCollisionEngine().updateDynamicObjectTransforms(); Globals.clientSceneWrapper.getCollisionEngine().updateDynamicObjectTransforms();
//
//update actor animations //update actor animations
Globals.profiler.beginCpuSample("update actor animations"); Globals.profiler.beginCpuSample("update actor animations");
for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){ for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){
@ -66,12 +64,14 @@ public class ClientSimulation {
} }
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
//
//make items play idle animation //make items play idle animation
Globals.profiler.beginCpuSample("item animations"); Globals.profiler.beginCpuSample("item animations");
for(Entity item : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM)){ for(Entity item : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM)){
ItemUtils.updateItemActorAnimation(item); ItemUtils.updateItemActorAnimation(item);
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
//
//particle state updates //particle state updates
Globals.profiler.beginCpuSample("particle state updates"); Globals.profiler.beginCpuSample("particle state updates");
for(Entity particle : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){ for(Entity particle : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){
@ -80,18 +80,12 @@ public class ClientSimulation {
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
//update attached entity positions //update attached entity positions
AttachUtils.clientUpdateAttachedEntityPositions(); AttachUtils.clientUpdateAttachedEntityPositions();
//update hitbox positions //
Globals.profiler.beginCpuSample("Hitbox updates"); //Hitbox stuff
for(Entity currentHitbox : Globals.clientHitboxManager.getAllHitboxes()){ Globals.profiler.beginCpuSample("update hitboxes");
HitboxUtils.clientUpdatePosition(currentHitbox); Globals.clientSceneWrapper.getHitboxManager().simulate();
}
//collide hitboxes
for(Entity currentHitbox : Globals.clientHitboxManager.getAllHitboxes()){
if(isReady){
HitboxUtils.clientCollideEntities(currentHitbox);
}
}
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
//
//update audio engine //update audio engine
Globals.profiler.beginCpuSample("audio engine update"); Globals.profiler.beginCpuSample("audio engine update");
if(Globals.audioEngine!=null){ if(Globals.audioEngine!=null){
@ -99,31 +93,32 @@ public class ClientSimulation {
Globals.virtualAudioSourceManager.update((float)Globals.timekeeper.getSimFrameTime()); Globals.virtualAudioSourceManager.update((float)Globals.timekeeper.getSimFrameTime());
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
//
//update foliage //update foliage
if(Globals.clientFoliageManager != null){ if(Globals.clientFoliageManager != null){
Globals.clientFoliageManager.update(); Globals.clientFoliageManager.update();
} }
//tally collidables and offset position accordingly //
// for(Entity currentCollidable : Globals.entityManager.getEntitiesWithTag(EntityTags.COLLIDABLE)){
// CollidableTree tree = CollidableTree.getCollidableTree(currentCollidable);
// tree.simulate(Main.deltaFrames);
// }
//targeting crosshair //targeting crosshair
Globals.profiler.beginCpuSample("crosshair update"); Globals.profiler.beginCpuSample("crosshair update");
Crosshair.checkTargetable(); Crosshair.checkTargetable();
Crosshair.updateTargetCrosshairPosition(); Crosshair.updateTargetCrosshairPosition();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
//
//simulate behavior trees //simulate behavior trees
Globals.clientSceneWrapper.getScene().simulateBehaviorTrees((float)Globals.timekeeper.getSimFrameTime()); Globals.clientSceneWrapper.getScene().simulateBehaviorTrees((float)Globals.timekeeper.getSimFrameTime());
//
//sum collidable impulses //sum collidable impulses
Globals.profiler.beginCpuSample("collidable logic"); Globals.profiler.beginCpuSample("collidable logic");
for(Entity collidable : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE)){ for(Entity collidable : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE)){
ClientCollidableTree.getClientCollidableTree(collidable).simulate((float)Globals.timekeeper.getSimFrameTime()); ClientCollidableTree.getClientCollidableTree(collidable).simulate((float)Globals.timekeeper.getSimFrameTime());
} }
//
//clear collidable impulse lists //clear collidable impulse lists
Globals.clientSceneWrapper.getCollisionEngine().clearCollidableImpulseLists(); Globals.clientSceneWrapper.getCollisionEngine().clearCollidableImpulseLists();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
//
//wrap up functions //wrap up functions
runClientFunctions(); runClientFunctions();

View File

@ -12,9 +12,9 @@ import org.ode4j.math.DMatrix3;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
import org.ode4j.ode.DBox; import org.ode4j.ode.DBox;
import org.ode4j.ode.DCylinder; import org.ode4j.ode.DCylinder;
import org.ode4j.ode.DGeom;
import org.ode4j.ode.DSphere; import org.ode4j.ode.DSphere;
import org.ode4j.ode.DTriMesh; import org.ode4j.ode.DTriMesh;
import org.ode4j.ode.OdeHelper;
import electrosphere.entity.types.terrain.TerrainChunkData; import electrosphere.entity.types.terrain.TerrainChunkData;
@ -81,6 +81,26 @@ public class CollisionBodyCreation {
return collisionEngine.createDBody(geom); return collisionEngine.createDBody(geom);
} }
/**
* Creates a dbody with existing shapes that are provided
* @param collisionEngine the collision engine to create it in
* @param geoms the geometries to attach
* @return the dbody
*/
public static DBody createBodyWithShapes(CollisionEngine collisionEngine, DGeom ... geoms){
return collisionEngine.createDBody(geoms);
}
/**
* Creates a sphere shape
* @param collisionEngine the collision engine
* @param radius the radius of the sphere
* @return the sphere shape
*/
public static DSphere createShapeSphere(CollisionEngine collisionEngine, double radius, long categoryBits){
return collisionEngine.createSphereGeom(radius, categoryBits);
}
/** /**
* Sets the provided body to be a kinematic body (no gravity applied) * Sets the provided body to be a kinematic body (no gravity applied)
* @param collisionEngine The collision engine * @param collisionEngine The collision engine
@ -154,7 +174,7 @@ public class CollisionBodyCreation {
*/ */
public static DBody generateRigidBodyFromAIScene(CollisionEngine collisionEngine, AIScene scene, long categoryBits){ public static DBody generateRigidBodyFromAIScene(CollisionEngine collisionEngine, AIScene scene, long categoryBits){
DBody body = collisionEngine.createDBody(null); DBody body = collisionEngine.createDBody((DGeom[])null);
PointerBuffer meshesBuffer = scene.mMeshes(); PointerBuffer meshesBuffer = scene.mMeshes();
while(meshesBuffer.hasRemaining()){ while(meshesBuffer.hasRemaining()){

View File

@ -31,6 +31,7 @@ import org.ode4j.ode.DBox;
import org.ode4j.ode.DCapsule; import org.ode4j.ode.DCapsule;
import org.ode4j.ode.DContact; import org.ode4j.ode.DContact;
import org.ode4j.ode.DContactBuffer; import org.ode4j.ode.DContactBuffer;
import org.ode4j.ode.DContactGeom;
import org.ode4j.ode.DContactJoint; import org.ode4j.ode.DContactJoint;
import org.ode4j.ode.DCylinder; import org.ode4j.ode.DCylinder;
import org.ode4j.ode.DGeom; import org.ode4j.ode.DGeom;
@ -50,6 +51,7 @@ import org.ode4j.ode.OdeHelper;
import electrosphere.collision.RayCastCallback.RayCastCallbackData; import electrosphere.collision.RayCastCallback.RayCastCallbackData;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.time.Timekeeper;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
@ -63,9 +65,6 @@ import electrosphere.logger.LoggerInterface;
*/ */
public class CollisionEngine { public class CollisionEngine {
//step interval time size
public static final float ENGINE_STEP_SIZE = 0.01f;
//gravity constant //gravity constant
public static final float GRAVITY_MAGNITUDE = 9.8f * 2; public static final float GRAVITY_MAGNITUDE = 9.8f * 2;
@ -91,16 +90,44 @@ public class CollisionEngine {
//callbacks for collision check //callbacks for collision check
RayCastCallback rayCastCallback = new RayCastCallback(); RayCastCallback rayCastCallback = new RayCastCallback();
//the collision resolution callback
CollisionResolutionCallback collisionResolutionCallback;
//buffer for collisions
DContactBuffer contacts = null;
// Callback for any near collisions in the broadphase of the collision check
private DNearCallback nearCallback;
/**
* Constructor
*/
public CollisionEngine(){ public CollisionEngine(){
world = OdeHelper.createWorld(); world = OdeHelper.createWorld();
space = OdeHelper.createBHVSpace(Collidable.TYPE_STATIC_BIT); space = OdeHelper.createBHVSpace(Collidable.TYPE_STATIC_BIT);
world.setGravity(0,-GRAVITY_MAGNITUDE,0); world.setGravity(0,-GRAVITY_MAGNITUDE,0);
contactgroup = OdeHelper.createJointGroup(); contactgroup = OdeHelper.createJointGroup();
this.nearCallback = new DNearCallback() {
@Override
public void call(Object data, DGeom o1, DGeom o2) {
nearCallback( data, o1, o2);
}
};
} }
public static void resolveCollision(Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude){ /**
* Resolves collisions in the engine
* @param contactGeom the ode4j contact geometry
* @param impactor the instigator of the collision
* @param receiver the receiver of the collision
* @param normal the normal to the collision surface
* @param localPosition the local position of the collision
* @param worldPos the world position of the collision
* @param magnitude the magnitude of the collision
*/
public static void resolveCollision(DContactGeom contactGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude){
switch(receiver.getType()){ switch(receiver.getType()){
case Collidable.TYPE_CREATURE: case Collidable.TYPE_CREATURE:
switch(impactor.getType()){ switch(impactor.getType()){
@ -223,7 +250,7 @@ public class CollisionEngine {
//simulate physics //simulate physics
Globals.profiler.beginCpuSample("step physics"); Globals.profiler.beginCpuSample("step physics");
world.quickStep(ENGINE_STEP_SIZE); world.quickStep(Timekeeper.ENGINE_STEP_SIZE);
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
// remove all contact joints // remove all contact joints
@ -233,27 +260,45 @@ public class CollisionEngine {
} }
/** /**
* Callback for any near collisions in the broadphase of the collision check * Runs a collision cycle on all bodies in the collision engine
*/ */
private DNearCallback nearCallback = new DNearCallback() { public void collide(){
@Override Globals.profiler.beginCpuSample("physics");
public void call(Object data, DGeom o1, DGeom o2) { spaceLock.acquireUninterruptibly();
nearCallback( data, o1, o2); Globals.profiler.beginCpuSample("collide");
} OdeHelper.spaceCollide(space, 0, nearCallback);
}; Globals.profiler.endCpuSample();
//buffer for collisions // remove all contact joints
DContactBuffer contacts = null; contactgroup.empty();
spaceLock.release();
Globals.profiler.endCpuSample();
}
// this is called by dSpaceCollide when two objects in space are /**
// potentially colliding. * Sets the near callback function for all collision calls.
* !!YOU LIKELY WANT TO INSTEAD OVERWRITE THE CollisionResolutionCallback!!
* @param callback the callback
*/
public void setNearCallback(DNearCallback callback){
this.nearCallback = callback;
}
/**
* This is called by dSpaceCollide when two objects in space are potentially colliding.
* @param data The data
* @param o1 the first collision body
* @param o2 the second collision body
*/
private void nearCallback (Object data, DGeom o1, DGeom o2) { private void nearCallback (Object data, DGeom o1, DGeom o2) {
// if (o1->body && o2->body) return; // if (o1->body && o2->body) return;
// exit without doing anything if the two bodies are connected by a joint // exit without doing anything if the two bodies are connected by a joint
DBody b1 = o1.getBody(); DBody b1 = o1.getBody();
DBody b2 = o2.getBody(); DBody b2 = o2.getBody();
if (b1!=null && b2!=null && areConnectedExcluding (b1,b2,DContactJoint.class)) return; if (b1!=null && b2!=null && areConnectedExcluding (b1,b2,DContactJoint.class)){
return;
}
//creates a buffer to store potential collisions //creates a buffer to store potential collisions
DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS); // up to MAX_CONTACTS contacts per box-box DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS); // up to MAX_CONTACTS contacts per box-box
@ -284,33 +329,51 @@ public class CollisionEngine {
DContact contact = contacts.get(i); DContact contact = contacts.get(i);
//special code for ray casting //special code for ray casting
if (o1 instanceof DRay || o2 instanceof DRay){ if (o1 instanceof DRay || o2 instanceof DRay){
DMatrix3 Rotation = new DMatrix3(); DVector3 end = new DVector3();
Rotation.setIdentity(); end.eqSum( contact.geom.pos, contact.geom.normal, contact.geom.depth );
// dsDrawSphere(contact.geom.pos, Rotation, (0.01));
DVector3 End = new DVector3();
End.eqSum( contact.geom.pos, contact.geom.normal, contact.geom.depth );
// dsDrawLine(contact.geom.pos, End);
continue; continue;
} }
// contact.geom.pos // Use the default collision resolution
resolveCollision( if(collisionResolutionCallback == null) {
bodyPointerMap.get(o1.getBody()), resolveCollision(
bodyPointerMap.get(o2.getBody()), contact.geom,
PhysicsUtils.odeVecToJomlVec(contact.geom.normal).mul(-1.0), bodyPointerMap.get(o1.getBody()),
PhysicsUtils.odeVecToJomlVec(contact.fdir1).mul(-1.0), bodyPointerMap.get(o2.getBody()),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos), PhysicsUtils.odeVecToJomlVec(contact.geom.normal).mul(-1.0),
(float)contact.geom.depth PhysicsUtils.odeVecToJomlVec(contact.fdir1).mul(-1.0),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
(float)contact.geom.depth
);
resolveCollision(
contact.geom,
bodyPointerMap.get(o2.getBody()),
bodyPointerMap.get(o1.getBody()),
PhysicsUtils.odeVecToJomlVec(contact.geom.normal),
PhysicsUtils.odeVecToJomlVec(contact.fdir1),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
(float)contact.geom.depth
);
} else {
//use custom collision resolution
collisionResolutionCallback.resolve(
contact.geom,
bodyPointerMap.get(o1.getBody()),
bodyPointerMap.get(o2.getBody()),
PhysicsUtils.odeVecToJomlVec(contact.geom.normal).mul(-1.0),
PhysicsUtils.odeVecToJomlVec(contact.fdir1).mul(-1.0),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
(float)contact.geom.depth
); );
resolveCollision( collisionResolutionCallback.resolve(
bodyPointerMap.get(o2.getBody()), contact.geom,
bodyPointerMap.get(o1.getBody()), bodyPointerMap.get(o2.getBody()),
PhysicsUtils.odeVecToJomlVec(contact.geom.normal), bodyPointerMap.get(o1.getBody()),
PhysicsUtils.odeVecToJomlVec(contact.fdir1), PhysicsUtils.odeVecToJomlVec(contact.geom.normal),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos), PhysicsUtils.odeVecToJomlVec(contact.fdir1),
(float)contact.geom.depth PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
(float)contact.geom.depth
); );
}
//add contact to contact group //add contact to contact group
DJoint c = OdeHelper.createContactJoint (world,contactgroup,contact ); DJoint c = OdeHelper.createContactJoint (world,contactgroup,contact );
@ -325,6 +388,14 @@ public class CollisionEngine {
} }
} }
} }
/**
* Sets the function that is called once a collision has happened
* @param collisionResolutionCallback the function
*/
public void setCollisionResolutionCallback(CollisionResolutionCallback collisionResolutionCallback){
this.collisionResolutionCallback = collisionResolutionCallback;
}
/** /**
* *
@ -691,6 +762,19 @@ public class CollisionEngine {
spaceLock.release(); spaceLock.release();
} }
/**
* Sets the transform of a geometry
* @param geom The geometry
* @param position The position
* @param rotation The rotation
*/
protected void setGeomTransform(DGeom geom, Vector3d position, Quaterniond rotation){
spaceLock.acquireUninterruptibly();
geom.setOffsetWorldPosition(position.x, position.y, position.z);
geom.setOffsetQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
spaceLock.release();
}
/** /**
* Corrects the initial axis of eg cylinders or capsules * Corrects the initial axis of eg cylinders or capsules
* @param geom the geometry to correct * @param geom the geometry to correct
@ -759,4 +843,22 @@ public class CollisionEngine {
spaceLock.release(); spaceLock.release();
} }
/**
* A callback for resolving collisions between two entities
*/
public interface CollisionResolutionCallback {
/**
* Resolves a collision between two collidables in the engine
* @param contactGeom the ode4j contact geom
* @param impactor The collidable initiating the contact
* @param receiver The collidable recieving the contact
* @param normal The normal of the collision
* @param localPosition The local position of the collision
* @param worldPos The world position of the collision
* @param magnitude The magnitude of the collision
*/
public void resolve(DContactGeom contactGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude);
}
} }

View File

@ -2,10 +2,12 @@ package electrosphere.collision;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Quaterniond;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
import org.ode4j.ode.DCylinder; import org.ode4j.ode.DCylinder;
import org.ode4j.ode.DGeom;
import org.ode4j.ode.DTriMesh; import org.ode4j.ode.DTriMesh;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
@ -301,5 +303,14 @@ public class PhysicsEntityUtils {
public static DBody getDBody(Entity entity){ public static DBody getDBody(Entity entity){
return (DBody)entity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); return (DBody)entity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY);
} }
/**
* Sets the position of a DGeom
* @param collisionEngine the collision engine
* @param geom the geometry
*/
public static void setGeometryPosition(CollisionEngine collisionEngine, DGeom geom, Vector3d position, Quaterniond rotation){
collisionEngine.setGeomTransform(geom, position, rotation);
}
} }

View File

@ -39,7 +39,15 @@ public class PhysicsUtils {
*/ */
public static Vector3d odeVecToJomlVec(org.ode4j.math.DVector3C vector){ public static Vector3d odeVecToJomlVec(org.ode4j.math.DVector3C vector){
return new Vector3d(vector.get0(),vector.get1(),vector.get2()); return new Vector3d(vector.get0(),vector.get1(),vector.get2());
}
/**
* Converts a joml vector to an Ode vector
* @param vector joml vector
* @return Ode vector
*/
public static org.ode4j.math.DVector3C jomlVecToOdeVec(Vector3d vector){
return new org.ode4j.math.DVector3(vector.x,vector.y,vector.z);
} }
/** /**

View File

@ -1,8 +1,9 @@
package electrosphere.collision.hitbox; package electrosphere.collision.hitbox;
import electrosphere.collision.CollisionEngine; import electrosphere.collision.CollisionEngine;
import electrosphere.entity.Entity; import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
import electrosphere.entity.EntityDataStrings; import electrosphere.engine.Globals;
import electrosphere.entity.state.hitbox.HitboxState;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
/** /**
@ -11,7 +12,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class HitboxManager { public class HitboxManager {
//the list of all hitboxes //the list of all hitboxes
CopyOnWriteArrayList<Entity> hitboxes = new CopyOnWriteArrayList<Entity>(); CopyOnWriteArrayList<HitboxState> hitboxes = new CopyOnWriteArrayList<HitboxState>();
//the collision engine for this hitbox manager //the collision engine for this hitbox manager
CollisionEngine collisionEngine; CollisionEngine collisionEngine;
@ -21,26 +22,27 @@ public class HitboxManager {
/** /**
* Constructor * Constructor
* @param resolutionCallback The callback that fires when a collision occurs
*/ */
public HitboxManager(){ public HitboxManager(CollisionResolutionCallback resolutionCallback){
collisionEngine = new CollisionEngine(); collisionEngine = new CollisionEngine();
collisionEngine.setCollisionResolutionCallback(resolutionCallback);
} }
/** /**
* Registers a hitbox to the manager * Registers a hitbox to the manager
* @param hitbox the hitbox to register * @param hitbox the hitbox to register
*/ */
public void registerHitbox(Entity hitbox){ public void registerHitbox(HitboxState hitbox){
hitboxes.add(hitbox); hitboxes.add(hitbox);
idIncrementer++; idIncrementer++;
hitbox.putData(EntityDataStrings.COLLISION_ENTITY_ID, idIncrementer);
} }
/** /**
* Gets all hitboxes in the manager * Gets all hitboxes in the manager
* @return all hitboxes in the manager * @return all hitboxes in the manager
*/ */
public CopyOnWriteArrayList<Entity> getAllHitboxes(){ public CopyOnWriteArrayList<HitboxState> getAllHitboxes(){
return hitboxes; return hitboxes;
} }
@ -48,7 +50,35 @@ public class HitboxManager {
* Deregisters a hitbox from the manager * Deregisters a hitbox from the manager
* @param hitbox the hitbox to deregister * @param hitbox the hitbox to deregister
*/ */
public void deregisterHitbox(Entity hitbox){ public void deregisterHitbox(HitboxState hitbox){
hitboxes.remove(hitbox); hitboxes.remove(hitbox);
} }
/**
* Gets the collision engine associated with the hitbox manager
* @return The collision engine
*/
public CollisionEngine getCollisionEngine(){
return this.collisionEngine;
}
/**
* Runs all per frame functions of the hitbox manager
*/
public void simulate(){
//update all positions
Globals.profiler.beginCpuSample("Update hitbox positions");
for(HitboxState state : hitboxes){
state.updateHitboxPositions(this.collisionEngine);
}
Globals.profiler.endCpuSample();
//collide hitboxes
Globals.profiler.beginCpuSample("Collide hitboxes");
this.collisionEngine.collide();
this.collisionEngine.clearCollidableImpulseLists();
Globals.profiler.endCpuSample();
}
} }

View File

@ -26,153 +26,153 @@ import org.joml.Vector3f;
*/ */
public class HitboxUtils { public class HitboxUtils {
/** // /**
* Spawns a hitbox entity on the client // * Spawns a hitbox entity on the client
* @param parent The parent entity to attach the hitbox to // * @param parent The parent entity to attach the hitbox to
* @param bone The bone on the parent to attach to // * @param bone The bone on the parent to attach to
* @param size The radius of the hitsphere // * @param size The radius of the hitsphere
* @return The hitbox entity // * @return The hitbox entity
*/ // */
public static Entity clientSpawnRegularHitbox(Entity parent, String bone, float size){ // public static Entity clientSpawnRegularHitbox(Entity parent, String bone, float size){
Entity rVal = EntityCreationUtils.createClientSpatialEntity(); // Entity rVal = EntityCreationUtils.createClientSpatialEntity();
HitboxData data = new HitboxData(); // HitboxData data = new HitboxData();
data.setActive(false); // data.setActive(false);
data.setBone(bone); // data.setBone(bone);
data.setRadius(size); // data.setRadius(size);
data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT); // data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT);
rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent); // rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
rVal.putData(EntityDataStrings.HITBOX_DATA, data); // rVal.putData(EntityDataStrings.HITBOX_DATA, data);
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); // rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); // rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
Globals.clientHitboxManager.registerHitbox(rVal); // Globals.clientHitboxManager.registerHitbox(rVal);
return rVal; // return rVal;
} // }
/** // /**
* Spawns a hitbox entity on the server // * Spawns a hitbox entity on the server
* @param parent The parent entity to attach the hitbox to // * @param parent The parent entity to attach the hitbox to
* @param bone The bone to attach to the hitbox to // * @param bone The bone to attach to the hitbox to
* @param size The radius of the hitsphere // * @param size The radius of the hitsphere
* @return The hitbox entity // * @return The hitbox entity
*/ // */
public static Entity serverSpawnRegularHitbox(Entity parent, String bone, float size){ // public static Entity serverSpawnRegularHitbox(Entity parent, String bone, float size){
Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0)); // Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0));
HitboxData data = new HitboxData(); // HitboxData data = new HitboxData();
data.setActive(false); // data.setActive(false);
data.setBone(bone); // data.setBone(bone);
data.setRadius(size); // data.setRadius(size);
data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT); // data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT);
rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent); // rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
rVal.putData(EntityDataStrings.HITBOX_DATA, data); // rVal.putData(EntityDataStrings.HITBOX_DATA, data);
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); // rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); // rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal); // Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal);
return rVal; // return rVal;
} // }
/** // /**
* Spawns a hurtbox on the client // * Spawns a hurtbox on the client
* @param parent The parent entity of the hurtbox // * @param parent The parent entity of the hurtbox
* @param bone The bone on the parent to attach the hurtbox to // * @param bone The bone on the parent to attach the hurtbox to
* @param size The radius of the hurtsphere // * @param size The radius of the hurtsphere
* @return The hurtbox entity // * @return The hurtbox entity
*/ // */
public static Entity clientSpawnRegularHurtbox(Entity parent, String bone, float size){ // public static Entity clientSpawnRegularHurtbox(Entity parent, String bone, float size){
Entity rVal = EntityCreationUtils.createClientSpatialEntity(); // Entity rVal = EntityCreationUtils.createClientSpatialEntity();
HitboxData data = new HitboxData(); // HitboxData data = new HitboxData();
data.setActive(true); // data.setActive(true);
data.setBone(bone); // data.setBone(bone);
data.setRadius(size); // data.setRadius(size);
data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT); // data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT);
rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent); // rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
rVal.putData(EntityDataStrings.HITBOX_DATA, data); // rVal.putData(EntityDataStrings.HITBOX_DATA, data);
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); // rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); // rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
Globals.clientHitboxManager.registerHitbox(rVal); // Globals.clientHitboxManager.registerHitbox(rVal);
return rVal; // return rVal;
} // }
/** // /**
* Spawns a hurtbox on the server // * Spawns a hurtbox on the server
* @param parent The parent entity of the hurtbox // * @param parent The parent entity of the hurtbox
* @param bone The bone on the parent to attach the hurtbox to // * @param bone The bone on the parent to attach the hurtbox to
* @param size The radius of the hurtsphere // * @param size The radius of the hurtsphere
* @return The hurtbox entity // * @return The hurtbox entity
*/ // */
public static Entity serverSpawnRegularHurtbox(Entity parent, String bone, float size){ // public static Entity serverSpawnRegularHurtbox(Entity parent, String bone, float size){
Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0)); // Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0));
HitboxData data = new HitboxData(); // HitboxData data = new HitboxData();
data.setActive(true); // data.setActive(true);
data.setBone(bone); // data.setBone(bone);
data.setRadius(size); // data.setRadius(size);
data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT); // data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT);
rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent); // rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
rVal.putData(EntityDataStrings.HITBOX_DATA, data); // rVal.putData(EntityDataStrings.HITBOX_DATA, data);
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); // rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); // rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal); // Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal);
return rVal; // return rVal;
} // }
/** // /**
* More sophisticated function for spawning in hitboxes. Takes a position callback so it's not tied to a bone // * More sophisticated function for spawning in hitboxes. Takes a position callback so it's not tied to a bone
* @param parent The parent entity of the hitbox // * @param parent The parent entity of the hitbox
* @param positionCallback The position callback for keeping hitbox entity position up to date // * @param positionCallback The position callback for keeping hitbox entity position up to date
* @param size The size of the hitbox // * @param size The size of the hitbox
* @param hurtbox If true, it will instead be a hurtbox // * @param hurtbox If true, it will instead be a hurtbox
* @param filter an optional list of parent entities to not colide with // * @param filter an optional list of parent entities to not colide with
* @return The hitbox entity // * @return The hitbox entity
*/ // */
public static Entity clientSpawnRegularHitbox(Entity parent, HitboxPositionCallback positionCallback, float size, boolean hurtbox, List<Entity> filter){ // public static Entity clientSpawnRegularHitbox(Entity parent, HitboxPositionCallback positionCallback, float size, boolean hurtbox, List<Entity> filter){
Entity rVal = EntityCreationUtils.createClientSpatialEntity(); // Entity rVal = EntityCreationUtils.createClientSpatialEntity();
HitboxData data = new HitboxData(); // HitboxData data = new HitboxData();
data.setActive(true); // data.setActive(true);
data.setPositionCallback(positionCallback); // data.setPositionCallback(positionCallback);
data.setRadius(size); // data.setRadius(size);
data.setEntityFilter(filter); // data.setEntityFilter(filter);
if(hurtbox){ // if(hurtbox){
data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT); // data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT);
} else { // } else {
data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT); // data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT);
} // }
rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent); // rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
rVal.putData(EntityDataStrings.HITBOX_DATA, data); // rVal.putData(EntityDataStrings.HITBOX_DATA, data);
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); // rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); // rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
Globals.clientHitboxManager.registerHitbox(rVal); // Globals.clientHitboxManager.registerHitbox(rVal);
return rVal; // return rVal;
} // }
/** // /**
* More sophisticated function for spawning in hitboxes. Takes a position callback so it's not tied to a bone // * More sophisticated function for spawning in hitboxes. Takes a position callback so it's not tied to a bone
* @param parent The parent entity of the hitbox // * @param parent The parent entity of the hitbox
* @param positionCallback The position callback for keeping hitbox entity position up to date // * @param positionCallback The position callback for keeping hitbox entity position up to date
* @param size The size of the hitbox // * @param size The size of the hitbox
* @param hurtbox If true, it will instead be a hurtbox // * @param hurtbox If true, it will instead be a hurtbox
* @param filter an optional list of parent entities to not colide with // * @param filter an optional list of parent entities to not colide with
* @return The hitbox entity // * @return The hitbox entity
*/ // */
public static Entity serverSpawnRegularHitbox(Entity parent, HitboxPositionCallback positionCallback, float size, boolean hurtbox, List<Entity> filter){ // public static Entity serverSpawnRegularHitbox(Entity parent, HitboxPositionCallback positionCallback, float size, boolean hurtbox, List<Entity> filter){
Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0)); // Entity rVal = EntityCreationUtils.createServerEntity(Globals.realmManager.getEntityRealm(parent), new Vector3d(0,0,0));
HitboxData data = new HitboxData(); // HitboxData data = new HitboxData();
data.setActive(true); // data.setActive(true);
data.setPositionCallback(positionCallback); // data.setPositionCallback(positionCallback);
data.setRadius(size); // data.setRadius(size);
data.setEntityFilter(filter); // data.setEntityFilter(filter);
if(hurtbox){ // if(hurtbox){
data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT); // data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT);
} else { // } else {
data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT); // data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT);
} // }
rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent); // rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent);
rVal.putData(EntityDataStrings.HITBOX_DATA, data); // rVal.putData(EntityDataStrings.HITBOX_DATA, data);
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); // rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); // rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true);
Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal); // Globals.realmManager.getEntityRealm(parent).getHitboxManager().registerHitbox(rVal);
return rVal; // return rVal;
} // }
public static void clientUpdatePosition(Entity hitbox){ public static void clientUpdatePosition(Entity hitbox){
Entity parent = ((Entity)hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT)); Entity parent = ((Entity)hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT));
@ -232,210 +232,48 @@ public class HitboxUtils {
} }
} }
/**
* Collides entities on the client
* @param generatorHitbox the hitbox generating the collision
*/
public static void clientCollideEntities(Entity generatorHitbox){
// long generatorId = (Long)generatorHitbox.getData(EntityDataStrings.COLLISION_ENTITY_ID);
//This is the entity the hitbox is attached to
Entity generatorParent = (Entity)generatorHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
for(Entity receiverHitbox : Globals.clientHitboxManager.getAllHitboxes()){
Entity receiverParent = (Entity)receiverHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
HitboxData generatorData = getHitboxData(generatorHitbox);
HitboxData receiverData = getHitboxData(receiverHitbox);
//check projectile filters
List<Entity> generatorFilter = generatorData.getEntityFilter();
if(generatorFilter != null && generatorFilter.contains(receiverParent)){
continue;
}
List<Entity> receiverFilter = receiverData.getEntityFilter();
if(receiverFilter != null && receiverFilter.contains(generatorParent)){
continue;
}
//if there is a collision
//and the collision isn't against itself
//and both hitboxes are active
if(
receiverParent != generatorParent &&
Globals.clientSceneWrapper.getCollisionEngine().collisionSphereCheck(generatorHitbox, generatorData, receiverHitbox, receiverData) &&
generatorData.isActive() &&
receiverData.isActive()){
//if two spheres collide, grab their hitbox types (eg hurt, hit, fire, etc)
String generatorType = generatorData.getType();
String receiverType = receiverData.getType();
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){
clientDamageHitboxColision(generatorHitbox, receiverHitbox);
}
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){
clientDamageHitboxColision(receiverHitbox, generatorHitbox);
}
}
}
}
/**
* Handles collision between two hitboxes on the server
* @param generatorHitbox the hitbox generating the collision
*/
public static void serverCollideEntities(Entity generatorHitbox){
// long generatorId = (Long)generatorHitbox.getData(EntityDataStrings.COLLISION_ENTITY_ID);
//This is the entity the hitbox is attached to
Entity generatorParent = (Entity)generatorHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
Realm generatorRealm = Globals.realmManager.getEntityRealm(generatorParent);
if(generatorRealm != null){
HitboxManager realmHitboxManager = generatorRealm.getHitboxManager();
for(Entity receiverHitbox : realmHitboxManager.getAllHitboxes()){
Entity receiverParent = (Entity)receiverHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
HitboxData generatorData = getHitboxData(generatorHitbox);
HitboxData receiverData = getHitboxData(receiverHitbox);
//check projectile filters
List<Entity> generatorFilter = generatorData.getEntityFilter();
if(generatorFilter != null && generatorFilter.contains(receiverParent)){
continue;
}
List<Entity> receiverFilter = receiverData.getEntityFilter();
if(receiverFilter != null && receiverFilter.contains(generatorParent)){
continue;
}
//if there is a collision
//and the collision isn't against itself
//and both hitboxes are active
if(
receiverParent != generatorParent &&
generatorRealm.getCollisionEngine().collisionSphereCheck(generatorHitbox, generatorData, receiverHitbox, receiverData) &&
generatorData.isActive() &&
receiverData.isActive()){
//if two spheres collide, grab their hitbox types (eg hurt, hit, fire, etc)
String generatorType = generatorData.getType();
String receiverType = receiverData.getType();
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){
serverDamageHitboxColision(generatorHitbox, receiverHitbox);
}
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){
serverDamageHitboxColision(receiverHitbox, generatorHitbox);
}
}
}
}
}
/** /**
* Handles a damage collision on the client * Handles a damage collision on the client
* @param hitbox the hitbox * @param impactor the entity initiating the collision
* @param hurtbox the hurtbox * @param receiver the entity receiving the collision
*/ */
public static void clientDamageHitboxColision(Entity hitbox, Entity hurtbox){ public static void clientDamageHitboxColision(Entity impactor, Entity receiver){
Entity hitboxParent = (Entity)hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT); // Entity hitboxParent = (Entity)impactor.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
Entity hurtboxParent = (Entity)hurtbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT); // Entity hurtboxParent = (Entity)receiver.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
//if the entity is attached to is an item, we need to compare with the parent of the item //if the entity is attached to is an item, we need to compare with the parent of the item
//to make sure you don't stab yourself for instance //to make sure you don't stab yourself for instance
boolean isItem = ItemUtils.isItem(hitboxParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM); // boolean isItem = ItemUtils.isItem(hitboxParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM);
Entity hitboxAttachParent = AttachUtils.getParent(hitboxParent); // Entity hitboxAttachParent = AttachUtils.getParent(hitboxParent);
if(isItem){ // if(isItem){
if(hitboxAttachParent != hurtboxParent){ // if(hitboxAttachParent != hurtboxParent){
LifeState lifeState = LifeUtils.getLifeState(hurtboxParent); // Vector3d hurtboxPos = EntityUtils.getPosition(receiver);
int currentHp = lifeState.getLifeCurrent(); // ParticleEffects.spawnBloodsplats(new Vector3f((float)hurtboxPos.x,(float)hurtboxPos.y,(float)hurtboxPos.z).add(0,0.1f,0), 20, 40);
int damage = ItemUtils.getWeaponDataRaw(hitboxParent).getDamage(); // }
LifeUtils.getLifeState(hurtboxParent).damage(damage); // } else {
if(currentHp > lifeState.getLifeCurrent()){
Vector3d hurtboxPos = EntityUtils.getPosition(hurtbox);
ParticleEffects.spawnBloodsplats(new Vector3f((float)hurtboxPos.x,(float)hurtboxPos.y,(float)hurtboxPos.z).add(0,0.1f,0), 20, 40);
}
if(!LifeUtils.getLifeState(hurtboxParent).isIsAlive()){
EntityUtils.getPosition(hurtboxParent).set(Globals.spawnPoint);
LifeUtils.getLifeState(hurtboxParent).revive();
}
}
} else {
int damage = 0;
//for entities using attacktree
if(CreatureUtils.clientGetAttackTree(hitboxParent) != null){
damage = ItemUtils.getWeaponDataRaw(hitboxParent).getDamage();
} else {
//for entities using shooter tree
if(ProjectileTree.getProjectileTree(hitboxParent) != null){
damage = (int)ProjectileTree.getProjectileTree(hitboxParent).getDamage();
}
}
LifeUtils.getLifeState(hurtboxParent).damage(damage);
if(!LifeUtils.getLifeState(hurtboxParent).isIsAlive()){
EntityUtils.getPosition(hurtboxParent).set(Globals.spawnPoint);
LifeUtils.getLifeState(hurtboxParent).revive();
}
}
}
/** // //client no longer manages damage; however, keeping this code around for the moment to show how we
* Handles a damage hitbox collision on the server // //might approach adding client-side effects as soon as impact occurs (ie play a sound, shoot sparks, etc)
* @param hitbox the hitbox // //before the server responds with a valid collision event or not
* @param hurtbox the hurtbox
*/ // // int damage = 0;
public static void serverDamageHitboxColision(Entity hitbox, Entity hurtbox){ // // //for entities using attacktree
// // if(CreatureUtils.clientGetAttackTree(hitboxParent) != null){
Entity hitboxParent = (Entity)hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT); // // damage = ItemUtils.getWeaponDataRaw(hitboxParent).getDamage();
Entity hurtboxParent = (Entity)hurtbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT); // // } else {
// // //for entities using shooter tree
//if the entity is attached to is an item, we need to compare with the parent of the item // // if(ProjectileTree.getProjectileTree(hitboxParent) != null){
//to make sure you don't stab yourself for instance // // damage = (int)ProjectileTree.getProjectileTree(hitboxParent).getDamage();
boolean isItem = ItemUtils.isItem(hitboxParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM); // // }
Entity hitboxAttachParent = AttachUtils.getParent(hitboxParent); // // }
// // LifeUtils.getLifeState(hurtboxParent).damage(damage);
if(isItem){ // // if(!LifeUtils.getLifeState(hurtboxParent).isIsAlive()){
if(hitboxAttachParent != hurtboxParent){ // // EntityUtils.getPosition(hurtboxParent).set(Globals.spawnPoint);
LifeState lifeState = LifeUtils.getLifeState(hurtboxParent); // // LifeUtils.getLifeState(hurtboxParent).revive();
int currentHp = lifeState.getLifeCurrent(); // // }
int damage = ItemUtils.getWeaponDataRaw(hitboxParent).getDamage(); // }
LifeUtils.getLifeState(hurtboxParent).damage(damage);
if(currentHp > lifeState.getLifeCurrent()){
Vector3d hurtboxPos = EntityUtils.getPosition(hurtbox);
ParticleEffects.spawnBloodsplats(new Vector3f((float)hurtboxPos.x,(float)hurtboxPos.y,(float)hurtboxPos.z).add(0,0.1f,0), 20, 40);
}
if(!LifeUtils.getLifeState(hurtboxParent).isIsAlive()){
EntityUtils.getPosition(hurtboxParent).set(Globals.spawnPoint);
LifeUtils.getLifeState(hurtboxParent).revive();
}
}
} else {
int damage = 0;
//for entities using attacktree
if(CreatureUtils.serverGetAttackTree(hitboxParent) != null){
damage = ItemUtils.getWeaponDataRaw(hitboxParent).getDamage();
} else {
//for entities using shooter tree
if(ProjectileTree.getProjectileTree(hitboxParent) != null){
damage = (int)ProjectileTree.getProjectileTree(hitboxParent).getDamage();
}
}
LifeUtils.getLifeState(hurtboxParent).damage(damage);
if(!LifeUtils.getLifeState(hurtboxParent).isIsAlive()){
EntityUtils.getPosition(hurtboxParent).set(Globals.spawnPoint);
LifeUtils.getLifeState(hurtboxParent).revive();
}
}
} }
/** /**
@ -447,24 +285,6 @@ public class HitboxUtils {
return (HitboxData)e.getData(EntityDataStrings.HITBOX_DATA); return (HitboxData)e.getData(EntityDataStrings.HITBOX_DATA);
} }
/**
* Gets the hitbox associated list
* @param e The entity that has hitboxes
* @return the list of hitboxes associated with the entity
*/
public static List<Entity> getHitboxAssociatedList(Entity e){
return (List<Entity>)e.getData(EntityDataStrings.HITBOX_ASSOCIATED_LIST);
}
/**
* Gets the hurtbox associated list
* @param e the entity that has hurtboxes
* @return the list of hurtboxes associated with the entity
*/
public static List<Entity> getHurtboxAssociatedList(Entity e){
return (List<Entity>)e.getData(EntityDataStrings.HURTBOX_ASSOCIATED_LIST);
}
/** /**
* Intended to be implemented as an anonoymous class when needed * Intended to be implemented as an anonoymous class when needed
*/ */

View File

@ -10,6 +10,7 @@ import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.camera.CameraEntityUtils; import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.renderer.ui.events.MouseEvent; import electrosphere.renderer.ui.events.MouseEvent;
public class CameraHandler { public class CameraHandler {
@ -107,8 +108,21 @@ public class CameraHandler {
cameraRotationVector.mul(CameraEntityUtils.getOrbitalCameraDistance(Globals.playerCamera)); cameraRotationVector.mul(CameraEntityUtils.getOrbitalCameraDistance(Globals.playerCamera));
CameraEntityUtils.setCameraEye(Globals.playerCamera, cameraRotationVector); CameraEntityUtils.setCameraEye(Globals.playerCamera, cameraRotationVector);
//tell the server that we changed where we're looking
Globals.clientConnection.queueOutgoingMessage(
EntityMessage.constructupdateEntityViewDirMessage(
Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId()),
Globals.timekeeper.getNumberOfSimFramesElapsed(),
cameraRotationVector.x,
cameraRotationVector.y,
cameraRotationVector.z
)
);
//the view matrix
Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera); Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera);
//update the cursor on client side
updatePlayerCursor(); updatePlayerCursor();
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();

View File

@ -84,6 +84,11 @@ import electrosphere.util.FileUtils;
* @author amaterasu * @author amaterasu
*/ */
public class Globals { public class Globals {
//
//Process data
//
public static String javaPID;
// //
//Top level user settings object //Top level user settings object
@ -302,9 +307,6 @@ public class Globals {
//script engine //script engine
public static ScriptEngine scriptEngine; public static ScriptEngine scriptEngine;
//manages hitboxes
public static HitboxManager clientHitboxManager;
//client scene management //client scene management
public static Scene clientScene; public static Scene clientScene;
public static ClientSceneWrapper clientSceneWrapper; public static ClientSceneWrapper clientSceneWrapper;
@ -442,8 +444,6 @@ public class Globals {
//script engine //script engine
scriptEngine = new ScriptEngine(); scriptEngine = new ScriptEngine();
scriptEngine.init(); scriptEngine.init();
//hitbox manager
clientHitboxManager = new HitboxManager();
//ai manager //ai manager
aiManager = new AIManager(); aiManager = new AIManager();
//realm & data cell manager //realm & data cell manager
@ -520,6 +520,7 @@ public class Globals {
//init fluid shader program //init fluid shader program
FluidChunkModelGeneration.fluidChunkShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/fluid2/fluid2.vs", "/Shaders/fluid2/fluid2.fs"); FluidChunkModelGeneration.fluidChunkShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/fluid2/fluid2.vs", "/Shaders/fluid2/fluid2.fs");
//init models //init models
assetManager.addModelPathToQueue("Models/basic/geometry/unitsphere.glb");
assetManager.addModelPathToQueue("Models/basic/geometry/unitsphere.fbx"); assetManager.addModelPathToQueue("Models/basic/geometry/unitsphere.fbx");
assetManager.addModelPathToQueue("Models/basic/geometry/unitsphere_1.fbx"); assetManager.addModelPathToQueue("Models/basic/geometry/unitsphere_1.fbx");
assetManager.addModelPathToQueue("Models/basic/geometry/unitsphere_grey.fbx"); assetManager.addModelPathToQueue("Models/basic/geometry/unitsphere_grey.fbx");

View File

@ -63,8 +63,8 @@ public class Main {
//initialize logging interfaces //initialize logging interfaces
LoggerInterface.initLoggers(); LoggerInterface.initLoggers();
//gets pid of engine //gets java pid of engine
System.out.println(ManagementFactory.getRuntimeMXBean().getName()); Globals.javaPID = ManagementFactory.getRuntimeMXBean().getName();
//load user settings //load user settings
UserSettings.loadUserSettings(); UserSettings.loadUserSettings();
@ -221,6 +221,8 @@ public class Main {
//main loop //main loop
while (running) { while (running) {
try {
Globals.profiler.beginRootCpuSample("frame"); Globals.profiler.beginRootCpuSample("frame");
LoggerInterface.loggerEngine.DEBUG("Begin Main Loop Frame"); LoggerInterface.loggerEngine.DEBUG("Begin Main Loop Frame");
@ -396,6 +398,10 @@ public class Main {
LoggerInterface.loggerEngine.DEBUG("End Main Loop Frame"); LoggerInterface.loggerEngine.DEBUG("End Main Loop Frame");
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} catch (NullPointerException ex){
LoggerInterface.loggerEngine.ERROR("Main frame uncaught NPE", ex);
}
} }
LoggerInterface.loggerEngine.WARNING("ENGINE SHUTDOWN"); LoggerInterface.loggerEngine.WARNING("ENGINE SHUTDOWN");

View File

@ -239,13 +239,21 @@ public class AssetManager {
// //
//Pose Models //Pose Models
// //
/**
* Adds a pose model to the list of pose models to load
* @param path The path to load
*/
public void addPoseModelPathToQueue(String path){ public void addPoseModelPathToQueue(String path){
if(!poseModelsInQueue.contains(path) && !poseModelsLoadedIntoMemory.containsKey(path)){ if(!poseModelsInQueue.contains(path) && !poseModelsLoadedIntoMemory.containsKey(path)){
poseModelsInQueue.add(path); poseModelsInQueue.add(path);
} }
} }
/**
* Fetches a pose model
* @param path The path to fetch
* @return The pose model if it exists, null otherwise
*/
public PoseModel fetchPoseModel(String path){ public PoseModel fetchPoseModel(String path){
PoseModel rVal = null; PoseModel rVal = null;
if(poseModelsLoadedIntoMemory.containsKey(path)){ if(poseModelsLoadedIntoMemory.containsKey(path)){

View File

@ -36,6 +36,9 @@ public class Timekeeper {
//the maximum number of simulation frames that can happen in a row before the main loop immediately skips more //the maximum number of simulation frames that can happen in a row before the main loop immediately skips more
public static final int SIM_FRAME_HARDCAP = 3; public static final int SIM_FRAME_HARDCAP = 3;
//step interval time size (for physics)
public static final float ENGINE_STEP_SIZE = 0.01f;
@ -135,4 +138,13 @@ public class Timekeeper {
return currentTime; return currentTime;
} }
/**
* The number of frames we're simulating this cycle
* @return The number of frames we're simulating this cycle
*/
public long getDeltaFrames(){
//this should always return 1. We're always simulating 1 frame per run of the loop in main
return 1;
}
} }

View File

@ -1,18 +1,16 @@
package electrosphere.entity; package electrosphere.entity;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.renderer.actor.ActorUtils; import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.actor.instance.InstancedActor;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerDataCell; import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
import electrosphere.server.poseactor.PoseActor; import electrosphere.server.poseactor.PoseActorUtils;
public class EntityCreationUtils { public class EntityCreationUtils {
@ -82,7 +80,7 @@ public class EntityCreationUtils {
* @param modelPath The model path for the model to back the pose actor * @param modelPath The model path for the model to back the pose actor
*/ */
public static void makeEntityPoseable(Entity entity, String modelPath){ public static void makeEntityPoseable(Entity entity, String modelPath){
entity.putData(EntityDataStrings.POSE_ACTOR, new PoseActor(modelPath)); entity.putData(EntityDataStrings.POSE_ACTOR, PoseActorUtils.createPoseActorFromModelPath(modelPath));
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity()); entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));

View File

@ -282,6 +282,11 @@ public class EntityDataStrings {
* Pose actor * Pose actor
*/ */
public static final String POSE_ACTOR = "poseActor"; public static final String POSE_ACTOR = "poseActor";
/**
* Server-specific btrees
*/
public static final String TREE_SERVERPLAYERVIEWDIR = "treeServerPlayerViewDir";
/* /*
Entity categories Entity categories

View File

@ -1,32 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.entity; package electrosphere.entity;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorUtils; import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.model.Model;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerDataCell; import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.poseactor.PoseActor; import electrosphere.server.poseactor.PoseActor;
import electrosphere.server.poseactor.PoseActorUtils;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
/** /**
* * Utilties for dealing with entities
* @author amaterasu
*/ */
public class EntityUtils { public class EntityUtils {
@ -90,7 +78,7 @@ public class EntityUtils {
*/ */
protected static Entity spawnPoseableEntity(String modelPath){ protected static Entity spawnPoseableEntity(String modelPath){
Entity rVal = new Entity(); Entity rVal = new Entity();
rVal.putData(EntityDataStrings.POSE_ACTOR, new PoseActor(modelPath)); rVal.putData(EntityDataStrings.POSE_ACTOR, PoseActorUtils.createPoseActorFromModelPath(modelPath));
// rVal.putData(EntityDataStrings.DATA_STRING_MODEL_PATH, modelPath); // rVal.putData(EntityDataStrings.DATA_STRING_MODEL_PATH, modelPath);
rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity()); rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());

View File

@ -3,19 +3,15 @@ package electrosphere.entity.state.attack;
import electrosphere.net.synchronization.BehaviorTreeIdEnums; import electrosphere.net.synchronization.BehaviorTreeIdEnums;
import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.hitbox.HitboxUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.collidable.Impulse; import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.equip.ClientEquipState; import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree; import electrosphere.entity.state.hitbox.HitboxState;
import electrosphere.entity.state.rotator.RotatorTree; import electrosphere.entity.state.rotator.RotatorTree;
import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.entity.types.collision.CollisionObjUtils;
@ -29,16 +25,11 @@ import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizableEnum; import electrosphere.net.synchronization.annotation.SynchronizableEnum;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.anim.Animation;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.EntityLookupUtils;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Quaternionfc;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -108,8 +99,8 @@ public class ClientAttackTree implements BehaviorTree {
String attackingPoint = null; String attackingPoint = null;
public ClientAttackTree(Entity e){ public ClientAttackTree(Entity e){
state = AttackTreeState.IDLE; setState(AttackTreeState.IDLE);
driftState = AttackTreeDriftState.NO_DRIFT; setDriftState(AttackTreeDriftState.NO_DRIFT);
parent = e; parent = e;
} }
@ -123,6 +114,9 @@ public class ClientAttackTree implements BehaviorTree {
return state; return state;
} }
/**
* Starts an attack
*/
public void start(){ public void start(){
currentMoveCanHold = false; currentMoveCanHold = false;
currentMoveHasWindup = false; currentMoveHasWindup = false;
@ -135,8 +129,8 @@ public class ClientAttackTree implements BehaviorTree {
String attackType = getAttackType(); String attackType = getAttackType();
//if we can attack, setup doing so //if we can attack, setup doing so
if(canAttack(attackType)){ if(canAttack(attackType)){
parent.putData(EntityDataStrings.ATTACK_MOVE_TYPE_ACTIVE, attackType); setAttackMoveTypeActive(attackType);
currentMoveset = (List<AttackMove>)parent.getData(attackType); currentMoveset = getMoveset(attackType);
if(currentMoveset != null){ if(currentMoveset != null){
Globals.clientConnection.queueOutgoingMessage(EntityMessage.constructstartAttackMessage()); Globals.clientConnection.queueOutgoingMessage(EntityMessage.constructstartAttackMessage());
} }
@ -148,23 +142,26 @@ public class ClientAttackTree implements BehaviorTree {
} }
public void interrupt(){ public void interrupt(){
state = AttackTreeState.IDLE; setState(AttackTreeState.IDLE);
} }
public void slowdown(){ public void slowdown(){
state = AttackTreeState.COOLDOWN; setState(AttackTreeState.COOLDOWN);
} }
@Override @Override
public void simulate(float deltaTime){ public void simulate(float deltaTime){
frameCurrent = frameCurrent + (float)Globals.timekeeper.getSimFrameTime(); frameCurrent = frameCurrent + (float)Globals.timekeeper.getDeltaFrames();
float velocity = CreatureUtils.getVelocity(parent); float velocity = CreatureUtils.getVelocity(parent);
Actor entityActor = EntityUtils.getActor(parent); Actor entityActor = EntityUtils.getActor(parent);
Vector3d position = EntityUtils.getPosition(parent); Vector3d position = EntityUtils.getPosition(parent);
Vector3d movementVector = CreatureUtils.getFacingVector(parent); Vector3d movementVector = CreatureUtils.getFacingVector(parent);
//synchronize move from server //synchronize move from server
if(this.currentMove == null && this.currentMoveId != null){ if(this.currentMoveset == null){
this.currentMoveset = getMoveset(getAttackType());
}
if(this.currentMove == null && this.currentMoveId != null && this.currentMoveset != null){
for(AttackMove move : currentMoveset){ for(AttackMove move : currentMoveset){
if(move.getAttackMoveId().equals(currentMoveId)){ if(move.getAttackMoveId().equals(currentMoveId)){
currentMove = move; currentMove = move;
@ -183,23 +180,23 @@ public class ClientAttackTree implements BehaviorTree {
lastUpdateTime = updateTime; lastUpdateTime = updateTime;
switch(message.gettreeState()){ switch(message.gettreeState()){
case 0: case 0:
state = AttackTreeState.WINDUP; setState(AttackTreeState.WINDUP);
frameCurrent = 0; frameCurrent = 0;
// System.out.println("Set state STARTUP"); // System.out.println("Set state STARTUP");
break; break;
case 1: case 1:
frameCurrent = currentMove.getWindupFrames()+1; frameCurrent = currentMove.getWindupFrames()+1;
state = AttackTreeState.ATTACK; setState(AttackTreeState.ATTACK);
// System.out.println("Set state MOVE"); // System.out.println("Set state MOVE");
break; break;
case 2: case 2:
frameCurrent = currentMove.getWindupFrames()+currentMove.getAttackFrames()+1; frameCurrent = currentMove.getWindupFrames()+currentMove.getAttackFrames()+1;
state = AttackTreeState.COOLDOWN; setState(AttackTreeState.COOLDOWN);
// System.out.println("Set state SLOWDOWN"); // System.out.println("Set state SLOWDOWN");
break; break;
case 3: case 3:
frameCurrent = 60; frameCurrent = 60;
state = AttackTreeState.IDLE; setState(AttackTreeState.IDLE);
// System.out.println("Set state IDLE"); // System.out.println("Set state IDLE");
break; break;
} }
@ -230,26 +227,22 @@ public class ClientAttackTree implements BehaviorTree {
//calculate the vector of movement //calculate the vector of movement
CollisionObjUtils.getCollidable(parent).addImpulse(new Impulse(new Vector3d(movementVector), new Vector3d(0,0,0), new Vector3d(0,0,0), currentMove.getDriftGoal() * Globals.timekeeper.getSimFrameTime(), "movement")); CollisionObjUtils.getCollidable(parent).addImpulse(new Impulse(new Vector3d(movementVector), new Vector3d(0,0,0), new Vector3d(0,0,0), currentMove.getDriftGoal() * Globals.timekeeper.getSimFrameTime(), "movement"));
if(frameCurrent > currentMove.getDriftFrameEnd()){ if(frameCurrent > currentMove.getDriftFrameEnd()){
driftState = AttackTreeDriftState.NO_DRIFT; setDriftState(AttackTreeDriftState.NO_DRIFT);
} }
} }
break; break;
case NO_DRIFT: case NO_DRIFT:
if(currentMove != null){ if(currentMove != null){
if(frameCurrent > currentMove.getDriftFrameStart() && frameCurrent < currentMove.getDriftFrameEnd()){ if(frameCurrent > currentMove.getDriftFrameStart() && frameCurrent < currentMove.getDriftFrameEnd()){
driftState = AttackTreeDriftState.DRIFT; setDriftState(AttackTreeDriftState.DRIFT);
} }
} }
break; break;
} }
// if(state != AttackTreeState.IDLE){
// System.out.println(frameCurrent);
// }
//state machine //state machine
switch(state){ switch(state){
case WINDUP: case WINDUP: {
if(parent.containsKey(EntityDataStrings.CLIENT_ROTATOR_TREE)){ if(parent.containsKey(EntityDataStrings.CLIENT_ROTATOR_TREE)){
RotatorTree.getClientRotatorTree(parent).setActive(true); RotatorTree.getClientRotatorTree(parent).setActive(true);
} }
@ -261,35 +254,31 @@ public class ClientAttackTree implements BehaviorTree {
} }
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonWindup().getName()); FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonWindup().getName());
} }
if(currentMoveCanHold && stillHold){ }
state = AttackTreeState.HOLD; } break;
} else { case HOLD: {
state = AttackTreeState.ATTACK; if(entityActor != null){
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(currentMove.getHoldAnimationName())){
entityActor.playAnimation(currentMove.getHoldAnimationName(),1);
entityActor.incrementAnimationTime(0.0001);
} }
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonHold().getName());
} }
break; } break;
case HOLD: case ATTACK: {
if(entityActor != null){ if(entityActor != null && currentMove != null){
if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationName)){ if(!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(currentMove.getAttackAnimationName())){
entityActor.playAnimation(animationName,1); entityActor.playAnimation(currentMove.getAttackAnimationName(),1);
entityActor.incrementAnimationTime(0.0001); entityActor.incrementAnimationTime(0.0001);
}
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonAttack().getName());
} }
FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonHold().getName()); //activate hitboxes
} List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
if(!stillHold){ for(Entity currentAttached : attachedEntities){
state = AttackTreeState.ATTACK; if(HitboxState.hasHitboxState(currentAttached)){
} HitboxState currentState = HitboxState.getHitboxState(currentAttached);
break; currentState.setActive(true);
case ATTACK:
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
for(Entity currentAttached : attachedEntities){
if(currentAttached.containsKey(EntityDataStrings.HITBOX_ASSOCIATED_LIST)){
List<Entity> hitboxes = HitboxUtils.getHitboxAssociatedList(currentAttached);
for(Entity hitbox : hitboxes){
HitboxUtils.getHitboxData(hitbox).setActive(true);
}
}
} }
} }
if(firesProjectile && projectileToFire != null){ if(firesProjectile && projectileToFire != null){
@ -325,34 +314,27 @@ public class ClientAttackTree implements BehaviorTree {
ProjectileUtils.clientSpawnBasicProjectile(projectileToFire, spawnPosition, arrowRotation, 750, initialVector, 0.03f); ProjectileUtils.clientSpawnBasicProjectile(projectileToFire, spawnPosition, arrowRotation, 750, initialVector, 0.03f);
projectileToFire = null; projectileToFire = null;
} }
if(currentMove != null && frameCurrent > currentMove.getWindupFrames() + currentMove.getAttackFrames()){ } break;
state = AttackTreeState.COOLDOWN; case COOLDOWN: {
} //deactive hitboxes
break; List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
case COOLDOWN: for(Entity currentAttached : attachedEntities){
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){ if(HitboxState.hasHitboxState(currentAttached)){
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent); HitboxState currentState = HitboxState.getHitboxState(currentAttached);
for(Entity currentAttached : attachedEntities){ currentState.setActive(false);
if(currentAttached.containsKey(EntityDataStrings.HITBOX_ASSOCIATED_LIST)){
List<Entity> hitboxes = HitboxUtils.getHitboxAssociatedList(currentAttached);
for(Entity hitbox : hitboxes){
HitboxUtils.getHitboxData(hitbox).setActive(false);
}
}
} }
} }
if(currentMove != null && frameCurrent > currentMove.getWindupFrames() + currentMove.getAttackFrames() + currentMove.getCooldownFrames()){ if(currentMove != null && frameCurrent > currentMove.getWindupFrames() + currentMove.getAttackFrames() + currentMove.getCooldownFrames()){
state = AttackTreeState.IDLE;
frameCurrent = 0; frameCurrent = 0;
if(parent.containsKey(EntityDataStrings.CLIENT_ROTATOR_TREE)){ if(parent.containsKey(EntityDataStrings.CLIENT_ROTATOR_TREE)){
RotatorTree.getClientRotatorTree(parent).setActive(false); RotatorTree.getClientRotatorTree(parent).setActive(false);
} }
} }
break; } break;
case IDLE: case IDLE: {
currentMove = null; currentMove = null;
currentMoveset = null; currentMoveset = null;
break; } break;
} }
} }
@ -360,6 +342,10 @@ public class ClientAttackTree implements BehaviorTree {
networkMessageQueue.add(networkMessage); networkMessageQueue.add(networkMessage);
} }
/**
* Gets the current attack type
* @return The current attack type
*/
String getAttackType(){ String getAttackType(){
String rVal = null; String rVal = null;
if(ClientEquipState.hasEquipState(parent)){ if(ClientEquipState.hasEquipState(parent)){
@ -433,6 +419,23 @@ public class ClientAttackTree implements BehaviorTree {
} }
return rVal; return rVal;
} }
/**
* Sets the current attack type of the entity
* @param attackType the current attack type
*/
public void setAttackMoveTypeActive(String attackType){
parent.putData(EntityDataStrings.ATTACK_MOVE_TYPE_ACTIVE, attackType);
}
/**
* Gets the current moveset
* @param attackType the attack type
* @return The moveset if it exists
*/
public List<AttackMove> getMoveset(String attackType){
return (List<AttackMove>)parent.getData(attackType);
}
/** /**
* <p> Automatically generated </p> * <p> Automatically generated </p>

View File

@ -9,22 +9,19 @@ import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.server.datacell.utils.DataCellSearchUtils; import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.hitbox.HitboxUtils; import electrosphere.collision.hitbox.HitboxUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeDriftState; import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeDriftState;
import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeState; import electrosphere.entity.state.attack.ClientAttackTree.AttackTreeState;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.collidable.Impulse; import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.equip.ServerEquipState; import electrosphere.entity.state.equip.ServerEquipState;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree; import electrosphere.entity.state.hitbox.HitboxState;
import electrosphere.entity.state.movement.groundmove.ServerGroundMovementTree; import electrosphere.entity.state.movement.groundmove.ServerGroundMovementTree;
import electrosphere.entity.state.rotator.RotatorTree;
import electrosphere.entity.state.rotator.ServerRotatorTree; import electrosphere.entity.state.rotator.ServerRotatorTree;
import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.entity.types.collision.CollisionObjUtils;
@ -37,17 +34,13 @@ import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.synchronization.annotation.SyncedField; import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.anim.Animation;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.poseactor.PoseActor; import electrosphere.server.poseactor.PoseActor;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Quaternionfc;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -58,9 +51,11 @@ import org.joml.Vector3f;
public class ServerAttackTree implements BehaviorTree { public class ServerAttackTree implements BehaviorTree {
@SyncedField @SyncedField
//the state of the attack tree
AttackTreeState state; AttackTreeState state;
@SyncedField @SyncedField
//the state of drifting caused by the attack animation
AttackTreeDriftState driftState; AttackTreeDriftState driftState;
Entity parent; Entity parent;
@ -115,8 +110,8 @@ public class ServerAttackTree implements BehaviorTree {
String attackType = getAttackType(); String attackType = getAttackType();
//if we can attack, setup doing so //if we can attack, setup doing so
if(canAttack(attackType)){ if(canAttack(attackType)){
parent.putData(EntityDataStrings.ATTACK_MOVE_TYPE_ACTIVE, attackType); setAttackMoveTypeActive(attackType);
currentMoveset = (List<AttackMove>)parent.getData(attackType); currentMoveset = getMoveset(attackType);
if(currentMoveset != null){ if(currentMoveset != null){
if(currentMove == null){ if(currentMove == null){
currentMove = currentMoveset.get(0); currentMove = currentMoveset.get(0);
@ -171,7 +166,7 @@ public class ServerAttackTree implements BehaviorTree {
@Override @Override
public void simulate(float deltaTime){ public void simulate(float deltaTime){
frameCurrent = frameCurrent + (float)Globals.timekeeper.getSimFrameTime(); frameCurrent = frameCurrent + (float)Globals.timekeeper.getDeltaFrames();
float velocity = CreatureUtils.getVelocity(parent); float velocity = CreatureUtils.getVelocity(parent);
PoseActor entityPoseActor = EntityUtils.getPoseActor(parent); PoseActor entityPoseActor = EntityUtils.getPoseActor(parent);
Vector3d position = EntityUtils.getPosition(parent); Vector3d position = EntityUtils.getPosition(parent);
@ -247,7 +242,7 @@ public class ServerAttackTree implements BehaviorTree {
//state machine //state machine
switch(state){ switch(state){
case WINDUP: case WINDUP: {
if(parent.containsKey(EntityDataStrings.SERVER_ROTATOR_TREE)){ if(parent.containsKey(EntityDataStrings.SERVER_ROTATOR_TREE)){
ServerRotatorTree.getServerRotatorTree(parent).setActive(true); ServerRotatorTree.getServerRotatorTree(parent).setActive(true);
} }
@ -278,28 +273,32 @@ public class ServerAttackTree implements BehaviorTree {
0 0
) )
); );
break; } break;
case HOLD: case HOLD: {
if(entityPoseActor != null){ if(entityPoseActor != null){
if(!entityPoseActor.isPlayingAnimation() || !entityPoseActor.isPlayingAnimation(animationName)){ if(!entityPoseActor.isPlayingAnimation() || !entityPoseActor.isPlayingAnimation(animationName)){
entityPoseActor.playAnimation(animationName,1); entityPoseActor.playAnimation(animationName,1);
entityPoseActor.incrementAnimationTime(0.0001); entityPoseActor.incrementAnimationTime(0.0001);
}
} }
} if(!stillHold){
if(!stillHold){ setState(AttackTreeState.ATTACK);
setState(AttackTreeState.ATTACK); }
} } break;
break; case ATTACK: {
case ATTACK: if(entityPoseActor != null && currentMove != null){
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){ if(!entityPoseActor.isPlayingAnimation() || !entityPoseActor.isPlayingAnimation(currentMove.getAttackAnimationName())){
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent); entityPoseActor.playAnimation(currentMove.getAttackAnimationName(),1);
for(Entity currentAttached : attachedEntities){ entityPoseActor.incrementAnimationTime(0.0001);
if(currentAttached.containsKey(EntityDataStrings.HITBOX_ASSOCIATED_LIST)){ }
List<Entity> hitboxes = HitboxUtils.getHitboxAssociatedList(currentAttached); FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, currentMove.getAnimationFirstPersonAttack().getName());
for(Entity hitbox : hitboxes){ }
HitboxUtils.getHitboxData(hitbox).setActive(true); //activate hitboxes
} List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
} for(Entity currentAttached : attachedEntities){
if(HitboxState.hasHitboxState(currentAttached)){
HitboxState currentState = HitboxState.getHitboxState(currentAttached);
currentState.setActive(true);
} }
} }
if(firesProjectile && projectileToFire != null){ if(firesProjectile && projectileToFire != null){
@ -353,17 +352,14 @@ public class ServerAttackTree implements BehaviorTree {
1 1
) )
); );
break; } break;
case COOLDOWN: case COOLDOWN: {
if(parent.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST)){ //deactive hitboxes
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent); List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
for(Entity currentAttached : attachedEntities){ for(Entity currentAttached : attachedEntities){
if(currentAttached.containsKey(EntityDataStrings.HITBOX_ASSOCIATED_LIST)){ if(HitboxState.hasHitboxState(currentAttached)){
List<Entity> hitboxes = HitboxUtils.getHitboxAssociatedList(currentAttached); HitboxState currentState = HitboxState.getHitboxState(currentAttached);
for(Entity hitbox : hitboxes){ currentState.setActive(false);
HitboxUtils.getHitboxData(hitbox).setActive(false);
}
}
} }
} }
if(frameCurrent > currentMove.getWindupFrames() + currentMove.getAttackFrames() + currentMove.getCooldownFrames()){ if(frameCurrent > currentMove.getWindupFrames() + currentMove.getAttackFrames() + currentMove.getCooldownFrames()){
@ -387,11 +383,11 @@ public class ServerAttackTree implements BehaviorTree {
2 2
) )
); );
break; } break;
case IDLE: case IDLE: {
currentMove = null; currentMove = null;
currentMoveset = null; currentMoveset = null;
break; } break;
} }
} }
@ -471,6 +467,23 @@ public class ServerAttackTree implements BehaviorTree {
} }
return rVal; return rVal;
} }
/**
* Sets the current attack type of the entity
* @param attackType the current attack type
*/
public void setAttackMoveTypeActive(String attackType){
parent.putData(EntityDataStrings.ATTACK_MOVE_TYPE_ACTIVE, attackType);
}
/**
* Gets the current moveset
* @param attackType the attack type
* @return The moveset if it exists
*/
public List<AttackMove> getMoveset(String attackType){
return (List<AttackMove>)parent.getData(attackType);
}
/** /**
* <p> Automatically generated </p> * <p> Automatically generated </p>

View File

@ -115,7 +115,7 @@ public class FirstPersonTree implements BehaviorTree {
* @param animationName the name of the animation * @param animationName the name of the animation
*/ */
public static void conditionallyPlayAnimation(Entity entity, String animationName){ public static void conditionallyPlayAnimation(Entity entity, String animationName){
if(hasTree(entity)){ if(entity != null && hasTree(entity)){
getTree(entity).playAnimation(animationName); getTree(entity).playAnimation(animationName);
} }
} }

View File

@ -72,7 +72,6 @@ public class ClientEquipState implements BehaviorTree {
boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId()); boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId());
boolean targetIsItem = ItemUtils.isItem(toEquip); boolean targetIsItem = ItemUtils.isItem(toEquip);
boolean targetIsAttached = AttachUtils.isAttached(toEquip); boolean targetIsAttached = AttachUtils.isAttached(toEquip);
boolean targetHasWhitelist = ItemUtils.hasEquipList(toEquip);
String equipItemClass = ItemUtils.getEquipClass(toEquip); String equipItemClass = ItemUtils.getEquipClass(toEquip);
List<String> pointEquipClassList = point.getEquipClassWhitelist(); List<String> pointEquipClassList = point.getEquipClassWhitelist();
boolean itemIsInPointWhitelist = pointEquipClassList.contains(equipItemClass); boolean itemIsInPointWhitelist = pointEquipClassList.contains(equipItemClass);
@ -90,7 +89,7 @@ public class ClientEquipState implements BehaviorTree {
* @param toEquip The entity to equip * @param toEquip The entity to equip
* @param point The equipment point to equip to * @param point The equipment point to equip to
*/ */
public void clientAttemptEquip(Entity toEquip, EquipPoint point){ public void attemptEquip(Entity toEquip, EquipPoint point){
boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId()); boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId());
boolean targetIsItem = ItemUtils.isItem(toEquip); boolean targetIsItem = ItemUtils.isItem(toEquip);
boolean targetIsAttached = AttachUtils.isAttached(toEquip); boolean targetIsAttached = AttachUtils.isAttached(toEquip);

View File

@ -0,0 +1,370 @@
package electrosphere.entity.state.hitbox;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.ode4j.ode.DBody;
import org.ode4j.ode.DGeom;
import electrosphere.collision.CollisionBodyCreation;
import electrosphere.collision.CollisionEngine;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.hitbox.HitboxManager;
import electrosphere.collision.hitbox.HitboxUtils.HitboxPositionCallback;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.game.data.collidable.HitboxData;
/**
* The hitbox state of this entity
*/
public class HitboxState {
/**
* Types of hitboxes
*/
public enum HitboxType {
HIT, // damages another entity
HURT, // receives damage from another entity
BLOCK, // blocks a hit from another entity
}
//the parent entity of the hitbox state
Entity parent;
//the body that contains all the hitbox shapes
DBody body;
//The collidable associated with the body
Collidable collidable;
//the map of bone -> hitbox shape in ode4j
Map<String,DGeom> hitboxGeomMap = new HashMap<String,DGeom>();
//the map of geometry -> hitbox shape status, useful for finding data about a given hitbox during collision
Map<DGeom,HitboxShapeStatus> geomBoneMap = new HashMap<DGeom,HitboxShapeStatus>();
//callback to provide a position for the hitbox each frame
HitboxPositionCallback positionCallback;
//controls whether the hitbox state is active or not
boolean active = true;
//the associated manager
HitboxManager manager;
/**
* Create hitbox state for an entity
* @param collisionEngine the collision engine
* @param entity The entity to attach the state to
* @param hitboxListRaw The list of hitbox data to apply
* @return The hitbox state that has been attached to the entity
*/
public static HitboxState attachHitboxState(HitboxManager manager, Entity entity, List<HitboxData> hitboxListRaw){
HitboxState rVal = new HitboxState();
//create the shapes
for(HitboxData hitboxDataRaw : hitboxListRaw){
DGeom geom = CollisionBodyCreation.createShapeSphere(manager.getCollisionEngine(), hitboxDataRaw.getRadius(), Collidable.TYPE_OBJECT_BIT);
rVal.hitboxGeomMap.put(hitboxDataRaw.getBone(),geom);
HitboxType type = HitboxType.HIT;
switch(hitboxDataRaw.getType()){
case "HIT": {
type = HitboxType.HIT;
} break;
case "HURT": {
type = HitboxType.HURT;
} break;
}
rVal.geomBoneMap.put(geom,new HitboxShapeStatus(hitboxDataRaw.getBone(), type, true));
}
//create body with all the shapes
DGeom[] geomArray = rVal.hitboxGeomMap.values().toArray(new DGeom[rVal.hitboxGeomMap.values().size()]);
rVal.body = CollisionBodyCreation.createBodyWithShapes(manager.getCollisionEngine(), geomArray);
//register collidable with collision engine
Collidable collidable = new Collidable(entity, Collidable.TYPE_OBJECT);
manager.getCollisionEngine().registerCollisionObject(rVal.body, collidable);
//attach
entity.putData(EntityDataStrings.HITBOX_DATA, rVal);
rVal.parent = entity;
//register
manager.registerHitbox(rVal);
rVal.manager = manager;
return rVal;
}
/**
* Create hitbox state for an entity
* @param collisionEngine the collision engine
* @param entity The entity to attach the state to
* @param data The hitbox data to apply
* @param callback The callback that provides a position for the hitbox each frame
* @return The hitbox state that has been attached to the entity
*/
public static HitboxState attachHitboxStateWithCallback(HitboxManager manager, CollisionEngine collisionEngine, Entity entity, HitboxData data, HitboxPositionCallback callback){
HitboxState rVal = new HitboxState();
//create the shapes
rVal.hitboxGeomMap.put(data.getBone(),CollisionBodyCreation.createShapeSphere(collisionEngine, data.getRadius(), Collidable.TYPE_OBJECT_BIT));
//create body with all the shapes
DGeom[] geomArray = rVal.hitboxGeomMap.values().toArray(new DGeom[rVal.hitboxGeomMap.values().size()]);
rVal.body = CollisionBodyCreation.createBodyWithShapes(collisionEngine, geomArray);
//register collidable with collision engine
Collidable collidable = new Collidable(entity, Collidable.TYPE_OBJECT);
collisionEngine.registerCollisionObject(rVal.body, collidable);
//attach
entity.putData(EntityDataStrings.HITBOX_DATA, rVal);
rVal.parent = entity;
//register
manager.registerHitbox(rVal);
rVal.manager = manager;
return rVal;
}
/**
* Updates the positions of all hitboxes
*/
public void updateHitboxPositions(CollisionEngine collisionEngine){
if(parent != null && EntityUtils.getActor(parent) != null){
if(!this.hitboxGeomMap.isEmpty()){
Vector3d entityPosition = EntityUtils.getPosition(parent);
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
for(String boneName : this.hitboxGeomMap.keySet()){
DGeom geom = this.hitboxGeomMap.get(boneName);
Quaterniond parentRotation = EntityUtils.getRotation(parent);
Vector3f positionScale = EntityUtils.getScale(parent);
Vector3d worldPosition = new Vector3d();
Vector3f bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName);
Vector3d parentPos = EntityUtils.getPosition(parent);
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
Quaterniond rotation = new Quaterniond(parentRotation);
worldPosition = worldPosition.mul(positionScale);
worldPosition = worldPosition.rotate(rotation);
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
}
} else if(positionCallback != null){
DGeom geom = body.getGeomIterator().next();
Vector3d worldPosition = this.positionCallback.getPosition();
Quaterniond rotation = new Quaterniond().identity();
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
}
} else if(parent != null && EntityUtils.getPoseActor(parent) != null){
if(!this.hitboxGeomMap.isEmpty()){
Vector3d entityPosition = EntityUtils.getPosition(parent);
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
for(String boneName : this.hitboxGeomMap.keySet()){
DGeom geom = this.hitboxGeomMap.get(boneName);
Quaterniond parentRotation = EntityUtils.getRotation(parent);
Vector3f positionScale = EntityUtils.getScale(parent);
Vector3d worldPosition = new Vector3d();
Vector3f bonePosition = EntityUtils.getPoseActor(parent).getBonePosition(boneName);
Vector3d parentPos = EntityUtils.getPosition(parent);
worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z);
Quaterniond rotation = new Quaterniond(parentRotation);
worldPosition = worldPosition.mul(positionScale);
worldPosition = worldPosition.rotate(rotation);
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
}
} else if(positionCallback != null){
DGeom geom = body.getGeomIterator().next();
Vector3d worldPosition = this.positionCallback.getPosition();
Quaterniond rotation = new Quaterniond().identity();
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
}
}
}
/**
* Gets the status of a shape in the hitbox object
* @param geom The geometry that is the shape within the hitbox data
* @return The status of the shape
*/
public HitboxShapeStatus getShapeStatus(DGeom geom){
return this.geomBoneMap.get(geom);
}
/**
* Gets the hitbox state of the entity
* @param entity the entity
* @return the hitbox state if it exists
*/
public static HitboxState getHitboxState(Entity entity){
return (HitboxState)entity.getData(EntityDataStrings.HITBOX_DATA);
}
/**
* Checks whether the entity has hitbox state or not
* @param entity the entity to check
* @return true if there is hitbox state, false otherwise
*/
public static boolean hasHitboxState(Entity entity){
return entity.containsKey(EntityDataStrings.HITBOX_DATA);
}
/**
* Destroys the hitbox state and removes it from the entity
* @param entity the entity
* @return The hitbox state if it exists, null otherwise
*/
public static HitboxState destroyHitboxState(Entity entity){
HitboxState state = null;
if(hasHitboxState(entity)){
state = getHitboxState(entity);
state.manager.deregisterHitbox(state);
}
return state;
}
/**
* Gets whether the hitbox state is active or not
* @return true if active, false otherwise
*/
public boolean isActive(){
return active;
}
/**
* Sets the active state of the hitbox
* @param state true to make it active, false otherwise
*/
public void setActive(boolean state){
this.active = state;
}
/**
* Gets the collection of all DGeoms in the data
* @return the collection of all DGeoms
*/
public Collection<DGeom> getGeometries(){
return this.hitboxGeomMap.values();
}
/**
* Gets the set of bone names in the state data
* @return The set of bone names in the state data
*/
public Set<String> getBones(){
return this.hitboxGeomMap.keySet();
}
/**
* Gets geometry on a single hitbox based on its bone name
* @param boneName the bone name
* @return the hitbox geometry
*/
public DGeom getGeometry(String boneName){
return this.hitboxGeomMap.get(boneName);
}
/**
* The status of a single shape inside the overall hitbox data
* IE a single sphere on the overall body
*/
public static class HitboxShapeStatus {
//the name of the bone the hitbox is attached to
String boneName;
//the type of hitbox
HitboxType type;
//controls whether the hitbox is active
boolean isActive;
/**
* Creates a status object for a hitbox
* @param boneName The name of the bone the hitbox is attached to, if any
* @param type The type of hitbox
* @param isActive if the hitbox is active or not
*/
public HitboxShapeStatus(String boneName, HitboxType type, boolean isActive){
this.boneName = boneName;
this.type = type;
this.isActive = isActive;
}
/**
* Gets the name of the bone the hitbox is attached to
* @return The name of the bone
*/
public String getBoneName(){
return boneName;
}
/**
* Sets the name of the bone the hitbox is attached to
* @param boneName The bone name
*/
public void setBoneName(String boneName){
this.boneName = boneName;
}
/**
* Gets the type of hitbox
* @return The type
*/
public HitboxType getType(){
return type;
}
/**
* Sets the type of hitbox
* @param type The type
*/
public void setType(HitboxType type){
this.type = type;
}
/**
* Gets whether the hitbox is active or not
* @return true if active, false otherwise
*/
public boolean isActive(){
return isActive;
}
/**
* Sets whether the hitbox is active or not
* @param active true for active, false otherwise
*/
public void setActive(boolean active){
this.isActive = active;
}
}
}

View File

@ -3,20 +3,13 @@ package electrosphere.entity.state.movement.groundmove;
import electrosphere.net.synchronization.BehaviorTreeIdEnums; import electrosphere.net.synchronization.BehaviorTreeIdEnums;
import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.gravity.ClientGravityTree;
import electrosphere.entity.state.gravity.GravityUtils; import electrosphere.entity.state.gravity.GravityUtils;
import electrosphere.collision.CollisionEngine;
import electrosphere.collision.PhysicsEntityUtils; import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.creature.type.movement.GroundMovementSystem; import electrosphere.game.data.creature.type.movement.GroundMovementSystem;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
@ -28,24 +21,17 @@ import electrosphere.entity.state.movement.FallTree;
import electrosphere.entity.state.movement.JumpTree; import electrosphere.entity.state.movement.JumpTree;
import electrosphere.entity.state.movement.SprintTree; import electrosphere.entity.state.movement.SprintTree;
import electrosphere.entity.state.movement.SprintTree.SprintTreeState; import electrosphere.entity.state.movement.SprintTree.SprintTreeState;
import electrosphere.net.NetUtils;
import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.synchronization.annotation.SyncedField; import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
import electrosphere.renderer.anim.Animation; import electrosphere.renderer.anim.Animation;
import electrosphere.renderer.model.Model;
import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f;
import org.ode4j.math.DVector3;
import org.ode4j.math.DVector3C; import org.ode4j.math.DVector3C;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
@ -69,6 +55,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
* The relative facing of the character to its rotation * The relative facing of the character to its rotation
* (ie is it strafing, moveing straight forward, backpedaling, etc) * (ie is it strafing, moveing straight forward, backpedaling, etc)
*/ */
@SynchronizableEnum
public static enum MovementRelativeFacing { public static enum MovementRelativeFacing {
FORWARD, FORWARD,
LEFT, LEFT,
@ -126,7 +113,6 @@ public class ClientGroundMovementTree implements BehaviorTree {
//if we aren't the server, alert the server we intend to walk forward //if we aren't the server, alert the server we intend to walk forward
Vector3d position = EntityUtils.getPosition(parent); Vector3d position = EntityUtils.getPosition(parent);
Quaterniond rotation = EntityUtils.getRotation(parent); Quaterniond rotation = EntityUtils.getRotation(parent);
Vector3d facingVector = CreatureUtils.getFacingVector(parent);
float velocity = CreatureUtils.getVelocity(parent); float velocity = CreatureUtils.getVelocity(parent);
Globals.clientConnection.queueOutgoingMessage( Globals.clientConnection.queueOutgoingMessage(
EntityMessage.constructmoveUpdateMessage( EntityMessage.constructmoveUpdateMessage(
@ -156,7 +142,6 @@ public class ClientGroundMovementTree implements BehaviorTree {
//if we aren't the server, alert the server we intend to slow down //if we aren't the server, alert the server we intend to slow down
Vector3d position = EntityUtils.getPosition(parent); Vector3d position = EntityUtils.getPosition(parent);
Quaterniond rotation = EntityUtils.getRotation(parent); Quaterniond rotation = EntityUtils.getRotation(parent);
Vector3d facingVector = CreatureUtils.getFacingVector(parent);
float velocity = CreatureUtils.getVelocity(parent); float velocity = CreatureUtils.getVelocity(parent);
Globals.clientConnection.queueOutgoingMessage( Globals.clientConnection.queueOutgoingMessage(
EntityMessage.constructmoveUpdateMessage( EntityMessage.constructmoveUpdateMessage(

View File

@ -3,15 +3,10 @@ package electrosphere.entity.state.movement.groundmove;
import electrosphere.net.synchronization.BehaviorTreeIdEnums; import electrosphere.net.synchronization.BehaviorTreeIdEnums;
import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.gravity.GravityUtils; import electrosphere.entity.state.gravity.GravityUtils;
import electrosphere.collision.CollisionEngine;
import electrosphere.collision.PhysicsEntityUtils; import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
@ -25,28 +20,21 @@ import electrosphere.entity.state.movement.ServerSprintTree;
import electrosphere.entity.state.movement.ServerSprintTree.SprintTreeState; import electrosphere.entity.state.movement.ServerSprintTree.SprintTreeState;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementRelativeFacing; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementRelativeFacing;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementTreeState; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementTreeState;
import electrosphere.net.NetUtils;
import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.synchronization.annotation.SyncedField; import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
import electrosphere.renderer.anim.Animation; import electrosphere.renderer.anim.Animation;
import electrosphere.renderer.model.Model;
import electrosphere.server.datacell.utils.DataCellSearchUtils; import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.server.poseactor.PoseActor; import electrosphere.server.poseactor.PoseActor;
import electrosphere.renderer.actor.Actor;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f;
import org.ode4j.math.DVector3C; import org.ode4j.math.DVector3C;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
@SynchronizedBehaviorTree(name = "serverGroundMovementTree", isServer = false, correspondingTree="clientGroundMovementTree") @SynchronizedBehaviorTree(name = "serverGroundMovementTree", isServer = true, correspondingTree="clientGroundMovementTree")
/* /*
Behavior tree for movement in an entity Behavior tree for movement in an entity
*/ */
@ -91,6 +79,10 @@ public class ServerGroundMovementTree implements BehaviorTree {
return state; return state;
} }
/**
* Starts the server movement tree
* @param facing The facing dir to start with
*/
public void start(MovementRelativeFacing facing){ public void start(MovementRelativeFacing facing){
if(canStartMoving()){ if(canStartMoving()){
setFacing(facing); setFacing(facing);
@ -98,7 +90,6 @@ public class ServerGroundMovementTree implements BehaviorTree {
//if we aren't the server, alert the server we intend to walk forward //if we aren't the server, alert the server we intend to walk forward
Vector3d position = EntityUtils.getPosition(parent); Vector3d position = EntityUtils.getPosition(parent);
Quaterniond rotation = EntityUtils.getRotation(parent); Quaterniond rotation = EntityUtils.getRotation(parent);
Vector3d facingVector = CreatureUtils.getFacingVector(parent);
float velocity = CreatureUtils.getVelocity(parent); float velocity = CreatureUtils.getVelocity(parent);
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(
EntityMessage.constructmoveUpdateMessage( EntityMessage.constructmoveUpdateMessage(
@ -128,7 +119,6 @@ public class ServerGroundMovementTree implements BehaviorTree {
//if we aren't the server, alert the server we intend to slow down //if we aren't the server, alert the server we intend to slow down
Vector3d position = EntityUtils.getPosition(parent); Vector3d position = EntityUtils.getPosition(parent);
Quaterniond rotation = EntityUtils.getRotation(parent); Quaterniond rotation = EntityUtils.getRotation(parent);
Vector3d facingVector = CreatureUtils.getFacingVector(parent);
float velocity = CreatureUtils.getVelocity(parent); float velocity = CreatureUtils.getVelocity(parent);
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(
EntityMessage.constructmoveUpdateMessage( EntityMessage.constructmoveUpdateMessage(
@ -213,9 +203,20 @@ public class ServerGroundMovementTree implements BehaviorTree {
case MOVEUPDATE: { case MOVEUPDATE: {
if(updateTime >= lastUpdateTime){ if(updateTime >= lastUpdateTime){
lastUpdateTime = updateTime; lastUpdateTime = updateTime;
switch(message.gettreeState()){
//0 is startup
case 0: {
start(MovementRelativeFacing.FORWARD);
} break;
case 2: {
slowdown();
} break;
default: {
} break;
}
//we want to always update the server facing vector with where the client says they're facing //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()); EntityUtils.getRotation(parent).set(message.getrotationX(),message.getrotationY(),message.getrotationZ(),message.getrotationW());
CreatureUtils.setFacingVector(parent, new Vector3d(0,0,1).rotate(EntityUtils.getRotation(parent)));
break; break;
} }
} break; } break;

View File

@ -0,0 +1,85 @@
package electrosphere.entity.state.server;
import org.joml.Vector3d;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.types.creature.CreatureUtils;
/**
* Stores the direction that the server thinks the player is looking
*/
public class ServerPlayerViewDirTree implements BehaviorTree {
//the direction of the view
Vector3d playerViewDir = new Vector3d();
//the last time this value was updated
long lastUpdateTime = 0;
//the parent entity
Entity parent;
@Override
public void simulate(float deltaTime) {
}
/**
* Constructor
* @param parent
*/
private ServerPlayerViewDirTree(Entity parent){
this.parent = parent;
}
/**
* Attaches a ServerPlayerViewDirTree to a given entity
* @param entity The entity to add to
*/
public static void attachServerPlayerViewDirTree(Entity entity){
ServerPlayerViewDirTree tree = new ServerPlayerViewDirTree(entity);
entity.putData(EntityDataStrings.TREE_SERVERPLAYERVIEWDIR, tree);
}
/**
* Gets the server player view dir tree if it exists
* @param entity The entity to get from
* @return The ServerPlayerViewDirTree if it exists, null otherwise
*/
public static ServerPlayerViewDirTree getTree(Entity entity){
return (ServerPlayerViewDirTree)entity.getData(EntityDataStrings.TREE_SERVERPLAYERVIEWDIR);
}
/**
* Checks whether the entity has a copy of this btree or not
* @param entity The entity
* @return true if the entity has the btree, false otherwise
*/
public static boolean hasTree(Entity entity){
return entity.containsKey(EntityDataStrings.TREE_SERVERPLAYERVIEWDIR);
}
/**
* Gets the player view dir
* @return The player view dir
*/
public Vector3d getPlayerViewDir(){
return playerViewDir;
}
/**
* Sets the player view dir vector
* @param playerViewDir The player view dir vector
*/
public void setPlayerViewDir(Vector3d playerViewDir, long time){
if(time > lastUpdateTime){
this.playerViewDir = playerViewDir;
this.lastUpdateTime = time;
CreatureUtils.setFacingVector(parent, new Vector3d(-playerViewDir.x,0,-playerViewDir.z));
}
}
}

View File

@ -7,7 +7,6 @@ import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.model.Model;
import electrosphere.server.datacell.ServerDataCell; import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.datacell.utils.ServerEntityTagUtils; import electrosphere.server.datacell.utils.ServerEntityTagUtils;
import electrosphere.server.poseactor.PoseActor; import electrosphere.server.poseactor.PoseActor;
@ -18,10 +17,8 @@ import java.util.List;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector4d;
/** /**
* Utilities for attaching entities to entities * Utilities for attaching entities to entities
@ -39,7 +36,28 @@ public class AttachUtils {
// FUNCTIONS TO UPDATE ATTACHMENTS FOR CURRENT FRAME // FUNCTIONS TO UPDATE ATTACHMENTS FOR CURRENT FRAME
// //
///
///
/// SERVER
///
///
/**
* Updates positions of all attached entities in a data cell
* @param cell The data cell
*/
public static void serverUpdateAttachedEntityPositions(ServerDataCell cell){ public static void serverUpdateAttachedEntityPositions(ServerDataCell cell){
Globals.profiler.beginCpuSample("AttachUtils.serverUpdateAttachedEntityPositions");
serverUpdateBoneAttachedEntityPositions(cell);
serverUpdateNonBoneAttachments(cell);
Globals.profiler.endCpuSample();
}
/**
* Updates entities attached to bones of actors in a data cell
* @param cell The data cell
*/
public static void serverUpdateBoneAttachedEntityPositions(ServerDataCell cell){
for(Entity currentEntity : cell.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){ for(Entity currentEntity : cell.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){
Entity parent; Entity parent;
if((parent = (Entity)currentEntity.getData(EntityDataStrings.ATTACH_PARENT))!=null){ if((parent = (Entity)currentEntity.getData(EntityDataStrings.ATTACH_PARENT))!=null){
@ -68,25 +86,97 @@ public class AttachUtils {
.mul(offsetRotation) .mul(offsetRotation)
.normalize(); .normalize();
} }
} else if(currentEntity.getData(EntityDataStrings.ATTACH_TARGET_BASE)!=null){
Vector3d positionOffset = getAttachPositionOffset(currentEntity);
Vector3d parentPosition = EntityUtils.getPosition(parent);
EntityUtils.getPosition(currentEntity).set(new Vector3d(parentPosition).add(positionOffset));
} }
} }
} }
/**
* Updates entities that aren't attached to a bone directly in a data cell
* @param cell the data cell
*/
private static void serverUpdateNonBoneAttachments(ServerDataCell cell){
Globals.profiler.beginCpuSample("AttachUtils.serverUpdateNonBoneAttachments");
Matrix4d parentTransform = new Matrix4d().identity();
Vector3d position = new Vector3d();
Quaterniond rotation = new Quaterniond();
Vector3d scaleRaw = new Vector3d();
Vector3f scale = new Vector3f();
Entity parent;
Matrix4f transform;
//update entities attached to centerpoint + transform of other entities
for(Entity currentEntity : cell.getScene().getEntitiesWithTag(EntityTags.TRANSFORM_ATTACHED)){
if((parent = (Entity)currentEntity.getData(EntityDataStrings.ATTACH_PARENT))!=null){
if((transform = getTransformOffset(currentEntity))!=null){
//parent objects
Vector3d parentPosition = EntityUtils.getPosition(parent);
Quaterniond parentRotation = EntityUtils.getRotation(parent);
Vector3f parentScale = EntityUtils.getScale(parent);
// calculate new transform for current entity
parentTransform.identity()
.translate(parentPosition)
.rotate(parentRotation)
.scale(parentScale.x,parentScale.y,parentScale.z)
.mul(transform);
//transform bone space
parentTransform.getTranslation(position);
parentTransform.getUnnormalizedRotation(rotation).normalize();
parentTransform.getScale(scaleRaw);
scale.set((float)scaleRaw.x,(float)scaleRaw.y,(float)scaleRaw.z);
//transform worldspace
// position.add(new Vector3d(EntityUtils.getPosition(parent)));
//set
EntityUtils.getPosition(currentEntity).set(position);
EntityUtils.getRotation(currentEntity).set(rotation);
EntityUtils.getScale(currentEntity).set(scale);
}
}
}
Globals.profiler.endCpuSample();
}
///
///
/// CLIENT
///
///
/** /**
* Client version of attachment update functions * Client version of attachment update functions
*/ */
public static void clientUpdateAttachedEntityPositions(){ public static void clientUpdateAttachedEntityPositions(){
Globals.profiler.beginCpuSample("AttachUtils.clientUpdateAttachedEntityPositions"); Globals.profiler.beginCpuSample("AttachUtils.clientUpdateAttachedEntityPositions");
updateBoneAttachments(); clientUpdateBoneAttachments();
updateNonBoneAttachments(); clientUpdateNonBoneAttachments();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }
/** /**
* Updates entities attached to bones * Updates entities attached to bones
*/ */
private static void updateBoneAttachments(){ private static void clientUpdateBoneAttachments(){
Globals.profiler.beginCpuSample("AttachUtils.updateBoneAttachments"); Globals.profiler.beginCpuSample("AttachUtils.clientUpdateBoneAttachments");
//update entities attached to bones of other entities //update entities attached to bones of other entities
for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){ for(Entity currentEntity : Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.BONE_ATTACHED)){
Entity parent; Entity parent;
@ -128,7 +218,10 @@ public class AttachUtils {
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }
private static void updateNonBoneAttachments(){ /**
* Updates entities that aren't attached to a bone directly
*/
private static void clientUpdateNonBoneAttachments(){
Globals.profiler.beginCpuSample("AttachUtils.updateNonBoneAttachments"); Globals.profiler.beginCpuSample("AttachUtils.updateNonBoneAttachments");
Matrix4d parentTransform = new Matrix4d().identity(); Matrix4d parentTransform = new Matrix4d().identity();
Vector3d position = new Vector3d(); Vector3d position = new Vector3d();
@ -334,6 +427,11 @@ public class AttachUtils {
// FUNCTIONS TO DETATCH AN ENTITY // FUNCTIONS TO DETATCH AN ENTITY
// //
/**
* Detatches an entity on the server
* @param parent The parent entity
* @param toAttach The attached entity
*/
public static void serverDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){ public static void serverDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){
ServerEntityTagUtils.removeTagFromEntity(toAttach, EntityTags.BONE_ATTACHED); ServerEntityTagUtils.removeTagFromEntity(toAttach, EntityTags.BONE_ATTACHED);
toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED); toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);
@ -344,6 +442,11 @@ public class AttachUtils {
} }
} }
/**
* Detatches an entity on the client
* @param parent The parent entity
* @param toAttach The attached entity
*/
public static void clientDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){ public static void clientDetatchEntityFromEntityAtBone(Entity parent, Entity toAttach){
Globals.clientSceneWrapper.getScene().removeEntityFromTag(toAttach, EntityTags.BONE_ATTACHED); Globals.clientSceneWrapper.getScene().removeEntityFromTag(toAttach, EntityTags.BONE_ATTACHED);
toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED); toAttach.removeData(EntityDataStrings.ATTACH_ENTITY_IS_ATTACHED);

View File

@ -30,6 +30,7 @@ import electrosphere.entity.state.equip.ClientEquipState;
import electrosphere.entity.state.equip.ServerEquipState; import electrosphere.entity.state.equip.ServerEquipState;
import electrosphere.entity.state.gravity.ClientGravityTree; import electrosphere.entity.state.gravity.ClientGravityTree;
import electrosphere.entity.state.gravity.ServerGravityTree; import electrosphere.entity.state.gravity.ServerGravityTree;
import electrosphere.entity.state.hitbox.HitboxState;
import electrosphere.entity.state.idle.IdleTree; import electrosphere.entity.state.idle.IdleTree;
import electrosphere.entity.state.idle.ServerIdleTree; import electrosphere.entity.state.idle.ServerIdleTree;
import electrosphere.entity.state.inventory.ClientInventoryState; import electrosphere.entity.state.inventory.ClientInventoryState;
@ -103,26 +104,26 @@ public class CreatureUtils {
Actor creatureActor = EntityUtils.getActor(rVal); Actor creatureActor = EntityUtils.getActor(rVal);
EntityUtils.setEntityType(rVal, ENTITY_TYPE_CREATURE); EntityUtils.setEntityType(rVal, ENTITY_TYPE_CREATURE);
EntityUtils.setEntitySubtype(rVal, type); EntityUtils.setEntitySubtype(rVal, type);
for(HitboxData hitboxdata : rawType.getHitboxes()){
List<Entity> hitboxList = new LinkedList<Entity>();
List<Entity> hurtboxList = new LinkedList<Entity>(); ///
if(hitboxdata.getType().equals("hit")){ ///
Entity hitbox = HitboxUtils.clientSpawnRegularHitbox(rVal, hitboxdata.getBone(), hitboxdata.getRadius()); /// HITBOX DATA
Globals.clientHitboxManager.registerHitbox(hitbox); ///
hitboxList.add(hitbox); ///
} else if(hitboxdata.getType().equals("hurt")){ HitboxState.attachHitboxState(Globals.clientSceneWrapper.getHitboxManager(), rVal, rawType.getHitboxes());
Entity hurtbox = HitboxUtils.clientSpawnRegularHurtbox(rVal, hitboxdata.getBone(), hitboxdata.getRadius());
Globals.clientHitboxManager.registerHitbox(hurtbox);
hurtboxList.add(hurtbox); //
} //
rVal.putData(EntityDataStrings.HITBOX_ASSOCIATED_LIST, hitboxList); // PHYSICS
rVal.putData(EntityDataStrings.HURTBOX_ASSOCIATED_LIST, hurtboxList); //
} //
//Physics object
if(rawType.getCollidable() != null){ if(rawType.getCollidable() != null){
CollidableTemplate physicsTemplate = rawType.getCollidable(); CollidableTemplate physicsTemplate = rawType.getCollidable();
PhysicsEntityUtils.clientAttachCollidableTemplate(rVal, physicsTemplate); PhysicsEntityUtils.clientAttachCollidableTemplate(rVal, physicsTemplate);
} }
// //
// //
// MOVEMENT SYSTEMS // MOVEMENT SYSTEMS
@ -390,21 +391,17 @@ public class CreatureUtils {
EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath()); EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath());
PoseActor creatureActor = EntityUtils.getPoseActor(rVal); PoseActor creatureActor = EntityUtils.getPoseActor(rVal);
for(HitboxData hitboxdata : rawType.getHitboxes()){ //
List<Entity> hitboxList = new LinkedList<Entity>(); //
List<Entity> hurtboxList = new LinkedList<Entity>(); // Hitbox stuff
if(hitboxdata.getType().equals("hit")){ //
Entity hitbox = HitboxUtils.serverSpawnRegularHitbox(rVal, hitboxdata.getBone(), hitboxdata.getRadius()); //
realm.getHitboxManager().registerHitbox(hitbox); HitboxState.attachHitboxState(realm.getHitboxManager(), rVal, rawType.getHitboxes());
hitboxList.add(hitbox); //
} else if(hitboxdata.getType().equals("hurt")){ //
Entity hurtbox = HitboxUtils.serverSpawnRegularHurtbox(rVal, hitboxdata.getBone(), hitboxdata.getRadius()); // Physics stuff
realm.getHitboxManager().registerHitbox(hurtbox); //
hurtboxList.add(hurtbox); //
}
rVal.putData(EntityDataStrings.HITBOX_ASSOCIATED_LIST, hitboxList);
rVal.putData(EntityDataStrings.HURTBOX_ASSOCIATED_LIST, hurtboxList);
}
if(rawType.getCollidable() != null){ if(rawType.getCollidable() != null){
CollidableTemplate physicsTemplate = rawType.getCollidable(); CollidableTemplate physicsTemplate = rawType.getCollidable();
PhysicsEntityUtils.serverAttachCollidableTemplate(realm, rVal, physicsTemplate); PhysicsEntityUtils.serverAttachCollidableTemplate(realm, rVal, physicsTemplate);

View File

@ -26,6 +26,7 @@ import electrosphere.entity.state.collidable.ClientCollidableTree;
import electrosphere.entity.state.collidable.ServerCollidableTree; import electrosphere.entity.state.collidable.ServerCollidableTree;
import electrosphere.entity.state.gravity.ClientGravityTree; import electrosphere.entity.state.gravity.ClientGravityTree;
import electrosphere.entity.state.gravity.ServerGravityTree; import electrosphere.entity.state.gravity.ServerGravityTree;
import electrosphere.entity.state.hitbox.HitboxState;
import electrosphere.game.data.collidable.CollidableTemplate; import electrosphere.game.data.collidable.CollidableTemplate;
import electrosphere.game.data.collidable.HitboxData; import electrosphere.game.data.collidable.HitboxData;
import electrosphere.game.data.item.type.EquipWhitelist; import electrosphere.game.data.item.type.EquipWhitelist;
@ -59,13 +60,7 @@ public class ItemUtils {
rVal.putData(EntityDataStrings.ITEM_IS_WEAPON, true); rVal.putData(EntityDataStrings.ITEM_IS_WEAPON, true);
WeaponData weaponData = item.getWeaponData(); WeaponData weaponData = item.getWeaponData();
if(weaponData.getHitboxes() != null){ if(weaponData.getHitboxes() != null){
List<Entity> hitboxList = new LinkedList<Entity>(); HitboxState.attachHitboxState(Globals.clientSceneWrapper.getHitboxManager(), rVal, weaponData.getHitboxes());
for(HitboxData hitboxdata : weaponData.getHitboxes()){
Entity hitbox = HitboxUtils.clientSpawnRegularHitbox(rVal, hitboxdata.getBone(), hitboxdata.getRadius());
Globals.clientHitboxManager.registerHitbox(hitbox);
hitboxList.add(hitbox);
}
rVal.putData(EntityDataStrings.HITBOX_ASSOCIATED_LIST,hitboxList);
} }
rVal.putData(EntityDataStrings.ITEM_WEAPON_CLASS,weaponData.getWeaponClass()); rVal.putData(EntityDataStrings.ITEM_WEAPON_CLASS,weaponData.getWeaponClass());
rVal.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData); rVal.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData);
@ -138,13 +133,7 @@ public class ItemUtils {
rVal.putData(EntityDataStrings.ITEM_IS_WEAPON, true); rVal.putData(EntityDataStrings.ITEM_IS_WEAPON, true);
WeaponData weaponData = item.getWeaponData(); WeaponData weaponData = item.getWeaponData();
if(weaponData.getHitboxes() != null){ if(weaponData.getHitboxes() != null){
List<Entity> hitboxList = new LinkedList<Entity>(); HitboxState.attachHitboxState(realm.getHitboxManager(), rVal, weaponData.getHitboxes());
for(HitboxData hitboxdata : weaponData.getHitboxes()){
Entity hitbox = HitboxUtils.serverSpawnRegularHitbox(rVal, hitboxdata.getBone(), hitboxdata.getRadius());
realm.getHitboxManager().registerHitbox(hitbox);
hitboxList.add(hitbox);
}
rVal.putData(EntityDataStrings.HITBOX_ASSOCIATED_LIST,hitboxList);
} }
rVal.putData(EntityDataStrings.ITEM_WEAPON_CLASS,weaponData.getWeaponClass()); rVal.putData(EntityDataStrings.ITEM_WEAPON_CLASS,weaponData.getWeaponClass());
rVal.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData); rVal.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData);
@ -378,13 +367,7 @@ public class ItemUtils {
//this deregisters from all four & unhooks rigid bodies from the physics runtime //this deregisters from all four & unhooks rigid bodies from the physics runtime
Globals.clientSceneWrapper.getCollisionEngine().destroyEntityThatHasPhysics(item); Globals.clientSceneWrapper.getCollisionEngine().destroyEntityThatHasPhysics(item);
//destroy hitboxes //destroy hitboxes
List<Entity> hitboxes = HitboxUtils.getHitboxAssociatedList(item); HitboxState.destroyHitboxState(item);
if(hitboxes != null){
for(Entity hitbox : hitboxes){
Globals.clientHitboxManager.deregisterHitbox(hitbox);
HitboxUtils.getHitboxData(hitbox).setActive(false);
}
}
//destroy graphics //destroy graphics
EntityUtils.cleanUpEntity(item); EntityUtils.cleanUpEntity(item);
} }
@ -401,13 +384,7 @@ public class ItemUtils {
if(itemRealm != null){ if(itemRealm != null){
itemRealm.getCollisionEngine().destroyEntityThatHasPhysics(item); itemRealm.getCollisionEngine().destroyEntityThatHasPhysics(item);
//destroy hitboxes //destroy hitboxes
List<Entity> hitboxes = HitboxUtils.getHitboxAssociatedList(item); HitboxState.destroyHitboxState(item);
if(hitboxes != null){
for(Entity hitbox : hitboxes){
itemRealm.getHitboxManager().deregisterHitbox(hitbox);
HitboxUtils.getHitboxData(hitbox).setActive(false);
}
}
} }
//destroy graphics //destroy graphics
EntityUtils.cleanUpEntity(item); EntityUtils.cleanUpEntity(item);

View File

@ -16,7 +16,9 @@ import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils; import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils; import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.state.hitbox.HitboxState;
import electrosphere.entity.state.movement.ProjectileTree; import electrosphere.entity.state.movement.ProjectileTree;
import electrosphere.game.data.collidable.HitboxData;
import electrosphere.game.data.projectile.ProjectileType; import electrosphere.game.data.projectile.ProjectileType;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
@ -92,11 +94,15 @@ public class ProjectileUtils {
List<Entity> filter = new LinkedList<Entity>(); List<Entity> filter = new LinkedList<Entity>();
filter.add(parent); filter.add(parent);
//collidable //collidable
HitboxUtils.clientSpawnRegularHitbox(rVal, new HitboxPositionCallback() { HitboxData hitboxData = new HitboxData();
public Vector3d getPosition(){ hitboxData.setRadius(rawType.getHitboxRadius());
return EntityUtils.getPosition(rVal); HitboxState.attachHitboxStateWithCallback(Globals.clientSceneWrapper.getHitboxManager(), Globals.clientSceneWrapper.getCollisionEngine(), rVal, hitboxData,
new HitboxPositionCallback() {
public Vector3d getPosition(){
return EntityUtils.getPosition(rVal);
}
} }
}, rawType.getHitboxRadius(), false, filter); );
return rVal; return rVal;
} }
@ -123,11 +129,15 @@ public class ProjectileUtils {
List<Entity> filter = new LinkedList<Entity>(); List<Entity> filter = new LinkedList<Entity>();
filter.add(parent); filter.add(parent);
//collidable //collidable
HitboxUtils.serverSpawnRegularHitbox(rVal, new HitboxPositionCallback() { HitboxData hitboxData = new HitboxData();
public Vector3d getPosition(){ hitboxData.setRadius(rawType.getHitboxRadius());
return EntityUtils.getPosition(rVal); HitboxState.attachHitboxStateWithCallback(realm.getHitboxManager(), realm.getCollisionEngine(), rVal, hitboxData,
new HitboxPositionCallback() {
public Vector3d getPosition(){
return EntityUtils.getPosition(rVal);
}
} }
}, rawType.getHitboxRadius(), false, filter); );
//position entity //position entity

View File

@ -5,8 +5,7 @@ import electrosphere.logger.LoggerInterface;
import electrosphere.util.FileUtils; import electrosphere.util.FileUtils;
/** /**
* * User-defined settings
* @author amaterasu
*/ */
public class UserSettings { public class UserSettings {
@ -41,7 +40,8 @@ public class UserSettings {
int renderResolutionY; int renderResolutionY;
//debug //debug
//debug visuals //debug visuals
boolean graphicsDebugDrawCollisionSpheres; boolean graphicsDebugDrawCollisionSpheresClient;
boolean graphicsDebugDrawCollisionSpheresServer;
boolean graphicsDebugDrawPhysicsObjects; boolean graphicsDebugDrawPhysicsObjects;
boolean graphicsDebugDrawMovementVectors; boolean graphicsDebugDrawMovementVectors;
boolean graphicsDebugDrawNavmesh; boolean graphicsDebugDrawNavmesh;
@ -82,8 +82,12 @@ public class UserSettings {
return graphicsPerformanceDrawShadows; return graphicsPerformanceDrawShadows;
} }
public boolean graphicsDebugDrawCollisionSpheres() { public boolean getGraphicsDebugDrawCollisionSpheresClient() {
return graphicsDebugDrawCollisionSpheres; return graphicsDebugDrawCollisionSpheresClient;
}
public boolean getGraphicsDebugDrawCollisionSpheresServer() {
return graphicsDebugDrawCollisionSpheresServer;
} }
public boolean graphicsDebugDrawPhysicsObjects() { public boolean graphicsDebugDrawPhysicsObjects() {
@ -131,8 +135,12 @@ public class UserSettings {
} }
public void setGraphicsDebugDrawCollisionSpheres(boolean draw){ public void setGraphicsDebugDrawCollisionSpheresClient(boolean draw){
this.graphicsDebugDrawCollisionSpheres = draw; this.graphicsDebugDrawCollisionSpheresClient = draw;
}
public void setGraphicsDebugDrawCollisionSpheresServer(boolean draw){
this.graphicsDebugDrawCollisionSpheresServer = draw;
} }
public void setGraphicsDebugDrawPhysicsObjects(boolean draw){ public void setGraphicsDebugDrawPhysicsObjects(boolean draw){
@ -178,7 +186,8 @@ public class UserSettings {
rVal.gameplayPhysicsCellRadius = 2; rVal.gameplayPhysicsCellRadius = 2;
//graphics settings //graphics settings
rVal.graphicsDebugDrawCollisionSpheres = false; rVal.graphicsDebugDrawCollisionSpheresClient = false;
rVal.graphicsDebugDrawCollisionSpheresServer = false;
rVal.graphicsDebugDrawMovementVectors = false; rVal.graphicsDebugDrawMovementVectors = false;
rVal.graphicsDebugDrawPhysicsObjects = false; rVal.graphicsDebugDrawPhysicsObjects = false;
rVal.graphicsDebugDrawNavmesh = false; rVal.graphicsDebugDrawNavmesh = false;

View File

@ -4,25 +4,48 @@ import java.util.List;
import electrosphere.game.data.collidable.HitboxData; import electrosphere.game.data.collidable.HitboxData;
/**
* Data about a weapon
*/
public class WeaponData { public class WeaponData {
//the class of weapon (ie sword, bow, etc)
String weaponClass; String weaponClass;
//the hitboxes associated with the weapon
List<HitboxData> hitboxes; List<HitboxData> hitboxes;
//the damage the weapon does
int damage; int damage;
//the model for the projectile
String projectileModel; String projectileModel;
/**
* Gets the weapon class
* @return the weapon class
*/
public String getWeaponClass(){ public String getWeaponClass(){
return weaponClass; return weaponClass;
} }
/**
* Gets the list of hitbox data
* @return the list of hitbox data
*/
public List<HitboxData> getHitboxes(){ public List<HitboxData> getHitboxes(){
return hitboxes; return hitboxes;
} }
/**
* Gets the projectile model
* @return the projectile model
*/
public String getProjectileModel(){ public String getProjectileModel(){
return projectileModel; return projectileModel;
} }
/**
* Gets the damage dealt
* @return the damage dealt
*/
public int getDamage(){ public int getDamage(){
return damage; return damage;
} }

View File

@ -10,6 +10,8 @@ import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.attack.ClientAttackTree;
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot; import electrosphere.renderer.ui.imgui.ImGuiLinePlot;
@ -172,16 +174,35 @@ public class ImGuiWindowMacros {
ImGui.text("Player Entity Details"); ImGui.text("Player Entity Details");
if(Globals.playerEntity != null){ if(Globals.playerEntity != null){
ImGui.text("Position: " + EntityUtils.getPosition(Globals.playerEntity)); ImGui.text("Position: " + EntityUtils.getPosition(Globals.playerEntity));
//server pos
int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId());
Entity serverPlayerEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity);
ImGui.text("Position (Server): " + EntityUtils.getPosition(serverPlayerEntity));
//client-side tree stuff
DBody body = PhysicsEntityUtils.getDBody(Globals.playerEntity); DBody body = PhysicsEntityUtils.getDBody(Globals.playerEntity);
ClientAttackTree attackTree = ClientAttackTree.getClientAttackTree(Globals.playerEntity);
if(body != null){ if(body != null){
ImGui.text("Velocity: " + body.getLinearVel()); ImGui.text("Velocity: " + body.getLinearVel());
ImGui.text("Force: " + body.getForce()); ImGui.text("Force: " + body.getForce());
ImGui.text("Angular Velocity: " + body.getAngularVel()); ImGui.text("Angular Velocity: " + body.getAngularVel());
ImGui.text("Torque: " + body.getTorque()); ImGui.text("Torque: " + body.getTorque());
ImGui.text("Move Vector: " + CreatureUtils.getFacingVector(Globals.playerEntity)); ImGui.text("Move Vector: " + CreatureUtils.getFacingVector(Globals.playerEntity));
Entity serverEntity = EntityLookupUtils.getEntityById(Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId())); if(attackTree != null){
ImGui.text("Move Vector (Server): " + CreatureUtils.getFacingVector(serverEntity)); ImGui.text("Attack Tree State: " + attackTree.getState());
}
} }
//server-side tree stuff
DBody serverBody = PhysicsEntityUtils.getDBody(serverPlayerEntity);
if(body != null){
ImGui.text("Velocity (Server): " + serverBody.getLinearVel());
ImGui.text("Force (Server): " + serverBody.getForce());
ImGui.text("Move Vector (Server): " + CreatureUtils.getFacingVector(serverPlayerEntity));
ImGui.text("Velocity (Server): " + CreatureUtils.getVelocity(serverPlayerEntity));
}
ImGui.text("View dir (Server): " + ServerPlayerViewDirTree.getTree(serverPlayerEntity).getPlayerViewDir());
} }
if(ImGui.button("Toggle Player Camera Lock")){ if(ImGui.button("Toggle Player Camera Lock")){
Globals.cameraHandler.setTrackPlayerEntity(!Globals.cameraHandler.getTrackPlayerEntity()); Globals.cameraHandler.setTrackPlayerEntity(!Globals.cameraHandler.getTrackPlayerEntity());

View File

@ -273,15 +273,27 @@ public class MenuGeneratorsInGame {
return false; return false;
}}); }});
//label (toggle draw collision spheres) //label (toggle draw client collision spheres)
Button toggleCollisionSpheresButton = new Button(); Button toggleClientCollisionSpheresButton = new Button();
Label toggleCollisionSpheresLabel = new Label(fontSize); Label toggleClientCollisionSpheresLabel = new Label(fontSize);
toggleCollisionSpheresLabel.setText("Toggle draw collision spheres"); toggleClientCollisionSpheresLabel.setText("Toggle draw client collision spheres");
toggleCollisionSpheresButton.addChild(toggleCollisionSpheresLabel); toggleClientCollisionSpheresButton.addChild(toggleClientCollisionSpheresLabel);
scrollable.addChild(toggleCollisionSpheresButton); scrollable.addChild(toggleClientCollisionSpheresButton);
toggleCollisionSpheresButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){ toggleClientCollisionSpheresButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
// Main.running = false; // Main.running = false;
Globals.userSettings.setGraphicsDebugDrawCollisionSpheres(!Globals.userSettings.graphicsDebugDrawCollisionSpheres()); Globals.userSettings.setGraphicsDebugDrawCollisionSpheresClient(!Globals.userSettings.getGraphicsDebugDrawCollisionSpheresClient());
return false;
}});
//label (toggle draw server collision spheres)
Button toggleServerCollisionSpheresButton = new Button();
Label toggleServerCollisionSpheresLabel = new Label(fontSize);
toggleServerCollisionSpheresLabel.setText("Toggle draw server collision spheres");
toggleServerCollisionSpheresButton.addChild(toggleServerCollisionSpheresLabel);
scrollable.addChild(toggleServerCollisionSpheresButton);
toggleServerCollisionSpheresButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
// Main.running = false;
Globals.userSettings.setGraphicsDebugDrawCollisionSpheresServer(!Globals.userSettings.getGraphicsDebugDrawCollisionSpheresServer());
return false; return false;
}}); }});

View File

@ -143,6 +143,7 @@ public class EntityProtocol {
// TODO // TODO
// //
// //
case UPDATEENTITYVIEWDIR:
case KILL: case KILL:
case SETPOSITION: case SETPOSITION:
case SETFACING: case SETFACING:

View File

@ -38,7 +38,7 @@ public class InventoryProtocol {
String equipPointName = message.getequipPointId(); String equipPointName = message.getequipPointId();
EquipPoint equipPoint = equipState.getEquipPoint(equipPointName); EquipPoint equipPoint = equipState.getEquipPoint(equipPointName);
//attach //attach
equipState.clientAttemptEquip(inWorldEntity, equipPoint); equipState.attemptEquip(inWorldEntity, equipPoint);
} }
} }
break; break;

View File

@ -9,10 +9,13 @@ public class SynchronizationProtocol {
Globals.profiler.beginCpuSample("SynchronizationProtocol.handleSynchronizationMessage"); Globals.profiler.beginCpuSample("SynchronizationProtocol.handleSynchronizationMessage");
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case UPDATECLIENTSTATE: case UPDATECLIENTSTATE:
case UPDATECLIENTSTRINGSTATE:
case ATTACHTREE: case ATTACHTREE:
case DETATCHTREE: case DETATCHTREE:
Globals.clientSynchronizationManager.pushMessage(message); Globals.clientSynchronizationManager.pushMessage(message);
break; break;
default:
throw new UnsupportedOperationException("Received synchronization message on the client of unsupported type: " + message.getMessageSubtype());
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }

View File

@ -28,6 +28,7 @@ public class EntityMessage extends NetworkMessage {
SETBTREEPROPERTYENUM, SETBTREEPROPERTYENUM,
ATTACHENTITYTOENTITY, ATTACHENTITYTOENTITY,
SPAWNFOLIAGESEED, SPAWNFOLIAGESEED,
UPDATEENTITYVIEWDIR,
} }
EntityMessageType messageType; EntityMessageType messageType;
@ -386,6 +387,12 @@ public class EntityMessage extends NetworkMessage {
return EntityMessage.canParseattachEntityToEntityMessage(byteBuffer); return EntityMessage.canParseattachEntityToEntityMessage(byteBuffer);
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED: case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED:
return EntityMessage.canParseSpawnFoliageSeedMessage(byteBuffer); return EntityMessage.canParseSpawnFoliageSeedMessage(byteBuffer);
case TypeBytes.ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR:
if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR_SIZE){
return true;
} else {
return false;
}
} }
return false; return false;
} }
@ -1010,6 +1017,28 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parseupdateEntityViewDirMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.UPDATEENTITYVIEWDIR);
stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal;
}
public static EntityMessage constructupdateEntityViewDirMessage(int entityID,long time,double positionX,double positionY,double positionZ){
EntityMessage rVal = new EntityMessage(EntityMessageType.UPDATEENTITYVIEWDIR);
rVal.setentityID(entityID);
rVal.settime(time);
rVal.setpositionX(positionX);
rVal.setpositionY(positionY);
rVal.setpositionZ(positionZ);
rVal.serialize();
return rVal;
}
@Override @Override
void serialize(){ void serialize(){
byte[] intValues = new byte[8]; byte[] intValues = new byte[8];
@ -1566,6 +1595,33 @@ public class EntityMessage extends NetworkMessage {
rawBytes[34+creatureTemplate.length()+i] = intValues[i]; rawBytes[34+creatureTemplate.length()+i] = intValues[i];
} }
break; break;
case UPDATEENTITYVIEWDIR:
rawBytes = new byte[2+4+8+8+8+8];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
//entity messaage header
rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR;
intValues = ByteStreamUtils.serializeIntToBytes(entityID);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(time);
for(int i = 0; i < 8; i++){
rawBytes[6+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
for(int i = 0; i < 8; i++){
rawBytes[14+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
for(int i = 0; i < 8; i++){
rawBytes[22+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
for(int i = 0; i < 8; i++){
rawBytes[30+i] = intValues[i];
}
break;
} }
serialized = true; serialized = true;
} }

View File

@ -141,6 +141,11 @@ SYNCHRONIZATION_MESSAGE,
rVal = EntityMessage.parseSpawnFoliageSeedMessage(byteBuffer); rVal = EntityMessage.parseSpawnFoliageSeedMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR:
if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseupdateEntityViewDirMessage(byteBuffer);
}
break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_LORE: case TypeBytes.MESSAGE_TYPE_LORE:

View File

@ -37,6 +37,7 @@ Message categories
public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM = 17; public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM = 17;
public static final byte ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY = 18; public static final byte ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY = 18;
public static final byte ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED = 19; public static final byte ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED = 19;
public static final byte ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR = 20;
/* /*
Entity packet sizes Entity packet sizes
*/ */
@ -54,6 +55,7 @@ Message categories
public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYFLOAT_SIZE = 26; public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYFLOAT_SIZE = 26;
public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYDOUBLE_SIZE = 30; public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYDOUBLE_SIZE = 30;
public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM_SIZE = 26; public static final byte ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM_SIZE = 26;
public static final byte ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR_SIZE = 38;
/* /*
Lore subcategories Lore subcategories
*/ */

View File

@ -1,24 +1,12 @@
package electrosphere.net.server.protocol; package electrosphere.net.server.protocol;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector3i;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.state.ironsight.IronSightTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.entity.types.creature.CreatureTemplate; import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.net.parser.net.message.CharacterMessage; import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.parser.net.message.PlayerMessage; import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.server.player.Player; import electrosphere.server.character.PlayerCharacterCreation;
import electrosphere.server.datacell.Realm;
import electrosphere.util.Utilities; import electrosphere.util.Utilities;
public class CharacterProtocol { public class CharacterProtocol {
@ -49,38 +37,12 @@ public class CharacterProtocol {
} }
} }
static void spawnPlayerCharacter(ServerConnectionHandler connectionHandler){ /**
Player playerObject = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId()); * Spawns the player's entity
//get template * @param connectionHandler The connection handler for the player
CreatureTemplate template = connectionHandler.getCurrentCreatureTemplate(); */
String raceName = template.getCreatureType();
//spawn player in world
Realm realm = Globals.realmManager.getRealms().iterator().next();
Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,new Vector3d(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z),raceName,template);
int playerCharacterId = newPlayerEntity.getId();
connectionHandler.setPlayerCharacterId(playerCharacterId);
CreatureUtils.setControllerPlayerId(newPlayerEntity, connectionHandler.getPlayerId());
//attach player object to player character
playerObject.setPlayerEntity(newPlayerEntity);
playerObject.setWorldPos(new Vector3i(
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.x),
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.y),
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z)
));
// System.out.println(EntityUtils.getRotation(newPlayerCharacter).set(0,1,0,1).normalize());
realm.getDataCellManager().addPlayerToRealm(playerObject);
// IronSightTree.attachIronSightTree(newPlayerEntity);
// //spawn player sword
// Entity sword = ItemUtils.spawnBasicItem("Katana");
// AttachUtils.attachEntityToEntityAtBone(newPlayerCharacter, sword, "Bone.031");
//set controller id
if(playerObject == Globals.clientPlayer){
Globals.playerEntity = newPlayerEntity;
}
}
static void spawnClientEntity(ServerConnectionHandler connectionHandler){ static void spawnClientEntity(ServerConnectionHandler connectionHandler){
spawnPlayerCharacter(connectionHandler); PlayerCharacterCreation.spawnPlayerCharacter(connectionHandler);
//set client initial discrete position //set client initial discrete position
connectionHandler.addMessagetoOutgoingQueue( connectionHandler.addMessagetoOutgoingQueue(
PlayerMessage.constructSetInitialDiscretePositionMessage( PlayerMessage.constructSetInitialDiscretePositionMessage(
@ -93,8 +55,6 @@ public class CharacterProtocol {
connectionHandler.addMessagetoOutgoingQueue( connectionHandler.addMessagetoOutgoingQueue(
TerrainMessage.constructSpawnPositionMessage(Globals.spawnPoint.x, Globals.spawnPoint.y, Globals.spawnPoint.z) TerrainMessage.constructSpawnPositionMessage(Globals.spawnPoint.x, Globals.spawnPoint.y, Globals.spawnPoint.z)
); );
//tell them what player stats they are
// connectionHandler.addMessagetoOutgoingQueue(PlayerMessage.constructSet_IDMessage(connectionHandler.getPlayerCharacterId()));
} }
} }

View File

@ -1,15 +1,11 @@
package electrosphere.net.server.protocol; package electrosphere.net.server.protocol;
import electrosphere.engine.Globals; import org.joml.Vector3d;
import electrosphere.engine.Main;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.attack.ServerAttackTree; import electrosphere.entity.state.attack.ServerAttackTree;
import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.state.server.ServerPlayerViewDirTree;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.NetUtils;
import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
@ -45,6 +41,12 @@ public class EntityProtocol {
ServerAttackTree.getServerAttackTree(targetEntity).addNetworkMessage(message); ServerAttackTree.getServerAttackTree(targetEntity).addNetworkMessage(message);
} }
} break; } break;
case UPDATEENTITYVIEWDIR: {
targetEntity = EntityLookupUtils.getEntityById(message.getentityID());
if(targetEntity != null && ServerPlayerViewDirTree.hasTree(targetEntity)){
ServerPlayerViewDirTree.getTree(targetEntity).setPlayerViewDir(new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ()),message.gettime());
}
} break;
//ignore stack //ignore stack
case KILL: case KILL:
case SPAWNCREATURE: case SPAWNCREATURE:
@ -54,6 +56,13 @@ public class EntityProtocol {
case SETFACING: case SETFACING:
case SETPOSITION: case SETPOSITION:
case SETPROPERTY: case SETPROPERTY:
case SETBTREEPROPERTYDOUBLE:
case SETBTREEPROPERTYENUM:
case SETBTREEPROPERTYFLOAT:
case SETBTREEPROPERTYINT:
case SETBTREEPROPERTYSTRING:
case SPAWNFOLIAGESEED:
case SPAWNITEM:
//silently ignore //silently ignore
break; break;
} }

View File

@ -92,7 +92,15 @@ public class Actor {
return -1.0f; return -1.0f;
} }
/**
* Checks if an animation is being played on any meshes
* @param animationName The animation name
* @return true if the animation is being played on any meshes, false if the provided animation name is null or the animation is not being played on any meshes
*/
public boolean isPlayingAnimation(String animationName){ public boolean isPlayingAnimation(String animationName){
if(animationName == null){
return false;
}
for(ActorAnimationMask mask : animationQueue){ for(ActorAnimationMask mask : animationQueue){
if(mask.getAnimationName().contains(animationName)){ if(mask.getAnimationName().contains(animationName)){
return true; return true;
@ -255,6 +263,12 @@ public class Actor {
return modelPath; return modelPath;
} }
/**
* Gets the position of a bone
* @param boneName The name of the bone
* @return The vector3f containing the position of the bone, or a vector of (0,0,0) if the model lookup fails
* //TODO: refactor to make failure more transparent (both for model not existing and bone not existing)
*/
public Vector3f getBonePosition(String boneName){ public Vector3f getBonePosition(String boneName){
Vector3f rVal = new Vector3f(); Vector3f rVal = new Vector3f();
Model model = Globals.assetManager.fetchModel(modelPath); Model model = Globals.assetManager.fetchModel(modelPath);

View File

@ -5,12 +5,15 @@ import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
/** /**
* * Utils for dealing with actors
* @author amaterasu
*/ */
public class ActorUtils { public class ActorUtils {
/**
* Creates an actor object and queues the model path
* @param modelPath The model path
* @return The actor object
*/
public static Actor createActorFromModelPath(String modelPath){ public static Actor createActorFromModelPath(String modelPath){
Actor rVal = new Actor(modelPath); Actor rVal = new Actor(modelPath);
Globals.assetManager.addModelPathToQueue(modelPath); Globals.assetManager.addModelPathToQueue(modelPath);
@ -24,7 +27,7 @@ public class ActorUtils {
@Deprecated @Deprecated
public static void applyBlenderTransformer(Entity actorEntity){ public static void applyBlenderTransformer(Entity actorEntity){
Actor entityActor = EntityUtils.getActor(actorEntity); // Actor entityActor = EntityUtils.getActor(actorEntity);
// entityActor.setAnimationScalar(60f); //should be the value of the fps i think // entityActor.setAnimationScalar(60f); //should be the value of the fps i think
} }

View File

@ -6,20 +6,24 @@ import org.joml.Quaternionf;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.lwjgl.opengl.GL40; import org.lwjgl.opengl.GL40;
import org.ode4j.ode.DGeom;
import org.ode4j.ode.DSphere;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.hitbox.HitboxUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.hitbox.HitboxState;
import electrosphere.entity.types.camera.CameraEntityUtils; import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.game.data.collidable.CollidableTemplate; import electrosphere.game.data.collidable.CollidableTemplate;
import electrosphere.game.data.collidable.HitboxData;
import electrosphere.renderer.OpenGLState; import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.model.Model; import electrosphere.renderer.model.Model;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.pathfinding.navmesh.NavCube; import electrosphere.server.pathfinding.navmesh.NavCube;
import electrosphere.server.pathfinding.navmesh.NavMesh; import electrosphere.server.pathfinding.navmesh.NavMesh;
import electrosphere.server.pathfinding.navmesh.NavShape; import electrosphere.server.pathfinding.navmesh.NavShape;
@ -56,44 +60,89 @@ public class DebugContentPipeline implements RenderPipeline {
Matrix4d modelTransformMatrix = new Matrix4d(); Matrix4d modelTransformMatrix = new Matrix4d();
if(Globals.userSettings.graphicsDebugDrawCollisionSpheres()){ if(Globals.userSettings.getGraphicsDebugDrawCollisionSpheresClient()){
for(Entity currentHitbox : Globals.clientHitboxManager.getAllHitboxes()){ Model hitboxModel;
if((boolean)currentHitbox.getData(EntityDataStrings.DATA_STRING_DRAW)){ for(HitboxState hitboxState : Globals.clientSceneWrapper.getHitboxManager().getAllHitboxes()){
Model hitboxModel; for(String boneName : hitboxState.getBones()){
HitboxData data = HitboxUtils.getHitboxData(currentHitbox); DGeom geom = hitboxState.getGeometry(boneName);
if(data.isActive()){ if(geom instanceof DSphere){
if(data.getType().equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){ DSphere sphereView = (DSphere)geom;
if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere.fbx")) != null){ if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere.glb")) != null){
Vector3d position = EntityUtils.getPosition(currentHitbox); Vector3d position = PhysicsUtils.odeVecToJomlVec(sphereView.getPosition());
//calculate camera-modified vector3f //calculate camera-modified vector3f
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition);
// modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
modelTransformMatrix.scale(data.getRadius() * 2);
hitboxModel.setModelMatrix(modelTransformMatrix);
hitboxModel.draw(renderPipelineState,openGLState);
}
} else if(data.getType().equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){
if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere_1.fbx")) != null){
Vector3d position = EntityUtils.getPosition(currentHitbox);
//calculate camera-modified vector3f
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition);
// modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
modelTransformMatrix.scale(data.getRadius() * 2);
hitboxModel.setModelMatrix(modelTransformMatrix);
hitboxModel.draw(renderPipelineState,openGLState);
}
}
} else {
if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere_grey.fbx")) != null){
Vector3d position = EntityUtils.getPosition(currentHitbox);
modelTransformMatrix.identity(); modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera))); modelTransformMatrix.translate(cameraModifiedPosition);
// modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere // modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
modelTransformMatrix.scale(data.getRadius() * 2); modelTransformMatrix.scale(sphereView.getRadius() * 2);
hitboxModel.setModelMatrix(modelTransformMatrix);
hitboxModel.draw(renderPipelineState,openGLState);
}
}
}
}
// for(Entity currentHitbox : Globals.clientHitboxManager.getAllHitboxes()){
// if((boolean)currentHitbox.getData(EntityDataStrings.DATA_STRING_DRAW)){
// Model hitboxModel;
// HitboxData data = HitboxUtils.getHitboxData(currentHitbox);
// if(data.isActive()){
// if(data.getType().equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){
// if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere.fbx")) != null){
// Vector3d position = EntityUtils.getPosition(currentHitbox);
// //calculate camera-modified vector3f
// Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
// modelTransformMatrix.identity();
// modelTransformMatrix.translate(cameraModifiedPosition);
// // modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
// modelTransformMatrix.scale(data.getRadius() * 2);
// hitboxModel.setModelMatrix(modelTransformMatrix);
// hitboxModel.draw(renderPipelineState,openGLState);
// }
// } else if(data.getType().equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){
// if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere_1.fbx")) != null){
// Vector3d position = EntityUtils.getPosition(currentHitbox);
// //calculate camera-modified vector3f
// Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
// modelTransformMatrix.identity();
// modelTransformMatrix.translate(cameraModifiedPosition);
// // modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
// modelTransformMatrix.scale(data.getRadius() * 2);
// hitboxModel.setModelMatrix(modelTransformMatrix);
// hitboxModel.draw(renderPipelineState,openGLState);
// }
// }
// } else {
// if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere_grey.fbx")) != null){
// Vector3d position = EntityUtils.getPosition(currentHitbox);
// modelTransformMatrix.identity();
// modelTransformMatrix.translate(new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)));
// // modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
// modelTransformMatrix.scale(data.getRadius() * 2);
// hitboxModel.setModelMatrix(modelTransformMatrix);
// hitboxModel.draw(renderPipelineState,openGLState);
// }
// }
// }
// }
}
if(Globals.userSettings.getGraphicsDebugDrawCollisionSpheresServer()){
Model hitboxModel;
int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId());
Entity serverPlayerEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity);
Realm playerRealm = Globals.realmManager.getEntityRealm(serverPlayerEntity);
for(HitboxState hitboxState : playerRealm.getHitboxManager().getAllHitboxes()){
for(String boneName : hitboxState.getBones()){
DGeom geom = hitboxState.getGeometry(boneName);
if(geom instanceof DSphere){
DSphere sphereView = (DSphere)geom;
if((hitboxModel = Globals.assetManager.fetchModel("Models/basic/geometry/unitsphere.glb")) != null){
Vector3d position = PhysicsUtils.odeVecToJomlVec(sphereView.getPosition());
//calculate camera-modified vector3f
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition);
// modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
modelTransformMatrix.scale(sphereView.getRadius() * 2);
hitboxModel.setModelMatrix(modelTransformMatrix); hitboxModel.setModelMatrix(modelTransformMatrix);
hitboxModel.draw(renderPipelineState,openGLState); hitboxModel.draw(renderPipelineState,openGLState);
} }

View File

@ -43,7 +43,9 @@ public class FirstPersonItemsPipeline implements RenderPipeline {
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) { public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
//update logic //update logic
updateFirstPersonModelPosition(Globals.firstPersonEntity); if(Globals.firstPersonEntity != null){
updateFirstPersonModelPosition(Globals.firstPersonEntity);
}
//setup opengl state //setup opengl state
this.firstPersonFramebuffer.bind(); this.firstPersonFramebuffer.bind();

View File

@ -0,0 +1,59 @@
package electrosphere.server.character;
import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.state.server.ServerPlayerViewDirTree;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.Realm;
/**
* Deals with spawning player characters
*/
public class PlayerCharacterCreation {
/**
* Spawns the player's character
* @param connectionHandler The connection handler of the player
*/
public static void spawnPlayerCharacter(ServerConnectionHandler connectionHandler){
Player playerObject = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
//get template
CreatureTemplate template = connectionHandler.getCurrentCreatureTemplate();
String raceName = template.getCreatureType();
//spawn entity in world
Realm realm = Globals.realmManager.getRealms().iterator().next();
Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,new Vector3d(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z),raceName,template);
int playerCharacterId = newPlayerEntity.getId();
connectionHandler.setPlayerCharacterId(playerCharacterId);
CreatureUtils.setControllerPlayerId(newPlayerEntity, connectionHandler.getPlayerId());
//custom player btrees
addPlayerServerBTrees(newPlayerEntity);
//attach player object to player character
playerObject.setPlayerEntity(newPlayerEntity);
playerObject.setWorldPos(new Vector3i(
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.x),
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.y),
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z)
));
realm.getDataCellManager().addPlayerToRealm(playerObject);
//set controller id
if(playerObject == Globals.clientPlayer){
Globals.playerEntity = newPlayerEntity;
}
}
/**
* Adds behavior trees that are unique to players a given entity
* @param entity The entity to add to
*/
static void addPlayerServerBTrees(Entity entity){
ServerPlayerViewDirTree.attachServerPlayerViewDirTree(entity);
}
}

View File

@ -154,15 +154,22 @@ public class Realm {
* Tells the data cell manager to simulate all loaded cells * Tells the data cell manager to simulate all loaded cells
*/ */
protected void simulate(){ protected void simulate(){
//
//simulate bullet physics engine step //simulate bullet physics engine step
collisionEngine.simulatePhysics((float)Globals.timekeeper.getSimFrameTime()); collisionEngine.simulatePhysics((float)Globals.timekeeper.getSimFrameTime());
collisionEngine.updateDynamicObjectTransforms(); collisionEngine.updateDynamicObjectTransforms();
//
//hitbox sim
hitboxManager.simulate();
//
//main simulation //main simulation
dataCellManager.simulate(); dataCellManager.simulate();
//
//data cell manager update misc variables (player positions, unload not-in-use cells) //data cell manager update misc variables (player positions, unload not-in-use cells)
if(dataCellManager != null){ if(dataCellManager != null){
dataCellManager.unloadPlayerlessChunks(); dataCellManager.unloadPlayerlessChunks();
} }
//
//clear collidable impulse lists //clear collidable impulse lists
collisionEngine.clearCollidableImpulseLists(); collisionEngine.clearCollidableImpulseLists();
} }

View File

@ -12,6 +12,7 @@ import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.game.server.world.ServerWorldData; import electrosphere.game.server.world.ServerWorldData;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.physics.ServerHitboxResolutionCallback;
/** /**
* Manages all realms for the engine. Should be a singleton * Manages all realms for the engine. Should be a singleton
@ -39,7 +40,7 @@ public class RealmManager {
* @return The realm * @return The realm
*/ */
public Realm createRealm(){ public Realm createRealm(){
return new Realm(new CollisionEngine(), new HitboxManager()); return new Realm(new CollisionEngine(), new HitboxManager(new ServerHitboxResolutionCallback()));
} }
/** /**
@ -51,7 +52,7 @@ public class RealmManager {
CollisionEngine collisionEngine = new CollisionEngine(); CollisionEngine collisionEngine = new CollisionEngine();
collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
//create realm //create realm
Realm realm = new Realm(collisionEngine, new HitboxManager()); Realm realm = new Realm(collisionEngine, new HitboxManager(new ServerHitboxResolutionCallback()));
//create function classes //create function classes
GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm,Globals.serverTerrainManager,Globals.serverFluidManager,Globals.serverContentManager); GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm,Globals.serverTerrainManager,Globals.serverFluidManager,Globals.serverContentManager);
EntityDataCellMapper entityDataCellMapper = new EntityDataCellMapper(); EntityDataCellMapper entityDataCellMapper = new EntityDataCellMapper();

View File

@ -0,0 +1,88 @@
package electrosphere.server.datacell.physics;
import org.joml.Vector3d;
import org.ode4j.ode.DContactGeom;
import org.ode4j.ode.DGeom;
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.hitbox.HitboxState;
import electrosphere.entity.state.hitbox.HitboxState.HitboxShapeStatus;
import electrosphere.entity.state.hitbox.HitboxState.HitboxType;
import electrosphere.entity.state.life.LifeUtils;
import electrosphere.entity.state.movement.ProjectileTree;
import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.DataCellSearchUtils;
/**
* Callback for managing collisions on the server
*/
public class ServerHitboxResolutionCallback implements CollisionResolutionCallback {
@Override
public void resolve(DContactGeom contactGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) {
Entity impactorParent = impactor.getParent();
Entity receiverParent = receiver.getParent();
HitboxState impactorState = HitboxState.getHitboxState(impactorParent);
HitboxState receiverState = HitboxState.getHitboxState(receiverParent);
DGeom impactorGeom = contactGeom.g1;
DGeom receiverGeom = contactGeom.g2;
HitboxShapeStatus impactorShapeStatus = impactorState.getShapeStatus(impactorGeom);
HitboxShapeStatus receiverShapeStatus = receiverState.getShapeStatus(receiverGeom);
Realm receiverRealm = Globals.realmManager.getEntityRealm(receiverParent);
//currently, impactor needs to be an item, and the receiver must not be an item
boolean isDamageEvent =
impactorShapeStatus != null &&
receiverShapeStatus != null &&
impactorShapeStatus.isActive() &&
receiverShapeStatus.isActive() &&
impactorShapeStatus.getType() == HitboxType.HIT &&
receiverShapeStatus.getType() == HitboxType.HURT &&
AttachUtils.getParent(impactorParent) != receiverParent
;
if(isDamageEvent){
//if the entity is attached to is an item, we need to compare with the parent of the item
//to make sure you don't stab yourself for instance
boolean isItem = ItemUtils.isItem(impactorParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM);
Entity hitboxAttachParent = AttachUtils.getParent(impactorParent);
if(isItem){
if(hitboxAttachParent != receiverParent){
int damage = ItemUtils.getWeaponDataRaw(impactorParent).getDamage();
LifeUtils.getLifeState(receiverParent).damage(damage);
if(!LifeUtils.getLifeState(receiverParent).isIsAlive()){
EntityUtils.getPosition(receiverParent).set(Globals.spawnPoint);
LifeUtils.getLifeState(receiverParent).revive();
}
}
} else {
int damage = 0;
//for entities using attacktree
if(CreatureUtils.serverGetAttackTree(impactorParent) != null){
damage = ItemUtils.getWeaponDataRaw(impactorParent).getDamage();
} else {
//for entities using shooter tree
if(ProjectileTree.getProjectileTree(impactorParent) != null){
damage = (int)ProjectileTree.getProjectileTree(impactorParent).getDamage();
}
}
LifeUtils.getLifeState(receiverParent).damage(damage);
if(!LifeUtils.getLifeState(receiverParent).isIsAlive()){
EntityUtils.getPosition(receiverParent).set(Globals.spawnPoint);
LifeUtils.getLifeState(receiverParent).revive();
}
}
}
}
}

View File

@ -12,13 +12,11 @@ import org.joml.Matrix4f;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector4d; import org.joml.Vector4d;
import org.joml.Vector4f;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.renderer.actor.ActorAnimationMask; import electrosphere.renderer.actor.ActorAnimationMask;
import electrosphere.renderer.actor.ActorBoneRotator; import electrosphere.renderer.actor.ActorBoneRotator;
import electrosphere.renderer.actor.ActorStaticMorph; import electrosphere.renderer.actor.ActorStaticMorph;
import electrosphere.renderer.actor.ActorStaticMorph.StaticMorphTransforms;
import electrosphere.renderer.model.Bone; import electrosphere.renderer.model.Bone;
/** /**

View File

@ -1,10 +1,21 @@
package electrosphere.server.poseactor; package electrosphere.server.poseactor;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
public class PoseActorUtils { public class PoseActorUtils {
/**
* Creates a pose actor object and queues the model path
* @param modelPath The model path
* @return The PoseActor object
*/
public static PoseActor createPoseActorFromModelPath(String modelPath){
PoseActor rVal = new PoseActor(modelPath);
Globals.assetManager.addPoseModelPathToQueue(modelPath);
return rVal;
}
public static void applyBlenderTransformer(Entity actorEntity){ public static void applyBlenderTransformer(Entity actorEntity){
PoseActor entityActor = EntityUtils.getPoseActor(actorEntity); PoseActor entityActor = EntityUtils.getPoseActor(actorEntity);

View File

@ -1,41 +1,20 @@
package electrosphere.server.simulation; package electrosphere.server.simulation;
import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.client.targeting.crosshair.Crosshair;
import electrosphere.collision.hitbox.HitboxManager; import electrosphere.collision.hitbox.HitboxManager;
import electrosphere.collision.hitbox.HitboxUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main; import electrosphere.engine.Main;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags; import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.scene.EntityDescriptor;
import electrosphere.entity.state.ParticleTree;
import electrosphere.entity.state.attack.ClientAttackTree;
import electrosphere.entity.state.collidable.ClientCollidableTree;
import electrosphere.entity.state.collidable.ServerCollidableTree; import electrosphere.entity.state.collidable.ServerCollidableTree;
import electrosphere.entity.state.idle.IdleTree;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils; import electrosphere.entity.types.item.ItemUtils;
import electrosphere.entity.state.life.LifeState;
import electrosphere.entity.state.life.LifeUtils;
import electrosphere.entity.state.movement.SprintTree;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
import electrosphere.entity.types.particle.ParticleUtils; import electrosphere.entity.types.particle.ParticleUtils;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.server.datacell.ServerDataCell; import electrosphere.server.datacell.ServerDataCell;
import java.sql.Time;
import org.joml.Vector3d;
import org.joml.Vector3f;
/** /**
* * Server-side micro-scale simulation
* @author amaterasu
*/ */
public class MicroSimulation { public class MicroSimulation {
@ -79,16 +58,9 @@ public class MicroSimulation {
} }
//update attached entity positions //update attached entity positions
AttachUtils.serverUpdateAttachedEntityPositions(dataCell); AttachUtils.serverUpdateAttachedEntityPositions(dataCell);
//update hitbox positions //
for(Entity currentHitbox : hitboxManager.getAllHitboxes()){ //hitbox updates
HitboxUtils.serverUpdatePosition(currentHitbox); hitboxManager.simulate();
}
//collide hitboxes
for(Entity currentHitbox : hitboxManager.getAllHitboxes()){
if(isReady){
HitboxUtils.serverCollideEntities(currentHitbox);
}
}
//simulate behavior trees //simulate behavior trees
dataCell.getScene().simulateBehaviorTrees((float)Globals.timekeeper.getSimFrameTime()); dataCell.getScene().simulateBehaviorTrees((float)Globals.timekeeper.getSimFrameTime());
//sum collidable impulses //sum collidable impulses