diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index e8f70895..fb9fad47 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -2100,6 +2100,7 @@ Actually fix pathing spinlock Support for observing ai entities ServerGroundMovementTree supports collidable entities ServerGroundMovementTree geom work +ServerLODComponent replaces bodies with geometries instead of just destroying the geometries diff --git a/src/main/java/electrosphere/client/ClientState.java b/src/main/java/electrosphere/client/ClientState.java index b1bb29a6..1d5b9d7f 100644 --- a/src/main/java/electrosphere/client/ClientState.java +++ b/src/main/java/electrosphere/client/ClientState.java @@ -189,7 +189,7 @@ public class ClientState { * Constructor */ public ClientState(){ - this.clientSceneWrapper = new ClientSceneWrapper(this.clientScene, new CollisionEngine(), CollisionEngine.create(new ClientChemistryCollisionCallback()), new CollisionEngine()); + this.clientSceneWrapper = new ClientSceneWrapper(this.clientScene, new CollisionEngine("clientPhysics"), CollisionEngine.create("clientChem", new ClientChemistryCollisionCallback()), new CollisionEngine("clientInteraction")); this.clientTemporalService = (ClientTemporalService)Globals.engineState.serviceManager.registerService(new ClientTemporalService()); } diff --git a/src/main/java/electrosphere/client/interact/ClientInteractionEngine.java b/src/main/java/electrosphere/client/interact/ClientInteractionEngine.java index a97ac295..6d5b3a7c 100644 --- a/src/main/java/electrosphere/client/interact/ClientInteractionEngine.java +++ b/src/main/java/electrosphere/client/interact/ClientInteractionEngine.java @@ -7,13 +7,9 @@ import java.util.concurrent.locks.ReentrantLock; import org.joml.Matrix4d; import org.joml.Quaterniond; import org.joml.Vector3d; -import org.joml.Vector3i; import org.ode4j.ode.DBody; -import electrosphere.client.block.BlockChunkData; import electrosphere.client.entity.camera.CameraEntityUtils; -import electrosphere.client.scene.ClientWorldData; -import electrosphere.client.terrain.cache.ChunkData; import electrosphere.client.ui.menu.ingame.InteractionTargetMenu; import electrosphere.collision.CollisionBodyCreation; import electrosphere.collision.CollisionEngine; @@ -24,9 +20,7 @@ import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; -import electrosphere.entity.types.EntityTypes.EntityType; import electrosphere.entity.types.common.CommonEntityUtils; -import electrosphere.server.physics.terrain.manager.ServerTerrainChunk; /** * Manages the interaction state @@ -90,7 +84,7 @@ public class ClientInteractionEngine { rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody); - Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable); + Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal)); } break; case CollidableTemplate.COLLIDABLE_TYPE_CUBE: { // @@ -125,7 +119,7 @@ public class ClientInteractionEngine { rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody); - Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable); + Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal)); } break; case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: { // @@ -161,7 +155,7 @@ public class ClientInteractionEngine { rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody); - Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable); + Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal)); } break; default: { throw new Error("Unsupported shape type! " + physicsTemplate.getType()); diff --git a/src/main/java/electrosphere/collision/CollisionEngine.java b/src/main/java/electrosphere/collision/CollisionEngine.java index 6c500d2e..f382af42 100644 --- a/src/main/java/electrosphere/collision/CollisionEngine.java +++ b/src/main/java/electrosphere/collision/CollisionEngine.java @@ -1,6 +1,7 @@ package electrosphere.collision; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -10,7 +11,6 @@ import java.util.concurrent.locks.ReentrantLock; import org.joml.Matrix4d; import org.joml.Quaterniond; import org.joml.Vector3d; -import org.joml.Vector4d; import org.ode4j.math.DVector3; import org.ode4j.ode.DBhvSpace; import org.ode4j.ode.DBody; @@ -100,6 +100,11 @@ public class CollisionEngine { * Distance from current floating point origin to trigger a rebase */ private static final double REBASE_TRIGGER_DISTANCE = 16; + + /** + * Maximum expected distance from local origin + */ + private static final double MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN = 3000; /** * world data that the collision engine leverages for position correction and the like @@ -188,16 +193,27 @@ public class CollisionEngine { */ private int geomCount = 0; + /** + * Tracks whether the engine has rebased or not + */ + private boolean hasRebased = false; + /** * buffer for storing potential collisions */ private DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS); + + /** + * The name of the collision engine + */ + private final String name; /** * Constructor */ - public CollisionEngine(){ + public CollisionEngine(String name){ + this.name = name; world = OdeHelper.createWorld(); world.setGravity(0,-GRAVITY_MAGNITUDE,0); world.setQuickStepNumIterations(QUICKSTEP_ITERATION_COUNT); @@ -221,8 +237,8 @@ public class CollisionEngine { /** * Creates a collision engine with a specified callback */ - public static CollisionEngine create(CollisionResolutionCallback callback){ - CollisionEngine rVal = new CollisionEngine(); + public static CollisionEngine create(String name, CollisionResolutionCallback callback){ + CollisionEngine rVal = new CollisionEngine(name); rVal.setCollisionResolutionCallback(callback); return rVal; } @@ -243,13 +259,6 @@ public class CollisionEngine { case Collidable.TYPE_CREATURE: switch(impactor.getType()){ case Collidable.TYPE_STATIC: - // System.out.println(EntityUtils.getPosition(impactor.getParent()) + " " + EntityUtils.getPosition(receiver.getParent())); -// System.out.println(); - // System.out.println("Terrain-creature collision: " + normal + " mag:" + magnitude); - // if(normal.y > normal.x + normal.z){ - // normal.x = 0; - // normal.z = 0; - // } receiver.addImpulse(new Impulse(normal, localPosition, worldPos, magnitude * 2, Collidable.TYPE_STATIC)); break; case Collidable.TYPE_CREATURE: @@ -276,8 +285,15 @@ public class CollisionEngine { spaceLock.unlock(); } + /** + * Gets the list of collidables + * @return The list of collidables + */ public List getCollidables(){ - return collidableList; + spaceLock.lock(); + List rVal = Collections.unmodifiableList(this.collidableList); + spaceLock.unlock(); + return rVal; } @@ -633,16 +649,16 @@ public class CollisionEngine { Matrix4d inverseTransform = new Matrix4d(); if(this.collisionWorldData != null){ for(Collidable collidable : collidableList){ - if(collidable.getParentTracksCollidable()){ + if(collidable.getParentTracksCollidable() && collidable.getReady()){ Entity physicsEntity = collidable.getParent(); DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity); DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity); - Vector4d rawPos = null; + Vector3d rawPos = null; inverseTransform.identity(); if(rigidBody != null){ - rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin),1)); + rawPos = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin); } else if(geom != null){ - rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(geom.getPosition()).add(this.floatingOrigin),1)); + rawPos = PhysicsUtils.odeVecToJomlVec(geom.getPosition()).add(this.floatingOrigin); } else { continue; } @@ -664,9 +680,21 @@ public class CollisionEngine { CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(physicsEntity); if(template != null){ suggestedPosition.sub(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()); + suggestedPosition = this.suggestMovementPosition(collisionWorldData, suggestedPosition); newRotation.mul(new Quaterniond(template.getRotX(),template.getRotY(),template.getRotZ(),template.getRotW()).invert()); } } + // if(rigidBody != null && suggestedPosition.distance(0,0,0) < 100){ + // String message = "\n" + + // "this.floatingOrigin: " + this.floatingOrigin + "\n" + + // "calculatedPosition: " + calculatedPosition + "\n" + + // "suggestedPosition: " + suggestedPosition + "\n" + + // "rawPos: " + rawPos + "\n" + + // (rigidBody != null ? "body: " + rigidBody.getPosition() + "\n" : "\n") + + // (geom != null ? "geom: " + geom.getPosition() + "\n" : "\n") + + // ""; + // throw new Error(message); + // } EntityUtils.getPosition(physicsEntity).set(suggestedPosition); EntityUtils.getRotation(physicsEntity).set(newRotation); } @@ -690,49 +718,46 @@ public class CollisionEngine { Entity physicsEntity = collidable.getParent(); DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity); if(rigidBody != null){ - Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin); + Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()); + // if(this.bodies.size() > 1 && currentBodyOffset.distance(0,0,0) > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN && this.hasRebased){ + // String message = "Body far outside expected range! " + currentBodyOffset + "\n"; + // message = message + this.getDebugStatus(); + // throw new Error(message); + // } + currentBodyOffset.add(this.floatingOrigin); if(collected == 0){ newOrigin.set(currentBodyOffset); } else { - float percentExisting = collected / (float)(collected + 1); - float percentNew = 1.0f - percentExisting; - newOrigin = newOrigin.mul(percentExisting).add(currentBodyOffset.mul(percentNew)); + newOrigin.add(currentBodyOffset); } collected++; } - // DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity); - // if(geom != null){ - // if(geom instanceof DSpace space){ - // for(DGeom child : space.getGeoms()){ - // Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(child.getPosition()).add(this.floatingOrigin); - // if(collected == 0){ - // newOrigin.set(currentBodyOffset); - // } else { - // float percentExisting = collected / (float)(collected + 1); - // float percentNew = 1.0f - percentExisting; - // newOrigin = newOrigin.mul(percentExisting).add(currentBodyOffset.mul(percentNew)); - // } - // collected++; - // } - // } else { - // Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(geom.getPosition()).add(this.floatingOrigin); - // if(collected == 0){ - // newOrigin.set(currentBodyOffset); - // } else { - // float percentExisting = collected / (float)(collected + 1); - // float percentNew = 1.0f - percentExisting; - // newOrigin = newOrigin.mul(percentExisting).add(currentBodyOffset.mul(percentNew)); - // } - // collected++; - // } - // } + } + if(collected > 0){ + newOrigin = newOrigin.mul(1.0/(double)collected); } newOrigin = newOrigin.round(); Vector3d delta = new Vector3d(this.floatingOrigin); delta = delta.sub(newOrigin); + //only perform rebase if sufficiently far away if(delta.length() > REBASE_TRIGGER_DISTANCE){ + //error checking + if(collected > 1 && delta.length() > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN){ + System.out.println("newOrigin: " + newOrigin); + System.out.println("delta: " + delta); + throw new Error(this.getDebugStatus()); + } + System.out.println("REbase"); + System.out.println(this.getStatus()); + System.out.println("newOrigin: " + newOrigin); + System.out.println("delta: " + delta); + if(delta.y > 100 || delta.y < -100){ + throw new Error(this.getDebugStatus()); + } + + this.floatingOrigin = newOrigin; //apply new origin to all geoms //calculate new origin @@ -757,6 +782,7 @@ public class CollisionEngine { } } } + this.hasRebased = true; } spaceLock.unlock(); Globals.profiler.endCpuSample(); @@ -766,12 +792,37 @@ public class CollisionEngine { * Registers a collision object with the server * @param body The body * @param collidable The corresponding collidable + * @param position The position of the body */ - public void registerCollisionObject(DBody body, Collidable collidable){ + public void registerCollisionObject(DBody body, Collidable collidable, Vector3d position){ if(collidable == null){ throw new Error("Collidable is null!"); } spaceLock.lock(); + // if(this.name.equals("serverPhysics") && position.distance(0,0,0) < 100){ + // throw new Error("Invalid position " + position); + // } + // if(this.name.equals("serverPhysics") && this.hasRebased && this.bodies.size() > 1 && position.distance(this.floatingOrigin) > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN){ + // String message = "Position invalid!\n" + + // "position: " + position.x + "," + position.y + "," + position.z + "\n" + + // "floating origin: " + this.floatingOrigin.x + "," + this.floatingOrigin.y + "," + this.floatingOrigin.z + "\n" + + // "dist: " + position.distance(this.floatingOrigin) + "\n" + + // "ent pos: " + EntityUtils.getPosition(collidable.getParent()) + "\n" + + // this.getDebugStatus() + + // ""; + // throw new Error(message); + // } + // if(this.name.equals("serverPhysics")){ + // System.out.println("Register collidable at " + position); + // } + + //Body transform needs to be set before the body is added to the collidable list + //this makes sure that dynamic update transforms and floating origin work correctly + this.setBodyTransform(body, new Vector3d(position), new Quaterniond()); + + // if(this.name.equals("serverPhysics") && (body.getPosition().get0() != position.x || body.getPosition().get1() != position.y || body.getPosition().get2() != position.z)){ + // System.out.println("Transform not set properly! " + body.getPosition() + " " + position); + // } this.registerPhysicsObject(body); bodyPointerMap.put(body,collidable); collidableList.add(collidable); @@ -1294,8 +1345,17 @@ public class CollisionEngine { */ protected void setBodyTransform(DBody body, Vector3d position, Quaterniond rotation){ spaceLock.lock(); + + // if(this.name.equals("serverPhysics")){ + // if(position.distance(0,0,0) < 100){ + // throw new Error("Reposition server body " + position); + // } + // } body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z); body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation)); + // if(this.name.equals("serverPhysics")){ + // System.out.println("SetBodyTransform " + body.getPosition()); + // } spaceLock.unlock(); } @@ -1334,8 +1394,26 @@ public class CollisionEngine { * @param angularForce The angular force */ protected void synchronizeData(DBody body, Vector3d position, Quaterniond rotation, Vector3d linearVel, Vector3d angularVel, Vector3d linearForce, Vector3d angularForce){ + if(!this.hasRebased){ + return; + } if(body != null){ spaceLock.lock(); + + + // if(this.name.equals("clientPhysics") || this.name.equals("serverPhysics")){ + // double posX = position.x - this.floatingOrigin.x; + // double posY = position.y - this.floatingOrigin.y; + // double posZ = position.z - this.floatingOrigin.z; + // if((posX > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posZ > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posX < -MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posZ < -MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN) && this.floatingOrigin.length() == 0 && this.hasRebased){ + // System.out.println("Sync body pos: " + posX + "," + posY + "," + posZ); + // spaceLock.unlock(); + // return; + // } + // if(this.bodies.size() > 2 && this.floatingOrigin.length() == 0 && this.hasRebased){ + // throw new Error(this.getDebugStatus()); + // } + // } body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z); body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation)); body.setLinearVel(PhysicsUtils.jomlVecToOdeVec(linearVel)); @@ -1355,6 +1433,19 @@ public class CollisionEngine { */ protected void setBodyTransform(DBody body, CollidableTemplate template, Vector3d position, Quaterniond rotation, Vector3d scale){ spaceLock.lock(); + // if(this.name.equals("clientPhysics") || this.name.equals("serverPhysics")){ + // double posX = position.x - this.floatingOrigin.x; + // double posY = position.y - this.floatingOrigin.y; + // double posZ = position.z - this.floatingOrigin.z; + // if((posX > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posZ > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posX < -MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posZ < -MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN) && this.floatingOrigin.length() == 0 && this.hasRebased){ + // System.out.println("Set body pos: " + posX + "," + posY + "," + posZ); + // spaceLock.unlock(); + // return; + // } + // if(this.bodies.size() > 2 && this.floatingOrigin.length() == 0 && this.hasRebased){ + // throw new Error(this.getDebugStatus()); + // } + // } body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z); body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation)); DGeom firstGeom = body.getFirstGeom(); @@ -1537,6 +1628,7 @@ public class CollisionEngine { */ public String getStatus(){ String message = "" + + "Name: " + this.name + "\n" + "Bodies: " + this.bodies.size() + "\n" + "Body Ptrs: " + this.bodyPointerMap.size() + "\n" + "Geom Ptrs: " + this.geomPointerMap.size() + "\n" + @@ -1549,6 +1641,22 @@ public class CollisionEngine { return message; } + /** + * Gets the status of the collision engine + * @return The status of the collision engine + */ + public String getDebugStatus(){ + String message = this.getStatus(); + for(Collidable collidable : collidableList){ + DBody rigidBody = PhysicsEntityUtils.getDBody(collidable.getParent()); + if(rigidBody != null){ + Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()); + message = message + existingPosition.x + "," + existingPosition.y + "," + existingPosition.z + "\n"; + } + } + return message; + } + /** * Gets the floating origin of the collision engine * @return The floating origin diff --git a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java index c06f2f37..71e983de 100644 --- a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java +++ b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java @@ -234,7 +234,7 @@ public class PhysicsEntityUtils { rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable); + Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal)); Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE); } break; case CollidableTemplate.COLLIDABLE_TYPE_CUBE: { @@ -298,7 +298,7 @@ public class PhysicsEntityUtils { rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable); + Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal)); Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE); } break; case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: { @@ -364,7 +364,7 @@ public class PhysicsEntityUtils { rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable); + Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal)); Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE); } break; } @@ -385,8 +385,9 @@ public class PhysicsEntityUtils { * @param realm The realm the entity is inside of * @param rVal The entity * @param physicsTemplate The collidable template + * @param position the position of the body */ - public static void serverAttachCollidableTemplate(Realm realm, Entity rVal, CollidableTemplate physicsTemplate){ + public static void serverAttachCollidableTemplate(Realm realm, Entity rVal, CollidableTemplate physicsTemplate, Vector3d position){ Collidable collidable; double mass = 1.0f; if(physicsTemplate.getMass() != null){ @@ -398,102 +399,7 @@ public class PhysicsEntityUtils { } CollisionEngine.lockOde(); if(physicsTemplate.getKinematic()){ - DGeom geom = null; - switch(physicsTemplate.getType()){ - case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: { - - // - //create dbody - geom = CollisionBodyCreation.createCylinderShape( - realm.getCollisionEngine(), - physicsTemplate.getDimension1(), - physicsTemplate.getDimension2(), - categoryBit - ); - - // - //create collidable and attach tracking - collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true); - PhysicsEntityUtils.setDGeom(rVal, geom); - - // - //store data - Matrix4d offsetTransform = new Matrix4d().translationRotateScale( - physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate - physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate - 1, 1, 1 //scale - ); - rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); - rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); - rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); - - rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - - ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); - realm.getCollisionEngine().registerCollisionObject(geom, collidable); - } break; - case CollidableTemplate.COLLIDABLE_TYPE_CUBE: { - // - //create dbody - geom = CollisionBodyCreation.createCubeShape( - realm.getCollisionEngine(), - new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()), - categoryBit - ); - - // - //create collidable and attach tracking - collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true); - PhysicsEntityUtils.setDGeom(rVal, geom); - - // - //store data - Matrix4d offsetTransform = new Matrix4d().translationRotateScale( - physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate - physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate - 1, 1, 1 //scale - ); - rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); - rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); - rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); - - rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - - ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); - realm.getCollisionEngine().registerCollisionObject(geom, collidable); - } break; - case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: { - // - //create dbody - geom = CollisionBodyCreation.createCapsuleShape( - realm.getCollisionEngine(), - physicsTemplate.getDimension1(), - physicsTemplate.getDimension2(), - categoryBit - ); - - // - //create collidable and attach tracking - collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true); - PhysicsEntityUtils.setDGeom(rVal, geom); - - // - //store data - Matrix4d offsetTransform = new Matrix4d().translationRotateScale( - physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate - physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate - 1, 1, 1 //scale - ); - rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); - rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); - rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); - - rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - - ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); - realm.getCollisionEngine().registerCollisionObject(geom, collidable); - } break; - } + PhysicsEntityUtils.serverAttachGeom(realm,rVal,physicsTemplate); } else { DBody rigidBody = null; switch(physicsTemplate.getType()){ @@ -551,17 +457,17 @@ public class PhysicsEntityUtils { realm.getCollisionEngine().setAngularlyStatic(rigidBody, true); } if(physicsTemplate.getKinematic()){ - Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody); + realm.getCollisionEngine().setKinematic(rigidBody); rigidBody.disable(); } rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree); - rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable); + + realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable, position); ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); } break; case CollidableTemplate.COLLIDABLE_TYPE_CUBE: { @@ -615,17 +521,17 @@ public class PhysicsEntityUtils { realm.getCollisionEngine().setAngularlyStatic(rigidBody, true); } if(physicsTemplate.getKinematic()){ - Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody); + realm.getCollisionEngine().setKinematic(rigidBody); rigidBody.disable(); } rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree); - rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable); + + realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable, position); ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); } break; case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: { @@ -681,17 +587,17 @@ public class PhysicsEntityUtils { realm.getCollisionEngine().setAngularlyStatic(rigidBody, true); } if(physicsTemplate.getKinematic()){ - Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody); + realm.getCollisionEngine().setKinematic(rigidBody); rigidBody.disable(); } rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree); - rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); - realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable); + + realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable, position); ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); } break; } @@ -706,6 +612,124 @@ public class PhysicsEntityUtils { CollisionEngine.unlockOde(); } + /** + * [SERVER ONLY] Attaches a collidable template to a given entity + * @param realm The realm the entity is inside of + * @param rVal The entity + * @param physicsTemplate The collidable template + * @return The geometry object + */ + public static DGeom serverAttachGeom(Realm realm, Entity rVal, CollidableTemplate physicsTemplate){ + if(physicsTemplate == null){ + throw new Error("Physics template is null!"); + } + Collidable collidable; + double mass = 1.0f; + long categoryBit = Collidable.TYPE_CREATURE_BIT; + if(physicsTemplate.getKinematic()){ + categoryBit = Collidable.TYPE_STATIC_BIT; + } + CollisionEngine.lockOde(); + DGeom geom = null; + switch(physicsTemplate.getType()){ + case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: { + + // + //create dbody + geom = CollisionBodyCreation.createCylinderShape( + realm.getCollisionEngine(), + physicsTemplate.getDimension1(), + physicsTemplate.getDimension2(), + categoryBit + ); + + // + //create collidable and attach tracking + collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true); + PhysicsEntityUtils.setDGeom(rVal, geom); + + // + //store data + Matrix4d offsetTransform = new Matrix4d().translationRotateScale( + physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate + physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate + 1, 1, 1 //scale + ); + rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); + rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); + rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); + + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + + ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); + realm.getCollisionEngine().registerCollisionObject(geom, collidable); + } break; + case CollidableTemplate.COLLIDABLE_TYPE_CUBE: { + // + //create dbody + geom = CollisionBodyCreation.createCubeShape( + realm.getCollisionEngine(), + new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()), + categoryBit + ); + + // + //create collidable and attach tracking + collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true); + PhysicsEntityUtils.setDGeom(rVal, geom); + + // + //store data + Matrix4d offsetTransform = new Matrix4d().translationRotateScale( + physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate + physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate + 1, 1, 1 //scale + ); + rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); + rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); + rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); + + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + + ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); + realm.getCollisionEngine().registerCollisionObject(geom, collidable); + } break; + case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: { + // + //create dbody + geom = CollisionBodyCreation.createCapsuleShape( + realm.getCollisionEngine(), + physicsTemplate.getDimension1(), + physicsTemplate.getDimension2(), + categoryBit + ); + + // + //create collidable and attach tracking + collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true); + PhysicsEntityUtils.setDGeom(rVal, geom); + + // + //store data + Matrix4d offsetTransform = new Matrix4d().translationRotateScale( + physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate + physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate + 1, 1, 1 //scale + ); + rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); + rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); + rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); + + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + + ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); + realm.getCollisionEngine().registerCollisionObject(geom, collidable); + } break; + } + CollisionEngine.unlockOde(); + return geom; + } + /** * [CLIENT ONLY] Given an entity and a terrain chunk description, create physics for the chunk and attach it to the entity @@ -718,7 +742,7 @@ public class PhysicsEntityUtils { DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT); CollisionBodyCreation.setAutoDisable(Globals.clientState.clientSceneWrapper.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD); Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false); - Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable); + Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable, EntityUtils.getPosition(terrain)); PhysicsEntityUtils.setDBody(terrain,terrainBody); CollisionEngine.unlockOde(); terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); @@ -750,7 +774,7 @@ public class PhysicsEntityUtils { DBody terrainBody = CollisionBodyCreation.generateBodyFromMultiShapeMeshData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT); CollisionBodyCreation.setAutoDisable(Globals.clientState.clientSceneWrapper.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD); Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false); - Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable); + Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable, EntityUtils.getPosition(terrain)); PhysicsEntityUtils.setDBody(terrain,terrainBody); terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); } @@ -781,7 +805,7 @@ public class PhysicsEntityUtils { DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT); CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD); - realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false)); + realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false), EntityUtils.getPosition(terrain)); PhysicsEntityUtils.setDBody(terrain,terrainBody); return terrainBody; @@ -816,7 +840,7 @@ public class PhysicsEntityUtils { DBody terrainBody = CollisionBodyCreation.generateBodyFromMultiShapeMeshData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT); CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD); - realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false)); + realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false), EntityUtils.getPosition(terrain)); PhysicsEntityUtils.setDBody(terrain,terrainBody); return terrainBody; @@ -889,6 +913,7 @@ public class PhysicsEntityUtils { ); } PhysicsEntityUtils.setCollidable(entity, null); + PhysicsEntityUtils.clearGeomAndBody(entity); Vector3d entityPos = EntityUtils.getPosition(entity); ServerEntityUtils.repositionEntity(entity, entityPos); } @@ -962,6 +987,18 @@ public class PhysicsEntityUtils { return (DGeom)entity.getData(EntityDataStrings.PHYSICS_GEOM); } + /** + * Clears the geom and body on an entity + * @param entity The entity + */ + public static void clearGeomAndBody(Entity entity){ + if(PhysicsEntityUtils.getCollidable(entity) != null){ + throw new Error("Trying to clear geom and body on an entity that still has a collidable!"); + } + entity.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY); + entity.removeData(EntityDataStrings.PHYSICS_GEOM); + } + /** * Sets the position of a DGeom * @param collisionEngine the collision engine diff --git a/src/main/java/electrosphere/collision/collidable/Collidable.java b/src/main/java/electrosphere/collision/collidable/Collidable.java index 82ec8961..e7bf9d7f 100644 --- a/src/main/java/electrosphere/collision/collidable/Collidable.java +++ b/src/main/java/electrosphere/collision/collidable/Collidable.java @@ -37,6 +37,11 @@ public class Collidable { * The params for the surface of this collidable when a collision occurs */ private SurfaceParams surfaceParams; + + /** + * Tracks whether this collidable has been simulated or not + */ + private boolean ready = false; //these should have corresponding category bits along with them public static final String TYPE_STATIC = "static"; @@ -122,6 +127,24 @@ public class Collidable { public void clear(){ impulses.clear(); } + + /** + * Gets whether the collidable is ready or not + * @return true if it is ready, false otherwise + */ + public boolean getReady() { + return ready; + } + + /** + * Sets the ready status of collidable + * @param ready true if the collidable is ready, false otherwise + */ + public void setReady(boolean ready) { + this.ready = ready; + } + + diff --git a/src/main/java/electrosphere/collision/hitbox/HitboxManager.java b/src/main/java/electrosphere/collision/hitbox/HitboxManager.java index 2f298a83..b8f70ab3 100644 --- a/src/main/java/electrosphere/collision/hitbox/HitboxManager.java +++ b/src/main/java/electrosphere/collision/hitbox/HitboxManager.java @@ -35,7 +35,7 @@ public class HitboxManager { * @param resolutionCallback The callback that fires when a collision occurs */ public HitboxManager(CollisionResolutionCallback resolutionCallback){ - collisionEngine = new CollisionEngine(); + collisionEngine = new CollisionEngine("hitbox"); collisionEngine.setCollisionResolutionCallback(resolutionCallback); } diff --git a/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java b/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java index b713bcb8..e4db9bbb 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java +++ b/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java @@ -160,7 +160,7 @@ public class LoadingUtils { } //set player character template serverPlayerConnection.setCreatureTemplate(template); - Character chara = Globals.serverState.characterService.createCharacter(template, serverPlayerConnection.getPlayerId()); + Character chara = Globals.serverState.characterService.createCharacter(template, serverPlayerConnection.getPlayerId(), new Vector3d()); Globals.clientState.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage(chara.getId() + "")); //set player world-space coordinates diff --git a/src/main/java/electrosphere/entity/ClientEntityUtils.java b/src/main/java/electrosphere/entity/ClientEntityUtils.java index 90643df2..196aa733 100644 --- a/src/main/java/electrosphere/entity/ClientEntityUtils.java +++ b/src/main/java/electrosphere/entity/ClientEntityUtils.java @@ -37,7 +37,7 @@ public class ClientEntityUtils { * @param entity * @param position */ - public static void reositionEntity(Entity entity, Vector3d position, Quaterniond rotation){ + public static void repositionEntity(Entity entity, Vector3d position, Quaterniond rotation){ //reposition entity CollisionObjUtils.clientPositionCharacter(entity, position, rotation); EntityUtils.getPosition(entity).set(position); diff --git a/src/main/java/electrosphere/entity/DrawableUtils.java b/src/main/java/electrosphere/entity/DrawableUtils.java index 51580287..bc5595ba 100644 --- a/src/main/java/electrosphere/entity/DrawableUtils.java +++ b/src/main/java/electrosphere/entity/DrawableUtils.java @@ -115,7 +115,9 @@ public class DrawableUtils { }); String path = Globals.assetManager.queuedAsset(model); entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorOfLoadingModel(path)); - entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); + if(!entity.containsKey(EntityDataStrings.DATA_STRING_POSITION)){ + 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_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_DRAW, true); @@ -132,7 +134,9 @@ public class DrawableUtils { */ public static void makeEntityDrawable(Entity entity, String path){ entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorFromModelPath(path)); - entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); + if(!entity.containsKey(EntityDataStrings.DATA_STRING_POSITION)){ + 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_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_DRAW, true); diff --git a/src/main/java/electrosphere/entity/EntityCreationUtils.java b/src/main/java/electrosphere/entity/EntityCreationUtils.java index 3891764e..55692142 100644 --- a/src/main/java/electrosphere/entity/EntityCreationUtils.java +++ b/src/main/java/electrosphere/entity/EntityCreationUtils.java @@ -131,7 +131,9 @@ public class EntityCreationUtils { */ public static void makeEntityPoseable(Entity entity, String modelPath){ entity.putData(EntityDataStrings.POSE_ACTOR, PoseActorUtils.createPoseActorFromModelPath(modelPath)); - entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); + if(!entity.containsKey(EntityDataStrings.DATA_STRING_POSITION)){ + 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_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_DRAW, true); @@ -147,7 +149,9 @@ public class EntityCreationUtils { */ public static void makeEntityDrawable(Entity entity, String modelPath){ entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorFromModelPath(modelPath)); - entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); + if(!entity.containsKey(EntityDataStrings.DATA_STRING_POSITION)){ + 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_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_DRAW, true); diff --git a/src/main/java/electrosphere/entity/ServerEntityUtils.java b/src/main/java/electrosphere/entity/ServerEntityUtils.java index 8559aacc..3ebfbade 100644 --- a/src/main/java/electrosphere/entity/ServerEntityUtils.java +++ b/src/main/java/electrosphere/entity/ServerEntityUtils.java @@ -40,10 +40,20 @@ public class ServerEntityUtils { if(position == null){ throw new Error("Trying to set server entity position to null!"); } + double startX = position.x; + double startY = position.y; + double startZ = position.z; //reposition entity, if the position isn't correct then it will spawn at 0,0,0 when the synchronization part is called CollisionObjUtils.serverPositionCharacter(entity, position); //get current server data cell ServerDataCell cell = realm.getDataCellManager().getDataCellAtPoint(position); + if(startX != position.x || startX != position.x || startX != position.x){ + throw new Error("Position not preserved while initially positioning entity! " + startX + "," + startY + "," + startZ + " " + position.x + "," + position.y + "," + position.z); + } + Vector3d entPos = EntityUtils.getPosition(entity); + if(startX != entPos.x || startX != entPos.x || startX != entPos.x){ + throw new Error("Position not preserved while initially positioning entity! " + startX + "," + startY + "," + startZ + " " + entPos.x + "," + entPos.y + "," + entPos.z); + } if(cell != null){ //initialize server datacell tracking of this entity realm.initializeServerSideEntity(entity, cell); @@ -56,6 +66,9 @@ public class ServerEntityUtils { //initialize server datacell tracking of this entity realm.initializeServerSideEntity(entity, cell); } + if(startX != position.x || startX != position.x || startX != position.x){ + throw new Error("Position not preserved while initially positioning entity! " + startX + "," + startY + "," + startZ + " " + position.x + "," + position.y + "," + position.z); + } } /** @@ -70,6 +83,10 @@ public class ServerEntityUtils { if(AttachUtils.getParent(entity) != null){ throw new Error("Trying to reposition attached entity!"); } + double startX = position.x; + double startY = position.y; + double startZ = position.z; + Realm realm = Globals.serverState.realmManager.getEntityRealm(entity); ServerWorldData worldDat = realm.getServerWorldData(); if( @@ -85,6 +102,11 @@ public class ServerEntityUtils { ServerEntityUtils.repositionEntityRecursive(realm, entity, position); //reposition entity CollisionObjUtils.serverPositionCharacter(entity, position); + + //error checking + if(position.x != startX || position.y != startY || position.z != startZ){ + throw new Error("Position mutated while repositioning! " + position + " " + startX + "," + startY + "," + startZ); + } } /** diff --git a/src/main/java/electrosphere/entity/scene/Scene.java b/src/main/java/electrosphere/entity/scene/Scene.java index 68274425..b1ca68e7 100644 --- a/src/main/java/electrosphere/entity/scene/Scene.java +++ b/src/main/java/electrosphere/entity/scene/Scene.java @@ -57,7 +57,7 @@ public class Scene { /** * Lock for threadsafeing the scene */ - ReentrantLock lock = new ReentrantLock(); + private ReentrantLock lock = new ReentrantLock(); /** * Constructor diff --git a/src/main/java/electrosphere/entity/state/collidable/ClientCollidableTree.java b/src/main/java/electrosphere/entity/state/collidable/ClientCollidableTree.java index 35c0c616..74f7e487 100644 --- a/src/main/java/electrosphere/entity/state/collidable/ClientCollidableTree.java +++ b/src/main/java/electrosphere/entity/state/collidable/ClientCollidableTree.java @@ -66,6 +66,8 @@ public class ClientCollidableTree implements BehaviorTree { } PhysicsUtils.setRigidBodyTransform(Globals.clientState.clientSceneWrapper.getCollisionEngine(), newPosition, rotation, body); + collidable.setReady(true); + //capsule-specific block collision logic // if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){ // //get capsule params diff --git a/src/main/java/electrosphere/entity/state/collidable/ServerCollidableTree.java b/src/main/java/electrosphere/entity/state/collidable/ServerCollidableTree.java index 621d1a47..5e3c41fd 100644 --- a/src/main/java/electrosphere/entity/state/collidable/ServerCollidableTree.java +++ b/src/main/java/electrosphere/entity/state/collidable/ServerCollidableTree.java @@ -59,6 +59,8 @@ public class ServerCollidableTree implements BehaviorTree { this.resetGravityFall(); } } + + collidable.setReady(true); //capsule-specific block collision logic // if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){ diff --git a/src/main/java/electrosphere/entity/state/furniture/ServerDoorState.java b/src/main/java/electrosphere/entity/state/furniture/ServerDoorState.java index 26576f53..b27c414b 100644 --- a/src/main/java/electrosphere/entity/state/furniture/ServerDoorState.java +++ b/src/main/java/electrosphere/entity/state/furniture/ServerDoorState.java @@ -86,7 +86,7 @@ public class ServerDoorState implements BehaviorTree { this.setState(DoorState.CLOSED); Realm parentRealm = Globals.serverState.realmManager.getEntityRealm(this.parent); Vector3d pos = EntityUtils.getPosition(this.parent); - PhysicsEntityUtils.serverAttachCollidableTemplate(parentRealm, this.parent, PhysicsEntityUtils.getPhysicsTemplate(this.parent)); + PhysicsEntityUtils.serverAttachCollidableTemplate(parentRealm, this.parent, PhysicsEntityUtils.getPhysicsTemplate(this.parent), pos); ServerEntityUtils.repositionEntity(this.parent, pos); } ), diff --git a/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java b/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java index 79ece7c3..e218ff78 100644 --- a/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java +++ b/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java @@ -284,7 +284,8 @@ public class HitboxCollectionState { //register collidable with collision engine this.collidable = new Collidable(this.parent, Collidable.TYPE_OBJECT, true); - collisionEngine.registerCollisionObject(this.body, this.collidable); + Vector3d entPos = EntityUtils.getPosition(this.parent); + collisionEngine.registerCollisionObject(this.body, this.collidable, entPos); CollisionEngine.unlockOde(); } diff --git a/src/main/java/electrosphere/entity/state/inventory/ServerInventoryState.java b/src/main/java/electrosphere/entity/state/inventory/ServerInventoryState.java index c2dc0d22..7f532019 100644 --- a/src/main/java/electrosphere/entity/state/inventory/ServerInventoryState.java +++ b/src/main/java/electrosphere/entity/state/inventory/ServerInventoryState.java @@ -350,7 +350,6 @@ public class ServerInventoryState implements BehaviorTree { inventory.addItem(inventoryItem); //if we are the server, immediately send required packets ServerDataCell dataCell = DataCellSearchUtils.getEntityDataCell(item); - // ServerDataCell dataCell = Globals.dataCellLocationResolver.getDataCellAtPoint(EntityUtils.getPosition(item),item); //broadcast destroy entityq dataCell.broadcastNetworkMessage(EntityMessage.constructDestroyMessage(item.getId())); diff --git a/src/main/java/electrosphere/entity/state/lod/ClientLODComponent.java b/src/main/java/electrosphere/entity/state/lod/ClientLODComponent.java index babb48f1..c219d4ba 100644 --- a/src/main/java/electrosphere/entity/state/lod/ClientLODComponent.java +++ b/src/main/java/electrosphere/entity/state/lod/ClientLODComponent.java @@ -57,7 +57,7 @@ public class ClientLODComponent implements BehaviorTree { ){ CollidableTemplate physicsTemplate = commonData.getCollidable(); PhysicsEntityUtils.clientAttachCollidableTemplate(this.parent, physicsTemplate); - ClientEntityUtils.reositionEntity(parent, EntityUtils.getPosition(parent), EntityUtils.getRotation(parent)); + ClientEntityUtils.repositionEntity(parent, EntityUtils.getPosition(parent), EntityUtils.getRotation(parent)); } } if(cachedLodLevel != lodLevel){ @@ -66,7 +66,7 @@ public class ClientLODComponent implements BehaviorTree { CommonEntityType type = CommonEntityUtils.getCommonData(this.parent); if(type.getCollidable() != null && PhysicsEntityUtils.getCollidable(this.parent) == null){ PhysicsEntityUtils.clientAttachCollidableTemplate(parent, type.getCollidable()); - ClientEntityUtils.reositionEntity(parent, EntityUtils.getPosition(parent), EntityUtils.getRotation(parent)); + ClientEntityUtils.repositionEntity(parent, EntityUtils.getPosition(parent), EntityUtils.getRotation(parent)); } } else if(cachedLodLevel == ServerLODComponent.LOW_RES){ if(PhysicsEntityUtils.containsDBody(this.parent)){ diff --git a/src/main/java/electrosphere/entity/state/lod/ServerLODComponent.java b/src/main/java/electrosphere/entity/state/lod/ServerLODComponent.java index d4a22ac0..884e61d2 100644 --- a/src/main/java/electrosphere/entity/state/lod/ServerLODComponent.java +++ b/src/main/java/electrosphere/entity/state/lod/ServerLODComponent.java @@ -17,6 +17,7 @@ import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums; import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.types.common.CommonEntityUtils; +import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.net.synchronization.annotation.SyncedField; import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; @@ -63,7 +64,8 @@ public class ServerLODComponent implements BehaviorTree { Realm realm = Globals.serverState.realmManager.getEntityRealm(this.parent); CommonEntityType type = CommonEntityUtils.getCommonData(this.parent); if(type.getCollidable() != null){ - PhysicsEntityUtils.serverAttachCollidableTemplate(realm, this.parent, type.getCollidable()); + PhysicsEntityUtils.serverDestroyPhysics(this.parent); + PhysicsEntityUtils.serverAttachCollidableTemplate(realm, this.parent, type.getCollidable(),EntityUtils.getPosition(parent)); } } } else { @@ -71,6 +73,14 @@ public class ServerLODComponent implements BehaviorTree { //make low res this.setLodLevel(LOW_RES); PhysicsEntityUtils.serverDestroyPhysics(this.parent); + Realm realm = Globals.serverState.realmManager.getEntityRealm(parent); + CommonEntityType type = CommonEntityUtils.getCommonData(this.parent); + if(type.getCollidable() != null){ + if(CreatureUtils.hasControllerPlayerId(parent)){ + throw new Error("Should not be attaching a geometry to a player entity!"); + } + PhysicsEntityUtils.serverAttachGeom(realm, parent, type.getCollidable()); + } } } } diff --git a/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java b/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java index 2050781c..ec590649 100644 --- a/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java +++ b/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java @@ -32,7 +32,7 @@ public class CollisionObjUtils { Vector3d position = EntityUtils.getPosition(entity); Quaterniond rotation = EntityUtils.getRotation(entity); Collidable collidable = new Collidable(entity, collidableType, true); - Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(collisionObject, collidable); + Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(collisionObject, collidable, EntityUtils.getPosition(entity)); PhysicsEntityUtils.setDBody(entity, collisionObject); @@ -55,7 +55,7 @@ public class CollisionObjUtils { Vector3d position = EntityUtils.getPosition(entity); Collidable collidable = new Collidable(entity, collidableType, true); Realm realm = Globals.serverState.realmManager.getEntityRealm(entity); - realm.getCollisionEngine().registerCollisionObject(collisionObject, collidable); + realm.getCollisionEngine().registerCollisionObject(collisionObject, collidable, EntityUtils.getPosition(entity)); PhysicsEntityUtils.setDBody(entity, collisionObject); @@ -73,7 +73,15 @@ public class CollisionObjUtils { * @param position The server */ public static void serverPositionCharacter(Entity e, Vector3d position){ - EntityUtils.getPosition(e).set(position); + CollisionEngine.lockOde(); + double startX = position.x; + double startY = position.y; + double startZ = position.z; + Vector3d entPos = EntityUtils.getPosition(e); + entPos.set(position); + if(startX != entPos.x || startX != entPos.x || startX != entPos.x){ + throw new Error("Failed to position entity! " + startX + "," + startY + "," + startZ + " " + entPos.x + "," + entPos.y + "," + entPos.z); + } Quaterniond rotation = EntityUtils.getRotation(e); DBody body = PhysicsEntityUtils.getDBody(e); DGeom geom = PhysicsEntityUtils.getDGeom(e); @@ -86,7 +94,7 @@ public class CollisionObjUtils { if(template == null){ PhysicsUtils.setGeomTransform( collisionEngine, - position, + new Vector3d(position), rotation, geom ); @@ -99,6 +107,14 @@ public class CollisionObjUtils { ); } } + Vector3d finalRef = EntityUtils.getPosition(e); + if(finalRef != entPos){ + throw new Error("Reference changed while positioning character! " + entPos + " " + finalRef); + } + if(startX != entPos.x || startX != entPos.x || startX != entPos.x){ + throw new Error("Position not preserved while positioning entity! " + startX + "," + startY + "," + startZ + " " + entPos.x + "," + entPos.y + "," + entPos.z + " " + position); + } + CollisionEngine.unlockOde(); } /** diff --git a/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java b/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java index b955e917..b07c85a4 100644 --- a/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java +++ b/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java @@ -432,6 +432,10 @@ public class CommonEntityUtils { */ public static Entity serverApplyCommonEntityTransforms(Realm realm, Vector3d position, Entity entity, CommonEntityType rawType){ + double startX = position.x; + double startY = position.y; + double startZ = position.z; + // //Set typing stuff // @@ -498,6 +502,9 @@ public class CommonEntityUtils { // Hitbox stuff // // + if(position.x != startX || position.y != startY || position.z != startZ){ + throw new Error("Position mutated while spawning entity!"); + } if(rawType.getHitboxes() != null){ HitboxCollectionState.attachHitboxState(realm.getHitboxManager(), true, entity, rawType.getHitboxes()); } @@ -507,9 +514,12 @@ public class CommonEntityUtils { // // if(rawType.getCollidable() != null){ + //actually attach collidable CollidableTemplate physicsTemplate = rawType.getCollidable(); if(Globals.serverState.lodEmitterService.isFullLod(position)){ - PhysicsEntityUtils.serverAttachCollidableTemplate(realm, entity, physicsTemplate); + PhysicsEntityUtils.serverAttachCollidableTemplate(realm, entity, physicsTemplate,position); + } else { + PhysicsEntityUtils.serverAttachGeom(realm, entity, physicsTemplate); } ServerLODComponent.attachTree(entity); } diff --git a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java index 55c86383..5e2261fe 100644 --- a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java +++ b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java @@ -209,6 +209,11 @@ public class CreatureUtils { * @return The creature entity */ public static Entity serverSpawnBasicCreature(Realm realm, Vector3d position, String type, ObjectTemplate template){ + + double posX = position.x; + double posY = position.y; + double posZ = position.z; + CreatureData rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getType(type); Entity rVal = EntityCreationUtils.createServerEntity(realm, position); @@ -287,6 +292,11 @@ public class CreatureUtils { storedTemplate.objectType = rawType.getId(); //store template on creature CreatureUtils.setCreatureTemplate(rVal, storedTemplate); + + //error check position modification + if(posX != position.x || posY != position.y || posZ != position.z){ + throw new Error("Creature has mutated position! " + posX + "," + posY + "," + posZ + " " + position.x + "," + position.y + "," + position.z); + } //position entity @@ -300,6 +310,10 @@ public class CreatureUtils { if(Globals.serverState.realmManager.getEntityRealm(rVal) == null){ LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Created creature without it being assigned to a realm!")); } + //make sure position hasn't changed + if(posX != position.x || posY != position.y || posZ != position.z){ + throw new Error("Creature has mutated position! " + posX + "," + posY + "," + posZ + " " + position.x + "," + position.y + "," + position.z); + } return rVal; } diff --git a/src/main/java/electrosphere/entity/types/terrain/BlockChunkEntity.java b/src/main/java/electrosphere/entity/types/terrain/BlockChunkEntity.java index 3b3ceb5d..acc6a6e3 100644 --- a/src/main/java/electrosphere/entity/types/terrain/BlockChunkEntity.java +++ b/src/main/java/electrosphere/entity/types/terrain/BlockChunkEntity.java @@ -79,7 +79,7 @@ public class BlockChunkEntity { EntityCreationUtils.makeEntityDrawablePreexistingModel(solidsEnt, modelPath); if(levelOfDetail == BlockChunkData.LOD_FULL_RES){ PhysicsEntityUtils.clientAttachTriGeomCollider(solidsEnt, data); - ClientEntityUtils.reositionEntity(solidsEnt, new Vector3d(EntityUtils.getPosition(solidsEnt)), new Quaterniond()); + ClientEntityUtils.repositionEntity(solidsEnt, new Vector3d(EntityUtils.getPosition(solidsEnt)), new Quaterniond()); } else { EntityCreationUtils.bypassShadowPass(solidsEnt); EntityCreationUtils.bypassVolumetics(solidsEnt); diff --git a/src/main/java/electrosphere/entity/types/tree/ProceduralTree.java b/src/main/java/electrosphere/entity/types/tree/ProceduralTree.java index eca0d44f..953eac5f 100644 --- a/src/main/java/electrosphere/entity/types/tree/ProceduralTree.java +++ b/src/main/java/electrosphere/entity/types/tree/ProceduralTree.java @@ -144,7 +144,7 @@ public class ProceduralTree { trunkChild.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); trunkChild.putData(EntityDataStrings.PHYSICS_MASS, TREE_MASS); - Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable); + Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(trunkChild)); //generate branches @@ -549,7 +549,7 @@ public class ProceduralTree { trunkChild.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); trunkChild.putData(EntityDataStrings.PHYSICS_MASS, TREE_MASS); - realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable); + realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(trunkChild)); return trunkChild; } diff --git a/src/main/java/electrosphere/net/server/player/Player.java b/src/main/java/electrosphere/net/server/player/Player.java index 7105cc03..fa306a04 100644 --- a/src/main/java/electrosphere/net/server/player/Player.java +++ b/src/main/java/electrosphere/net/server/player/Player.java @@ -38,37 +38,37 @@ public class Player { /** * The corresponding connection handler */ - ServerConnectionHandler connectionHandler; + private ServerConnectionHandler connectionHandler; /** * The id of the player */ - int id; + private int id; /** * The database's id of the player */ - int dbId; + private int dbId; /** * The world position of this player */ - Vector3i worldPos; + private Vector3i worldPos; /** * The simulation radius of this player */ - int simulationRadius = DEFAULT_SIMULATION_RADIUS; + private int simulationRadius = DEFAULT_SIMULATION_RADIUS; /** * The player's primary entity */ - Entity playerEntity; + private Entity playerEntity; /** * Tracks whether the player's entity has been sent or not */ - boolean hasSentPlayerEntity = false; + private boolean hasSentPlayerEntity = false; /** * Constructor diff --git a/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java b/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java index ab613471..8cd3d134 100644 --- a/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java +++ b/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java @@ -69,8 +69,7 @@ public class CharacterProtocol implements ServerProtocolTemplate { - serverContentManager.saveSerializationToDisk(key, serializedEntities); - serverTerrainManager.savePositionToDisk(worldPos); + try { + serverContentManager.saveSerializationToDisk(key, serializedEntities); + serverTerrainManager.savePositionToDisk(worldPos); + } catch(Throwable e){ + e.printStackTrace(); + } }); Globals.profiler.endCpuSample(); @@ -895,9 +900,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager this.loaderService.queueLocationBasedOperation(key, () -> { try { serverContentManager.generateContentForDataCell(parent, localWorldPos, rVal, cellKey); - } catch(Error e){ - e.printStackTrace(); - } catch(Exception e){ + } catch(Throwable e){ e.printStackTrace(); } }); diff --git a/src/main/java/electrosphere/server/entity/ServerContentManager.java b/src/main/java/electrosphere/server/entity/ServerContentManager.java index 77ef3856..b1af199b 100644 --- a/src/main/java/electrosphere/server/entity/ServerContentManager.java +++ b/src/main/java/electrosphere/server/entity/ServerContentManager.java @@ -5,6 +5,7 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; +import org.joml.Vector3d; import org.joml.Vector3i; import electrosphere.engine.Globals; diff --git a/src/main/java/electrosphere/server/macro/character/CharacterUtils.java b/src/main/java/electrosphere/server/macro/character/CharacterUtils.java index a1510ce4..cfd3d486 100644 --- a/src/main/java/electrosphere/server/macro/character/CharacterUtils.java +++ b/src/main/java/electrosphere/server/macro/character/CharacterUtils.java @@ -99,8 +99,7 @@ public class CharacterUtils { public static Character spawnCharacter(Realm realm, Vector3d position, String race){ Race raceData = Globals.gameConfigCurrent.getRaceMap().getRace(race); String creatureType = raceData.getAssociatedCreature(); - Character rVal = Globals.serverState.characterService.createCharacter(ObjectTemplate.createDefault(EntityType.CREATURE, creatureType), CharacterService.NO_PLAYER); - rVal.setPos(position); + Character rVal = Globals.serverState.characterService.createCharacter(ObjectTemplate.createDefault(EntityType.CREATURE, creatureType), CharacterService.NO_PLAYER, position); Race.setRace(rVal, Race.create(race, creatureType)); realm.getDataCellManager().evaluateMacroObject(rVal); return rVal; diff --git a/src/main/java/electrosphere/server/macro/civilization/town/TownPopulator.java b/src/main/java/electrosphere/server/macro/civilization/town/TownPopulator.java index 6c2c9ca9..376a387d 100644 --- a/src/main/java/electrosphere/server/macro/civilization/town/TownPopulator.java +++ b/src/main/java/electrosphere/server/macro/civilization/town/TownPopulator.java @@ -30,12 +30,12 @@ public class TownPopulator { List structs = town.getStructures(macroData); Random rand = new Random(town.getId()); for(VirtualStructure struct : structs){ + Vector3d placePos = new Vector3d(struct.getPos()).add(1,1,1); ObjectTemplate template = ObjectTemplate.create(EntityType.CREATURE, "human"); - Character chara = Globals.serverState.characterService.createCharacter(template, CharacterService.NO_PLAYER); + Character chara = Globals.serverState.characterService.createCharacter(template, CharacterService.NO_PLAYER, placePos); Race.setRace(chara, Globals.gameConfigCurrent.getRaceMap().getRace("human")); CharacterUtils.addShelter(chara, struct); town.addResident(chara); - chara.setPos(new Vector3d(struct.getPos()).add(1,1,1)); } //assign jobs to created characters diff --git a/src/main/java/electrosphere/server/service/CharacterService.java b/src/main/java/electrosphere/server/service/CharacterService.java index 210c4e8d..a5092c59 100644 --- a/src/main/java/electrosphere/server/service/CharacterService.java +++ b/src/main/java/electrosphere/server/service/CharacterService.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; +import org.joml.Vector3d; import org.joml.Vector3i; import com.google.gson.Gson; @@ -61,13 +62,15 @@ public class CharacterService extends SignalServiceImpl { * Creates a character in the database * @param template The creature template for the character * @param playerId The player's id + * @param pos The position to place the character at */ - public Character createCharacter(ObjectTemplate template, int playerId){ + public Character createCharacter(ObjectTemplate template, int playerId, Vector3d pos){ if(template == null){ throw new Error("Template is null!"); } lock.lock(); Character toStore = new Character(template); + toStore.setPos(pos); toStore.setPlayerId(playerId); DatabaseResult result = Globals.serverState.dbController.executePreparedQuery( "INSERT INTO charaData (playerId,dataVal) VALUES (?,?) RETURNING id;", diff --git a/src/test/java/electrosphere/test/testutils/TestEngineUtils.java b/src/test/java/electrosphere/test/testutils/TestEngineUtils.java index 4139fb68..a6ba9982 100644 --- a/src/test/java/electrosphere/test/testutils/TestEngineUtils.java +++ b/src/test/java/electrosphere/test/testutils/TestEngineUtils.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.concurrent.TimeUnit; +import org.joml.Vector3d; import org.junit.jupiter.api.Assertions; import java.util.function.Supplier; @@ -165,7 +166,7 @@ public class TestEngineUtils { ObjectTemplate creatureTemplate = ObjectTemplate.createDefault(EntityType.CREATURE, "human"); ServerConnectionHandler serverConnection = Globals.serverState.server.getFirstConnection(); serverConnection.setCreatureTemplate(creatureTemplate); - Character chara = Globals.serverState.characterService.createCharacter(creatureTemplate, serverConnection.getPlayerId()); + Character chara = Globals.serverState.characterService.createCharacter(creatureTemplate, serverConnection.getPlayerId(), new Vector3d()); serverConnection.setCharacterId(chara.getId()); PlayerCharacterCreation.spawnPlayerCharacter(serverConnection); }