hitbox collision debounce work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
4cf34d162c
commit
1ca9c60640
@ -553,6 +553,7 @@ Movement tweaks
|
|||||||
Hitbox support offsets now
|
Hitbox support offsets now
|
||||||
Multiple hitboxes per bone
|
Multiple hitboxes per bone
|
||||||
Potential fix for client concurrency issue
|
Potential fix for client concurrency issue
|
||||||
|
Debounce attack collisions
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
@ -561,6 +562,8 @@ Potential fix for client concurrency issue
|
|||||||
BIG BIG BIG BIG IMMEDIATE TO DO:
|
BIG BIG BIG BIG IMMEDIATE TO DO:
|
||||||
always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible
|
always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible
|
||||||
|
|
||||||
|
Rename "BehaviorTree" to be "Component" (what it actually is)
|
||||||
|
|
||||||
Ability to fully reload game engine state without exiting client
|
Ability to fully reload game engine state without exiting client
|
||||||
- Back out to main menu and load a new level without any values persisting
|
- Back out to main menu and load a new level without any values persisting
|
||||||
- Receive a teleport packet from server and flush all game state before requesting state from server again
|
- Receive a teleport packet from server and flush all game state before requesting state from server again
|
||||||
|
|||||||
@ -119,7 +119,7 @@ public class HitboxAudioService {
|
|||||||
if(ItemUtils.isWeapon(senderEntity)){
|
if(ItemUtils.isWeapon(senderEntity)){
|
||||||
if(CreatureUtils.isCreature(receiverEntity)){
|
if(CreatureUtils.isCreature(receiverEntity)){
|
||||||
if(isBlockSound){
|
if(isBlockSound){
|
||||||
return this.getWeaponOnCreature();
|
return this.getWeaponOnBlock();
|
||||||
} else if(isDamageSound){
|
} else if(isDamageSound){
|
||||||
return this.getWeaponOnCreature();
|
return this.getWeaponOnCreature();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,7 @@ import electrosphere.renderer.actor.Actor;
|
|||||||
import electrosphere.server.datacell.Realm;
|
import electrosphere.server.datacell.Realm;
|
||||||
import electrosphere.util.math.MathUtils;
|
import electrosphere.util.math.MathUtils;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
@ -82,6 +83,11 @@ public class ServerAttackTree implements BehaviorTree {
|
|||||||
String projectileToFire = null;
|
String projectileToFire = null;
|
||||||
String attackingPoint = null;
|
String attackingPoint = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of entities that have collided with the current attack
|
||||||
|
*/
|
||||||
|
List<Entity> collidedEntities = new LinkedList<Entity>();
|
||||||
|
|
||||||
//The state transition util
|
//The state transition util
|
||||||
StateTransitionUtil stateTransitionUtil;
|
StateTransitionUtil stateTransitionUtil;
|
||||||
|
|
||||||
@ -190,14 +196,14 @@ public class ServerAttackTree implements BehaviorTree {
|
|||||||
//figure out attack type we should be doing
|
//figure out attack type we should be doing
|
||||||
String attackType = getAttackType();
|
String attackType = getAttackType();
|
||||||
//if we can attack, setup doing so
|
//if we can attack, setup doing so
|
||||||
if(canAttack(attackType)){
|
if(this.canAttack(attackType)){
|
||||||
setAttackMoveTypeActive(attackType);
|
this.setAttackMoveTypeActive(attackType);
|
||||||
currentMoveset = getMoveset(attackType);
|
currentMoveset = this.getMoveset(attackType);
|
||||||
if(currentMoveset != null){
|
if(currentMoveset != null){
|
||||||
if(currentMove == null){
|
if(currentMove == null){
|
||||||
currentMove = currentMoveset.get(0);
|
currentMove = currentMoveset.get(0);
|
||||||
} else {
|
} else {
|
||||||
currentMove = getNextMove(currentMoveset,currentMove.getNextMoveId());
|
currentMove = this.getNextMove(currentMoveset,currentMove.getNextMoveId());
|
||||||
}
|
}
|
||||||
if(currentMove != null){
|
if(currentMove != null){
|
||||||
firesProjectile = currentMove.getFiresProjectile();
|
firesProjectile = currentMove.getFiresProjectile();
|
||||||
@ -206,18 +212,20 @@ public class ServerAttackTree implements BehaviorTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//set initial stuff (this alerts the client as well)
|
//set initial stuff (this alerts the client as well)
|
||||||
setCurrentMoveId(currentMove.getAttackMoveId());
|
this.setCurrentMoveId(currentMove.getAttackMoveId());
|
||||||
|
|
||||||
//start tree
|
//start tree
|
||||||
if(currentMove.getWindupState() != null){
|
if(currentMove.getWindupState() != null){
|
||||||
setState(AttackTreeState.WINDUP);
|
this.setState(AttackTreeState.WINDUP);
|
||||||
} else if(currentMove.getAttackState() != null){
|
} else if(currentMove.getAttackState() != null){
|
||||||
setState(AttackTreeState.ATTACK);
|
this.setState(AttackTreeState.ATTACK);
|
||||||
} else {
|
} else {
|
||||||
LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Trying to start attacking tree, but current move does not have windup or attack states defined!"));
|
LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Trying to start attacking tree, but current move does not have windup or attack states defined!"));
|
||||||
}
|
}
|
||||||
//intuit can hold from presence of windup anim
|
//intuit can hold from presence of windup anim
|
||||||
currentMoveCanHold = currentMove.getHoldState() != null;
|
currentMoveCanHold = currentMove.getHoldState() != null;
|
||||||
|
//clear collided list
|
||||||
|
this.collidedEntities.clear();
|
||||||
//stop movement tree
|
//stop movement tree
|
||||||
if(parent.containsKey(EntityDataStrings.SERVER_MOVEMENT_BT)){
|
if(parent.containsKey(EntityDataStrings.SERVER_MOVEMENT_BT)){
|
||||||
BehaviorTree movementTree = CreatureUtils.serverGetEntityMovementTree(parent);
|
BehaviorTree movementTree = CreatureUtils.serverGetEntityMovementTree(parent);
|
||||||
@ -229,12 +237,15 @@ public class ServerAttackTree implements BehaviorTree {
|
|||||||
EntityUtils.getRotation(parent).rotationTo(MathUtils.getOriginVector(), new Vector3d(movementVector.x,movementVector.y,movementVector.z));
|
EntityUtils.getRotation(parent).rotationTo(MathUtils.getOriginVector(), new Vector3d(movementVector.x,movementVector.y,movementVector.z));
|
||||||
frameCurrent = 0;
|
frameCurrent = 0;
|
||||||
} else {
|
} else {
|
||||||
setState(AttackTreeState.IDLE);
|
this.setState(AttackTreeState.IDLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases the tree from holding its animation
|
||||||
|
*/
|
||||||
public void release(){
|
public void release(){
|
||||||
stillHold = false;
|
stillHold = false;
|
||||||
}
|
}
|
||||||
@ -429,10 +440,18 @@ public class ServerAttackTree implements BehaviorTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a network message to the tree
|
||||||
|
* @param networkMessage The network message
|
||||||
|
*/
|
||||||
public void addNetworkMessage(EntityMessage networkMessage) {
|
public void addNetworkMessage(EntityMessage networkMessage) {
|
||||||
networkMessageQueue.add(networkMessage);
|
networkMessageQueue.add(networkMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current attack type
|
||||||
|
* @return The current attack type
|
||||||
|
*/
|
||||||
String getAttackType(){
|
String getAttackType(){
|
||||||
String rVal = null;
|
String rVal = null;
|
||||||
if(ServerEquipState.hasEquipState(parent)){
|
if(ServerEquipState.hasEquipState(parent)){
|
||||||
@ -464,7 +483,7 @@ public class ServerAttackTree implements BehaviorTree {
|
|||||||
* @param attackType The type of attack to perform
|
* @param attackType The type of attack to perform
|
||||||
* @return true if it can attack, false otherwise
|
* @return true if it can attack, false otherwise
|
||||||
*/
|
*/
|
||||||
boolean canAttack(String attackType){
|
private boolean canAttack(String attackType){
|
||||||
boolean rVal = true;
|
boolean rVal = true;
|
||||||
if(attackType == null){
|
if(attackType == null){
|
||||||
return false;
|
return false;
|
||||||
@ -503,7 +522,13 @@ public class ServerAttackTree implements BehaviorTree {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttackMove getNextMove(List<AttackMove> moveset, String nextMoveId){
|
/**
|
||||||
|
* Gets the next attack move
|
||||||
|
* @param moveset The moveset
|
||||||
|
* @param nextMoveId The next move's id
|
||||||
|
* @return The next move if it exists, null otherwise
|
||||||
|
*/
|
||||||
|
private AttackMove getNextMove(List<AttackMove> moveset, String nextMoveId){
|
||||||
AttackMove rVal = null;
|
AttackMove rVal = null;
|
||||||
for(AttackMove move : moveset){
|
for(AttackMove move : moveset){
|
||||||
if(move.getAttackMoveId().equals(nextMoveId)){
|
if(move.getAttackMoveId().equals(nextMoveId)){
|
||||||
@ -538,6 +563,23 @@ public class ServerAttackTree implements BehaviorTree {
|
|||||||
public List<AttackMove> getMoveset(String attackType){
|
public List<AttackMove> getMoveset(String attackType){
|
||||||
return (List<AttackMove>)parent.getData(attackType);
|
return (List<AttackMove>)parent.getData(attackType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the target can be collided with
|
||||||
|
* @param target The target
|
||||||
|
* @return true if can be collided with, false otherwise (ie it has already collided)
|
||||||
|
*/
|
||||||
|
public boolean canCollideEntity(Entity target){
|
||||||
|
return !this.collidedEntities.contains(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets that the current attack has collided with the provided entity
|
||||||
|
* @param target The target entity
|
||||||
|
*/
|
||||||
|
public void collideEntity(Entity target){
|
||||||
|
this.collidedEntities.add(target);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p> Automatically generated </p>
|
* <p> Automatically generated </p>
|
||||||
|
|||||||
@ -7,12 +7,22 @@ import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem;
|
|||||||
import electrosphere.entity.EntityDataStrings;
|
import electrosphere.entity.EntityDataStrings;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||||
|
import electrosphere.net.parser.net.message.CombatMessage;
|
||||||
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
||||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||||
import electrosphere.entity.state.life.ClientLifeTree.LifeStateEnum;
|
import electrosphere.entity.state.life.ClientLifeTree.LifeStateEnum;
|
||||||
|
import electrosphere.entity.types.item.ItemUtils;
|
||||||
|
import electrosphere.game.data.collidable.HitboxData;
|
||||||
import electrosphere.game.data.creature.type.HealthSystem;
|
import electrosphere.game.data.creature.type.HealthSystem;
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.net.synchronization.annotation.SyncedField;
|
import electrosphere.net.synchronization.annotation.SyncedField;
|
||||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||||
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
|
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
|
||||||
@ -48,8 +58,12 @@ public class ServerLifeTree implements BehaviorTree {
|
|||||||
//the current iframe count
|
//the current iframe count
|
||||||
int iFrameCurrent = 0;
|
int iFrameCurrent = 0;
|
||||||
|
|
||||||
|
//accumulates collisions and determines if the parent takes damage or blocks them
|
||||||
|
List<CollisionEvent> collisionAccumulator = new LinkedList<CollisionEvent>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void simulate(float deltaTime) {
|
public void simulate(float deltaTime) {
|
||||||
|
this.handleAccumulatedCollisions();
|
||||||
switch(state){
|
switch(state){
|
||||||
case ALIVE: {
|
case ALIVE: {
|
||||||
if(iFrameCurrent > 0){
|
if(iFrameCurrent > 0){
|
||||||
@ -101,6 +115,85 @@ public class ServerLifeTree implements BehaviorTree {
|
|||||||
return this.state == LifeStateEnum.ALIVE;
|
return this.state == LifeStateEnum.ALIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the collisions that have been accumulated in this tree
|
||||||
|
*/
|
||||||
|
private void handleAccumulatedCollisions(){
|
||||||
|
int numCollisions = 0;
|
||||||
|
if(collisionAccumulator.size() > 0){
|
||||||
|
//get the blocked entities
|
||||||
|
List<Entity> blockedEntities = new LinkedList<Entity>();
|
||||||
|
for(CollisionEvent event : collisionAccumulator){
|
||||||
|
if(event.isBlock && !blockedEntities.contains(event.source)){
|
||||||
|
//don't allow multiple hits per collision
|
||||||
|
blockedEntities.add(event.source);
|
||||||
|
|
||||||
|
//tracking
|
||||||
|
numCollisions++;
|
||||||
|
|
||||||
|
//tell clients an impact just happened
|
||||||
|
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(
|
||||||
|
CombatMessage.constructserverReportHitboxCollisionMessage(
|
||||||
|
event.source.getId(),
|
||||||
|
parent.getId(),
|
||||||
|
Globals.timekeeper.getNumberOfSimFramesElapsed(),
|
||||||
|
event.sourceHitboxData.getHitboxData().getType(),
|
||||||
|
HitboxData.HITBOX_TYPE_BLOCK_CONNECTED
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(CollisionEvent event : collisionAccumulator){
|
||||||
|
if(event.isDamage && !blockedEntities.contains(event.source)){
|
||||||
|
//don't allow multiple hits per collision
|
||||||
|
blockedEntities.add(event.source);
|
||||||
|
|
||||||
|
//tracking
|
||||||
|
numCollisions++;
|
||||||
|
|
||||||
|
//tell clients an impact just happened
|
||||||
|
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(
|
||||||
|
CombatMessage.constructserverReportHitboxCollisionMessage(
|
||||||
|
event.source.getId(),
|
||||||
|
parent.getId(),
|
||||||
|
Globals.timekeeper.getNumberOfSimFramesElapsed(),
|
||||||
|
event.sourceHitboxData.getHitboxData().getType(),
|
||||||
|
event.parentHitboxData.getHitboxData().getType()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
//do damage calculation
|
||||||
|
int damage = ItemUtils.getWeaponDataRaw(event.source).getDamage();
|
||||||
|
this.damage(damage);
|
||||||
|
if(!this.isAlive()){
|
||||||
|
throw new UnsupportedOperationException("Reviving not implemented yet!");
|
||||||
|
// Realm entityRealm = Globals.realmManager.getEntityRealm(receiverParent);
|
||||||
|
// EntityUtils.getPosition(receiverParent).set(entityRealm.getSpawnPoint());
|
||||||
|
// serverLifeTree.revive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collisionAccumulator.clear();
|
||||||
|
}
|
||||||
|
if(numCollisions > 0){
|
||||||
|
LoggerInterface.loggerEngine.DEBUG("Server life tree handled: " + numCollisions + " unique collisions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a collision event to the life tree
|
||||||
|
* @param collisionSource The collision source
|
||||||
|
* @param position The position of the collision event
|
||||||
|
* @param sourceHitboxData The hitbox data for the source of the collision
|
||||||
|
* @param parentHitboxData The hitbox data for the parent of the tree
|
||||||
|
* @param isDamage True if this is a damage event
|
||||||
|
* @param isBlock True if this is a block event
|
||||||
|
*/
|
||||||
|
public void addCollisionEvent(Entity collisionSource, HitboxState sourceHitboxData, HitboxState parentHitboxData, Vector3d position, boolean isDamage, boolean isBlock){
|
||||||
|
CollisionEvent collisionEvent = new CollisionEvent(collisionSource, sourceHitboxData, parentHitboxData, isDamage, isBlock);
|
||||||
|
this.collisionAccumulator.add(collisionEvent);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p> Automatically generated </p>
|
* <p> Automatically generated </p>
|
||||||
* <p>
|
* <p>
|
||||||
@ -192,4 +285,52 @@ public class ServerLifeTree implements BehaviorTree {
|
|||||||
return (ServerLifeTree)entity.getData(EntityDataStrings.TREE_SERVERLIFETREE);
|
return (ServerLifeTree)entity.getData(EntityDataStrings.TREE_SERVERLIFETREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single collision event
|
||||||
|
*/
|
||||||
|
public static class CollisionEvent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The source of the collision event
|
||||||
|
*/
|
||||||
|
Entity source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hitbox data for the source of the collision
|
||||||
|
*/
|
||||||
|
HitboxState sourceHitboxData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hitbox data for the parent of the tree
|
||||||
|
*/
|
||||||
|
HitboxState parentHitboxData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this is a damage event
|
||||||
|
*/
|
||||||
|
boolean isDamage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this is a block event
|
||||||
|
*/
|
||||||
|
boolean isBlock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param source The source of the collision
|
||||||
|
* @param sourceHitboxData The hitbox data for the source of the collision
|
||||||
|
* @param parentHitboxData The hitbox data for the parent of the tree
|
||||||
|
* @param isDamage True if this is a damage event
|
||||||
|
* @param isBlock True if this is a block event
|
||||||
|
*/
|
||||||
|
public CollisionEvent(Entity source, HitboxState sourceHitboxData, HitboxState parentHitboxData, boolean isDamage, boolean isBlock){
|
||||||
|
this.source = source;
|
||||||
|
this.sourceHitboxData = sourceHitboxData;
|
||||||
|
this.parentHitboxData = parentHitboxData;
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
this.isBlock = isBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,19 +6,14 @@ import org.ode4j.ode.DGeom;
|
|||||||
|
|
||||||
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
|
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
|
||||||
import electrosphere.collision.collidable.Collidable;
|
import electrosphere.collision.collidable.Collidable;
|
||||||
import electrosphere.engine.Globals;
|
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.state.attack.ServerAttackTree;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
||||||
import electrosphere.entity.state.life.ServerLifeTree;
|
import electrosphere.entity.state.life.ServerLifeTree;
|
||||||
import electrosphere.entity.state.movement.ProjectileTree;
|
|
||||||
import electrosphere.entity.types.attach.AttachUtils;
|
import electrosphere.entity.types.attach.AttachUtils;
|
||||||
import electrosphere.entity.types.creature.CreatureUtils;
|
|
||||||
import electrosphere.entity.types.item.ItemUtils;
|
import electrosphere.entity.types.item.ItemUtils;
|
||||||
import electrosphere.game.data.collidable.HitboxData;
|
|
||||||
import electrosphere.net.parser.net.message.CombatMessage;
|
|
||||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for managing collisions on the server
|
* Callback for managing collisions on the server
|
||||||
@ -43,22 +38,49 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
|||||||
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(impactorParent) != receiverParent;
|
||||||
|
boolean impactorCollisionBlocked = false;
|
||||||
|
|
||||||
//currently, impactor needs to be an item, and the receiver must not be an item
|
//check if the impactor thinks it can collide with the receiver
|
||||||
|
if(impactorParent != null && ServerAttackTree.getServerAttackTree(impactorParent) != null){
|
||||||
|
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorParent);
|
||||||
|
//if we collide with the creature directly
|
||||||
|
if(!impactorAttackTree.canCollideEntity(receiverParent)){
|
||||||
|
impactorCollisionBlocked = true;
|
||||||
|
}
|
||||||
|
//if we collide with an item attached to the creature
|
||||||
|
if(AttachUtils.hasParent(receiverParent) && !impactorAttackTree.canCollideEntity(AttachUtils.getParent(receiverParent))){
|
||||||
|
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));
|
||||||
|
//if we collide with the creature directly
|
||||||
|
if(!impactorAttackTree.canCollideEntity(receiverParent)){
|
||||||
|
impactorCollisionBlocked = true;
|
||||||
|
}
|
||||||
|
//if we collide with an item attached to the creature
|
||||||
|
if(AttachUtils.hasParent(receiverParent) && !impactorAttackTree.canCollideEntity(AttachUtils.getParent(receiverParent))){
|
||||||
|
impactorCollisionBlocked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if is damage event
|
||||||
boolean isDamageEvent =
|
boolean isDamageEvent =
|
||||||
!impactorShapeStatusIsNull &&
|
!impactorShapeStatusIsNull &&
|
||||||
!receiverShapeStatusIsNull &&
|
!receiverShapeStatusIsNull &&
|
||||||
impactorIsHit &&
|
impactorIsHit &&
|
||||||
receiverIsHurt &&
|
receiverIsHurt &&
|
||||||
parentsAreDifferent
|
parentsAreDifferent &&
|
||||||
|
!impactorCollisionBlocked
|
||||||
;
|
;
|
||||||
|
|
||||||
|
//check if is block event
|
||||||
boolean isBlockEvent =
|
boolean isBlockEvent =
|
||||||
!impactorShapeStatusIsNull &&
|
!impactorShapeStatusIsNull &&
|
||||||
!receiverShapeStatusIsNull &&
|
!receiverShapeStatusIsNull &&
|
||||||
impactorIsHit &&
|
impactorIsHit &&
|
||||||
receiverIsBlock &&
|
receiverIsBlock &&
|
||||||
parentsAreDifferent
|
parentsAreDifferent &&
|
||||||
|
!impactorCollisionBlocked
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@ -75,62 +97,68 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
|||||||
boolean isItem = ItemUtils.isItem(impactorParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM);
|
boolean isItem = ItemUtils.isItem(impactorParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM);
|
||||||
Entity hitboxAttachParent = AttachUtils.getParent(impactorParent);
|
Entity hitboxAttachParent = AttachUtils.getParent(impactorParent);
|
||||||
|
|
||||||
//tell clients an impact just happened
|
//
|
||||||
DataCellSearchUtils.getEntityDataCell(receiverParent).broadcastNetworkMessage(
|
//handle receiver
|
||||||
CombatMessage.constructserverReportHitboxCollisionMessage(
|
|
||||||
impactorParent.getId(),
|
|
||||||
receiverParent.getId(),
|
|
||||||
Globals.timekeeper.getNumberOfSimFramesElapsed(),
|
|
||||||
impactorShapeStatus.getHitboxData().getType(),
|
|
||||||
receiverShapeStatus.getHitboxData().getType()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if(isItem){
|
if(isItem){
|
||||||
if(hitboxAttachParent != receiverParent){
|
if(hitboxAttachParent != receiverParent){
|
||||||
int damage = ItemUtils.getWeaponDataRaw(impactorParent).getDamage();
|
|
||||||
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverParent);
|
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverParent);
|
||||||
serverLifeTree.damage(damage);
|
serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, localPosition, isDamageEvent, isBlockEvent);
|
||||||
if(!serverLifeTree.isAlive()){
|
|
||||||
throw new UnsupportedOperationException("Reviving not implemented yet!");
|
|
||||||
// Realm entityRealm = Globals.realmManager.getEntityRealm(receiverParent);
|
|
||||||
// EntityUtils.getPosition(receiverParent).set(entityRealm.getSpawnPoint());
|
|
||||||
// serverLifeTree.revive();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int damage = 0;
|
|
||||||
//for entities using attacktree
|
|
||||||
if(CreatureUtils.serverGetAttackTree(impactorParent) != null){
|
|
||||||
damage = ItemUtils.getWeaponDataRaw(impactorParent).getDamage();
|
|
||||||
} else {
|
|
||||||
//for entities using shooter tree
|
|
||||||
if(ProjectileTree.getProjectileTree(impactorParent) != null){
|
|
||||||
damage = (int)ProjectileTree.getProjectileTree(impactorParent).getDamage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverParent);
|
|
||||||
serverLifeTree.damage(damage);
|
|
||||||
if(!serverLifeTree.isAlive()){
|
|
||||||
throw new UnsupportedOperationException("Reviving not implemented yet!");
|
|
||||||
// Realm entityRealm = Globals.realmManager.getEntityRealm(receiverParent);
|
|
||||||
// EntityUtils.getPosition(receiverParent).set(entityRealm.getSpawnPoint());
|
|
||||||
// serverLifeTree.revive();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//handle attacker
|
||||||
|
this.handleAttackerCollision(impactorParent,receiverParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isBlockEvent){
|
if(isBlockEvent){
|
||||||
//tell clients an impact just happened
|
//
|
||||||
DataCellSearchUtils.getEntityDataCell(receiverParent).broadcastNetworkMessage(
|
//handle receiver
|
||||||
CombatMessage.constructserverReportHitboxCollisionMessage(
|
boolean receiverIsItem = ItemUtils.isItem(receiverParent);
|
||||||
impactorParent.getId(),
|
boolean receiverHasParent = AttachUtils.hasParent(receiverParent);
|
||||||
receiverParent.getId(),
|
if(receiverIsItem && receiverHasParent){
|
||||||
Globals.timekeeper.getNumberOfSimFramesElapsed(),
|
//item is equipped to something
|
||||||
impactorShapeStatus.getHitboxData().getType(),
|
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(AttachUtils.getParent(receiverParent));
|
||||||
HitboxData.HITBOX_TYPE_BLOCK_CONNECTED //TODO: more proper block override handling
|
if(serverLifeTree != null){
|
||||||
)
|
serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, localPosition, isDamageEvent, isBlockEvent);
|
||||||
);
|
}
|
||||||
|
} else {
|
||||||
|
//attacking an item that is not equipped to anything
|
||||||
|
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(receiverParent);
|
||||||
|
if(serverLifeTree != null){
|
||||||
|
serverLifeTree.addCollisionEvent(impactorParent, impactorShapeStatus, receiverShapeStatus, localPosition, isDamageEvent, isBlockEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//handle attacker
|
||||||
|
this.handleAttackerCollision(impactorParent,receiverParent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles collision tracking from the impactor's side
|
||||||
|
* @param impactorParent The impactor hitbox's parent entity
|
||||||
|
* @param receiverParent The receiver hitbox's parent entity
|
||||||
|
*/
|
||||||
|
private void handleAttackerCollision(Entity impactorParent, Entity receiverParent){
|
||||||
|
boolean receiverIsItem = ItemUtils.isItem(receiverParent);
|
||||||
|
boolean receiverHasParent = AttachUtils.hasParent(receiverParent);
|
||||||
|
|
||||||
|
if(impactorParent != null && ServerAttackTree.getServerAttackTree(impactorParent) != null){
|
||||||
|
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorParent);
|
||||||
|
impactorAttackTree.collideEntity(receiverParent);
|
||||||
|
//if the receiver is an item that is equipped, collide with parent too
|
||||||
|
if(receiverIsItem && receiverHasParent){
|
||||||
|
impactorAttackTree.collideEntity(AttachUtils.getParent(receiverParent));
|
||||||
|
}
|
||||||
|
} 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);
|
||||||
|
//if the receiver is an item that is equipped, collide with parent too
|
||||||
|
if(receiverIsItem && receiverHasParent){
|
||||||
|
impactorAttackTree.collideEntity(AttachUtils.getParent(receiverParent));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user