hitbox collision debugging
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-09-02 18:30:26 -04:00
parent bff1b62659
commit b1612cc943
9 changed files with 192 additions and 66 deletions

View File

@ -649,6 +649,24 @@ Fix Yoga double free bug
Explicit error on setting uniform to unsupported type Explicit error on setting uniform to unsupported type
Methods for getting buffers from mesh Methods for getting buffers from mesh
(08/29/2024)
use STBImage instead of ImageIO
Signal passing architecture
Services architecture
(09/01/2024)
Lots of jenkins pipeline work (finally got it mostly consistent!)
(09/02/2024)
Engine mostly building reproducibly/consistently/testably
Framebuffer fixes
Attack tree integration test
Shadowmap fixes
Shadowmap pipeline debug menu
Shader storage refactor
Unit definition/spawning
Hitbox updates for katana 2H
# TODO # TODO

View File

@ -5,6 +5,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.ode4j.ode.DContactGeom; import org.ode4j.ode.DContactGeom;
import org.ode4j.ode.DGeom;
import electrosphere.collision.CollisionEngine; import electrosphere.collision.CollisionEngine;
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback; import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
@ -220,8 +221,8 @@ public class ClientSceneWrapper {
*/ */
CollisionResolutionCallback resolutionCallback = new CollisionResolutionCallback() { CollisionResolutionCallback resolutionCallback = new CollisionResolutionCallback() {
@Override @Override
public void resolve(DContactGeom geom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) { public void resolve(DContactGeom geom, DGeom impactorGeom, DGeom receiverGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) {
HitboxUtils.clientDamageHitboxColision(geom, impactor, receiver, normal, localPosition, worldPos, magnitude); HitboxUtils.clientDamageHitboxColision(geom, impactorGeom, receiverGeom, impactor, receiver, normal, localPosition, worldPos, magnitude);
} }
}; };

View File

@ -353,6 +353,8 @@ public class CollisionEngine {
//use custom collision resolution //use custom collision resolution
collisionResolutionCallback.resolve( collisionResolutionCallback.resolve(
contact.geom, contact.geom,
o1,
o2,
bodyPointerMap.get(o1.getBody()), bodyPointerMap.get(o1.getBody()),
bodyPointerMap.get(o2.getBody()), bodyPointerMap.get(o2.getBody()),
PhysicsUtils.odeVecToJomlVec(contact.geom.normal).mul(-1.0), PhysicsUtils.odeVecToJomlVec(contact.geom.normal).mul(-1.0),
@ -362,6 +364,8 @@ public class CollisionEngine {
); );
collisionResolutionCallback.resolve( collisionResolutionCallback.resolve(
contact.geom, contact.geom,
o2,
o1,
bodyPointerMap.get(o2.getBody()), bodyPointerMap.get(o2.getBody()),
bodyPointerMap.get(o1.getBody()), bodyPointerMap.get(o1.getBody()),
PhysicsUtils.odeVecToJomlVec(contact.geom.normal), PhysicsUtils.odeVecToJomlVec(contact.geom.normal),
@ -931,6 +935,8 @@ public class CollisionEngine {
/** /**
* Resolves a collision between two collidables in the engine * Resolves a collision between two collidables in the engine
* @param contactGeom the ode4j contact geom * @param contactGeom the ode4j contact geom
* @param geom1 The first geometry
* @param geom2 The second geometry
* @param impactor The collidable initiating the contact * @param impactor The collidable initiating the contact
* @param receiver The collidable recieving the contact * @param receiver The collidable recieving the contact
* @param normal The normal of the collision * @param normal The normal of the collision
@ -938,7 +944,7 @@ public class CollisionEngine {
* @param worldPos The world position of the collision * @param worldPos The world position of the collision
* @param magnitude The magnitude 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); public void resolve(DContactGeom contactGeom, DGeom geom1, DGeom geom2, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude);
} }
} }

View File

@ -25,8 +25,16 @@ import electrosphere.logger.LoggerInterface;
public class RayCastCallback implements DNearCallback { public class RayCastCallback implements DNearCallback {
/**
* Maximum number of contacts allowed
*/
static final int MAX_CONTACTS = 5; static final int MAX_CONTACTS = 5;
/**
* Really far away from the ray origin point
*/
static final double REALLY_LONG_DISTANCE = 1000000;
/** /**
* // Check ray collision against a space * // Check ray collision against a space
void RayCallback(void *Data, dGeomID Geometry1, dGeomID Geometry2) { void RayCallback(void *Data, dGeomID Geometry1, dGeomID Geometry2) {
@ -49,7 +57,7 @@ void RayCallback(void *Data, dGeomID Geometry1, dGeomID Geometry2) {
//For the current execution, this stores the shortest length that has currently been encountered. //For the current execution, this stores the shortest length that has currently been encountered.
//This is used to keep track of the closest body so that there doesn't need to be contact join creation. //This is used to keep track of the closest body so that there doesn't need to be contact join creation.
//This should be reset every time a ray cast is called in collision engine by calling setLength in this object. //This should be reset every time a ray cast is called in collision engine by calling setLength in this object.
double shortestLength = 1000000; double shortestLength = REALLY_LONG_DISTANCE;
@Override @Override
public void call(Object data, DGeom o1, DGeom o2) { public void call(Object data, DGeom o1, DGeom o2) {
@ -111,6 +119,14 @@ void RayCallback(void *Data, dGeomID Geometry1, dGeomID Geometry2) {
} }
} }
} }
if(rayCastData.collisionPosition == null){
String errorMessage = "Collision error!\n" +
"body1: " + b1 + "\n" +
"body2: " + b2 + "\n" +
"collidable1: " + collidable1 + "\n" +
"collidable2: " + collidable2 + "\n";
LoggerInterface.loggerEngine.ERROR(new IllegalStateException(errorMessage));
}
} }
} }
} }

View File

@ -24,14 +24,12 @@ public class HitboxUtils {
* @param impactor the entity initiating the collision * @param impactor the entity initiating the collision
* @param receiver the entity receiving the collision * @param receiver the entity receiving the collision
*/ */
public static void clientDamageHitboxColision(DContactGeom contactGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude){ public static void clientDamageHitboxColision(DContactGeom contactGeom, DGeom impactorGeom, DGeom receiverGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude){
Entity impactorParent = impactor.getParent(); Entity impactorParent = impactor.getParent();
Entity receiverParent = receiver.getParent(); Entity receiverParent = receiver.getParent();
HitboxCollectionState impactorState = HitboxCollectionState.getHitboxState(impactorParent); HitboxCollectionState impactorState = HitboxCollectionState.getHitboxState(impactorParent);
HitboxCollectionState receiverState = HitboxCollectionState.getHitboxState(receiverParent); HitboxCollectionState receiverState = HitboxCollectionState.getHitboxState(receiverParent);
DGeom impactorGeom = contactGeom.g1;
DGeom receiverGeom = contactGeom.g2;
HitboxState impactorShapeStatus = impactorState.getShapeStatus(impactorGeom); HitboxState impactorShapeStatus = impactorState.getShapeStatus(impactorGeom);
HitboxState receiverShapeStatus = receiverState.getShapeStatus(receiverGeom); HitboxState receiverShapeStatus = receiverState.getShapeStatus(receiverGeom);

View File

@ -1,6 +1,5 @@
package electrosphere.entity.state.hitbox; package electrosphere.entity.state.hitbox;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -268,21 +267,27 @@ public class HitboxCollectionState {
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation); PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, worldPosition, rotation);
} }
//update bone-attached hitboxes on server
} else if(parent != null && isServer && EntityUtils.getPoseActor(parent) != null){ } else if(parent != null && isServer && EntityUtils.getPoseActor(parent) != null){
if(!this.geoms.isEmpty()){ if(!this.geoms.isEmpty()){
Vector3d entityPosition = EntityUtils.getPosition(parent); Vector3d entityPosition = EntityUtils.getPosition(parent);
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition)); this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
//
for(String boneName : this.boneHitboxMap.keySet()){ for(String boneName : this.boneHitboxMap.keySet()){
Vector3f bonePosition = EntityUtils.getPoseActor(parent).getBonePosition(boneName); Vector3f bonePosition = EntityUtils.getPoseActor(parent).getBonePosition(boneName);
//
for(HitboxState state : this.boneHitboxMap.get(boneName)){ for(HitboxState state : this.boneHitboxMap.get(boneName)){
DGeom geom = this.stateGeomMap.get(state); if(state == null){
HitboxState shapeStatus = this.geomStateMap.get(geom); throw new IllegalStateException("Geometry not assigned to a hitbox state!");
switch(shapeStatus.shapeType){ }
//
switch(state.shapeType){
case SPHERE: { case SPHERE: {
this.updateSphereShapePosition(collisionEngine,boneName,shapeStatus,bonePosition); this.updateSphereShapePosition(collisionEngine,boneName,state,bonePosition);
} break; } break;
case CAPSULE: { case CAPSULE: {
this.updateCapsuleShapePosition(collisionEngine,boneName,shapeStatus,bonePosition); this.updateCapsuleShapePosition(collisionEngine,boneName,state,bonePosition);
} break; } break;
case STATIC_CAPSULE: { case STATIC_CAPSULE: {
} break; } break;
@ -387,9 +392,7 @@ public class HitboxCollectionState {
//called all subsequent updates to hitbox position //called all subsequent updates to hitbox position
//destroy old capsule //destroy old capsule
this.geomStateMap.remove(geom); this.destroyGeom(collisionEngine, geom);
this.geoms.remove(geom);
CollisionBodyCreation.destroyShape(collisionEngine, geom);
//calculate position between new world point and old world point //calculate position between new world point and old world point
Vector3d bodyPosition = new Vector3d(worldPosition).lerp(previousWorldPos, 0.5); Vector3d bodyPosition = new Vector3d(worldPosition).lerp(previousWorldPos, 0.5);
@ -426,18 +429,14 @@ public class HitboxCollectionState {
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, bodyPosition, worldRotation); PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, bodyPosition, worldRotation);
} else { } else {
//called first time the hitbox updates position //called first time the hitbox updates position
this.geomStateMap.remove(geom); this.destroyGeom(collisionEngine, geom);
this.geoms.remove(geom);
CollisionBodyCreation.destroyShape(collisionEngine, geom);
//create new capsule //create new capsule
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), hitboxState.getHitboxData().getRadius(), length, Collidable.TYPE_OBJECT_BIT); geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), hitboxState.getHitboxData().getRadius(), length, Collidable.TYPE_OBJECT_BIT);
CollisionBodyCreation.attachGeomToBody(collisionEngine,body,geom); CollisionBodyCreation.attachGeomToBody(collisionEngine,body,geom);
} }
//update maps and other variables for next frame //update maps and other variables for next frame
this.stateGeomMap.put(hitboxState,geom); this.registerGeom(geom, hitboxState);
this.geomStateMap.put(geom,hitboxState);
this.geoms.add(geom);
hitboxState.setPreviousWorldPos(worldPosition); hitboxState.setPreviousWorldPos(worldPosition);
} }
@ -560,11 +559,26 @@ public class HitboxCollectionState {
* @param state The state associated with the geom * @param state The state associated with the geom
*/ */
private void registerGeom(DGeom geom, HitboxState state){ private void registerGeom(DGeom geom, HitboxState state){
if(state == null){
throw new IllegalArgumentException("Null hitbox state provided to geometry register!");
}
this.geoms.add(geom); this.geoms.add(geom);
this.geomStateMap.put(geom,state); this.geomStateMap.put(geom,state);
this.stateGeomMap.put(state,geom); this.stateGeomMap.put(state,geom);
} }
/**
* Destroys a geometry
* @param collisionEngine The collision engine for the body
* @param geom The geometry
*/
private void destroyGeom(CollisionEngine collisionEngine, DGeom geom){
HitboxState state = this.geomStateMap.remove(geom);
this.stateGeomMap.remove(state);
this.geoms.remove(geom);
CollisionBodyCreation.destroyShape(collisionEngine, geom);
}
/** /**
* Gets the hitbox type of a given hitbox data * Gets the hitbox type of a given hitbox data
* @param data The data * @param data The data

View File

@ -203,7 +203,11 @@ public class MenuGeneratorsLevelEditor {
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera));
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
Realm realm = Globals.realmManager.getRealms().iterator().next(); Realm realm = Globals.realmManager.getRealms().iterator().next();
Vector3d cursorPos = realm.getCollisionEngine().rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0).add(cursorVerticalOffset); Vector3d cursorPos = realm.getCollisionEngine().rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0);
if(cursorPos == null){
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).mul(-5.0));
}
cursorPos = cursorPos.add(cursorVerticalOffset);
UnitUtils.spawnUnit(realm, cursorPos, unitDefinition.getId()); UnitUtils.spawnUnit(realm, cursorPos, unitDefinition.getId());
})); }));
} }

View File

@ -1,4 +1,4 @@
package electrosphere.server.datacell.physics; package electrosphere.server.collision;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.ode4j.ode.DContactGeom; import org.ode4j.ode.DContactGeom;
@ -14,6 +14,7 @@ import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
import electrosphere.entity.state.life.ServerLifeTree; import electrosphere.entity.state.life.ServerLifeTree;
import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.types.item.ItemUtils; import electrosphere.entity.types.item.ItemUtils;
import electrosphere.logger.LoggerInterface;
/** /**
* Callback for managing collisions on the server * Callback for managing collisions on the server
@ -21,48 +22,106 @@ import electrosphere.entity.types.item.ItemUtils;
public class ServerHitboxResolutionCallback implements CollisionResolutionCallback { public class ServerHitboxResolutionCallback implements CollisionResolutionCallback {
@Override @Override
public void resolve(DContactGeom contactGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) { public void resolve(DContactGeom contactGeom, DGeom impactorGeom, DGeom receiverGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) {
Entity impactorParent = impactor.getParent(); Entity impactorEntity = impactor.getParent();
Entity receiverParent = receiver.getParent(); Entity receiverEntity = receiver.getParent();
HitboxCollectionState impactorState = HitboxCollectionState.getHitboxState(impactorParent); HitboxCollectionState impactorState = HitboxCollectionState.getHitboxState(impactorEntity);
HitboxCollectionState receiverState = HitboxCollectionState.getHitboxState(receiverParent); HitboxCollectionState receiverState = HitboxCollectionState.getHitboxState(receiverEntity);
DGeom impactorGeom = contactGeom.g1;
DGeom receiverGeom = contactGeom.g2;
HitboxState impactorShapeStatus = impactorState.getShapeStatus(impactorGeom); HitboxState impactorShapeStatus = impactorState.getShapeStatus(impactorGeom);
HitboxState receiverShapeStatus = receiverState.getShapeStatus(receiverGeom); HitboxState receiverShapeStatus = receiverState.getShapeStatus(receiverGeom);
//basic error checking
if(impactorEntity == null){
throw new IllegalStateException("Impactor's entity is null");
}
if(receiverEntity == null){
throw new IllegalStateException("Receiver's entity is null");
}
if(!HitboxCollectionState.hasHitboxState(impactorEntity)){
throw new IllegalStateException("Impactor state is null");
}
if(!HitboxCollectionState.hasHitboxState(receiverEntity)){
throw new IllegalStateException("Receiver state is null");
}
if(impactorGeom == null){
throw new IllegalStateException("Impactor geom is null");
}
if(receiverGeom == null){
throw new IllegalStateException("Receiver geom is null");
}
if(!impactorState.getGeometries().contains(impactorGeom)){
String message = "Impactor geom has wrong parent assigned!\n" +
"Problem geom: " + impactorGeom + "\n" +
"All geometries tracked: " + impactorState.getGeometries() + "n\""
;
throw new IllegalStateException(message);
}
if(impactorShapeStatus == null){
String message = "Impactor shape status is null\n" +
"Problem geom: " + impactorGeom + "\n" +
"All geometries tracked: " + impactorState.getGeometries() + "n\""
;
throw new IllegalStateException(message);
}
if(receiverShapeStatus == null){
String message = "Receiver shape status is null\n" +
"Problem geom: " + receiverGeom + "\n" +
"All geometries tracked: " + receiverState.getGeometries() + "n\""
;
throw new IllegalStateException(message);
}
boolean impactorShapeStatusIsNull = impactorShapeStatus == null; boolean impactorShapeStatusIsNull = impactorShapeStatus == null;
boolean receiverShapeStatusIsNull = receiverShapeStatus == null; boolean receiverShapeStatusIsNull = receiverShapeStatus == null;
boolean impactorIsHit = impactorShapeStatus != null && impactorShapeStatus.getType() == HitboxType.HIT; boolean impactorIsHit = impactorShapeStatus != null && impactorShapeStatus.getType() == HitboxType.HIT;
boolean receiverIsHurt = receiverShapeStatus != null && receiverShapeStatus.getType() == HitboxType.HURT; boolean receiverIsHurt = receiverShapeStatus != null && receiverShapeStatus.getType() == HitboxType.HURT;
boolean receiverIsBlock = receiverShapeStatus != null && (receiverShapeStatus.getType() == HitboxType.BLOCK || (receiverShapeStatus.getType() == HitboxType.HIT && receiverShapeStatus.isBlockOverride())); boolean receiverIsBlock = receiverShapeStatus != null && (receiverShapeStatus.getType() == HitboxType.BLOCK || (receiverShapeStatus.getType() == HitboxType.HIT && receiverShapeStatus.isBlockOverride()));
boolean parentsAreDifferent = AttachUtils.getParent(impactorParent) != receiverParent; boolean parentsAreDifferent = AttachUtils.getParent(impactorEntity) != receiverEntity;
boolean impactorCollisionBlocked = false; boolean impactorCollisionBlocked = false;
//check if the impactor thinks it can collide with the receiver //check if the impactor thinks it can collide with the receiver
if(impactorParent != null && ServerAttackTree.getServerAttackTree(impactorParent) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorParent); //
//sword has attack tree
if(impactorEntity != null && ServerAttackTree.getServerAttackTree(impactorEntity) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorEntity);
//
//sword-on-sword check
//if we collide with the creature directly //if we collide with the creature directly
if(!impactorAttackTree.canCollideEntity(receiverParent)){ if(!impactorAttackTree.canCollideEntity(receiverEntity)){
impactorCollisionBlocked = true; impactorCollisionBlocked = true;
} }
//
//sword-on-creature check
//if we collide with an item attached to the creature //if we collide with an item attached to the creature
if(AttachUtils.hasParent(receiverParent) && !impactorAttackTree.canCollideEntity(AttachUtils.getParent(receiverParent))){ if(AttachUtils.hasParent(receiverEntity) && !impactorAttackTree.canCollideEntity(AttachUtils.getParent(receiverEntity))){
impactorCollisionBlocked = true; impactorCollisionBlocked = true;
} }
} else if(impactorParent != null && AttachUtils.hasParent(impactorParent) && AttachUtils.getParent(impactorParent) != null && ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorParent)) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorParent)); //
//creature has attack tree
} else if(impactorEntity != null && AttachUtils.hasParent(impactorEntity) && AttachUtils.getParent(impactorEntity) != null && ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity)) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity));
//
//creature-on-sword check
//if we collide with the creature directly //if we collide with the creature directly
if(!impactorAttackTree.canCollideEntity(receiverParent)){ if(!impactorAttackTree.canCollideEntity(receiverEntity)){
impactorCollisionBlocked = true; impactorCollisionBlocked = true;
} }
//
//creature-on-creature check
//if we collide with an item attached to the creature //if we collide with an item attached to the creature
if(AttachUtils.hasParent(receiverParent) && !impactorAttackTree.canCollideEntity(AttachUtils.getParent(receiverParent))){ if(AttachUtils.hasParent(receiverEntity) && !impactorAttackTree.canCollideEntity(AttachUtils.getParent(receiverEntity))){
impactorCollisionBlocked = true; impactorCollisionBlocked = true;
} }
} }
//
//check if is damage event //check if is damage event
boolean isDamageEvent = boolean isDamageEvent =
!impactorShapeStatusIsNull && !impactorShapeStatusIsNull &&
@ -73,6 +132,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
!impactorCollisionBlocked !impactorCollisionBlocked
; ;
//
//check if is block event //check if is block event
boolean isBlockEvent = boolean isBlockEvent =
!impactorShapeStatusIsNull && !impactorShapeStatusIsNull &&
@ -94,70 +154,79 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
if(isDamageEvent){ if(isDamageEvent){
//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(impactorParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM); boolean isItem = ItemUtils.isItem(impactorEntity);
Entity hitboxAttachParent = AttachUtils.getParent(impactorParent); Entity hitboxAttachParent = AttachUtils.getParent(impactorEntity);
// //
//handle receiver //handle receiver
if(isItem){ if(isItem){
if(hitboxAttachParent != receiverParent){ if(hitboxAttachParent != receiverEntity){
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverParent); ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverEntity);
serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent); serverLifeTree.addCollisionEvent(impactorEntity, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent);
} }
} }
// //
//handle attacker //handle attacker
this.handleAttackerCollision(impactorParent,receiverParent); this.handleAttackerCollision(impactorEntity,receiverEntity);
} }
if(isBlockEvent){ if(isBlockEvent){
// //
//handle receiver //handle receiver
boolean receiverIsItem = ItemUtils.isItem(receiverParent); boolean receiverIsItem = ItemUtils.isItem(receiverEntity);
boolean receiverHasParent = AttachUtils.hasParent(receiverParent); boolean receiverHasParent = AttachUtils.hasParent(receiverEntity);
if(receiverIsItem && receiverHasParent){ if(receiverIsItem && receiverHasParent){
//item is equipped to something //item is equipped to something
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(AttachUtils.getParent(receiverParent)); ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(AttachUtils.getParent(receiverEntity));
if(serverLifeTree != null){ if(serverLifeTree != null){
serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent); serverLifeTree.addCollisionEvent(impactorEntity, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent);
} }
} else { } else {
//attacking an item that is not equipped to anything //attacking an item that is not equipped to anything
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverParent); ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverEntity);
if(serverLifeTree != null){ if(serverLifeTree != null){
serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent); serverLifeTree.addCollisionEvent(impactorEntity, impactorShapeStatus, receiverShapeStatus, worldPos, isDamageEvent, isBlockEvent);
} }
} }
// //
//handle attacker //handle attacker
this.handleAttackerCollision(impactorParent,receiverParent); this.handleAttackerCollision(impactorEntity,receiverEntity);
} }
} }
/** /**
* Handles collision tracking from the impactor's side * Handles collision tracking from the impactor's side
* @param impactorParent The impactor hitbox's parent entity * @param impactorEntity The impactor hitbox's parent entity
* @param receiverParent The receiver hitbox's parent entity * @param receiverParent The receiver hitbox's parent entity
*/ */
private void handleAttackerCollision(Entity impactorParent, Entity receiverParent){ private void handleAttackerCollision(Entity impactorEntity, Entity receiverEntity){
boolean receiverIsItem = ItemUtils.isItem(receiverParent); boolean receiverIsItem = ItemUtils.isItem(receiverEntity);
boolean receiverHasParent = AttachUtils.hasParent(receiverParent); boolean receiverHasParent = AttachUtils.hasParent(receiverEntity);
if(impactorParent != null && ServerAttackTree.getServerAttackTree(impactorParent) != null){ //
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorParent); //The sword has the attack tree
impactorAttackTree.collideEntity(receiverParent); if(impactorEntity != null && ServerAttackTree.getServerAttackTree(impactorEntity) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorEntity);
impactorAttackTree.collideEntity(receiverEntity);
//if the receiver is an item that is equipped, collide with parent too //if the receiver is an item that is equipped, collide with parent too
if(receiverIsItem && receiverHasParent){ if(receiverIsItem && receiverHasParent){
impactorAttackTree.collideEntity(AttachUtils.getParent(receiverParent)); impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity));
} else if(receiverHasParent){
LoggerInterface.loggerEngine.WARNING("Potentially unhandled case with server collision!");
} }
} else if(impactorParent != null && AttachUtils.hasParent(impactorParent) && AttachUtils.getParent(impactorParent) != null && ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorParent)) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorParent)); //
impactorAttackTree.collideEntity(receiverParent); //The parent of the sword has the attack tree
} else if(impactorEntity != null && AttachUtils.hasParent(impactorEntity) && AttachUtils.getParent(impactorEntity) != null && ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity)) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity));
impactorAttackTree.collideEntity(receiverEntity);
//if the receiver is an item that is equipped, collide with parent too //if the receiver is an item that is equipped, collide with parent too
if(receiverIsItem && receiverHasParent){ if(receiverIsItem && receiverHasParent){
impactorAttackTree.collideEntity(AttachUtils.getParent(receiverParent)); impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity));
} else if(receiverHasParent){
LoggerInterface.loggerEngine.WARNING("Potentially unhandled case with server collision!");
} }
} }
} }

View File

@ -11,8 +11,8 @@ import electrosphere.collision.hitbox.HitboxManager;
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.collision.ServerHitboxResolutionCallback;
import electrosphere.server.content.ServerContentManager; import electrosphere.server.content.ServerContentManager;
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