diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 251aff42..eed965af 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1437,6 +1437,9 @@ GriddedDataCellTrackingData created Reduce allocations in GriddedDataCellManager methods that loop cells Implement max distance for queueing for simulation Client hitbox body destruction based on distance from player (for performance) +ServerEntityUtils move entity function properly transfers entity tags now +Fix ServerAttackTree freezing bug +Fix visually attaching item on server creating item at 0,0,0 on init (thereby creating a new datacell if its not nearby) diff --git a/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java b/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java index b73ae40b..bda1b6aa 100644 --- a/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java +++ b/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java @@ -97,9 +97,9 @@ public class StateTransitionUtil { LoggerInterface.loggerEngine.DEBUG("Skipping state " + stateEnum + " because there is not a state registered to that enum value!"); } else { if(this.isServer){ - simulateServerState(this.parent,state); + this.simulateServerState(this.parent,state); } else { - simulateClientState(this.parent,state); + this.simulateClientState(this.parent,state); } } } diff --git a/src/main/java/electrosphere/entity/scene/Scene.java b/src/main/java/electrosphere/entity/scene/Scene.java index a2b2070b..c4164e2b 100644 --- a/src/main/java/electrosphere/entity/scene/Scene.java +++ b/src/main/java/electrosphere/entity/scene/Scene.java @@ -32,6 +32,11 @@ public class Scene { */ Map> tagEntityMap; + /** + * The map of entity -> tags that entity is registered to + */ + Map> entityTagMap; + /** * The list of behavior trees */ @@ -50,6 +55,7 @@ public class Scene { entityIdMap = new HashMap(); tagEntityMap = new HashMap>(); behaviorTreeList = new LinkedList(); + entityTagMap = new HashMap>(); tagEntityMap.put(EntityTags.BONE_ATTACHED, new HashSet()); tagEntityMap.put(EntityTags.COLLIDABLE, new HashSet()); tagEntityMap.put(EntityTags.SPRINTABLE, new HashSet()); @@ -95,6 +101,16 @@ public class Scene { newEntityList.add(e); tagEntityMap.put(tag,newEntityList); } + if(this.entityTagMap.containsKey(e)){ + List tagList = this.entityTagMap.get(e); + if(!tagList.contains(tag)){ + tagList.add(tag); + } + } else { + List tagList = new LinkedList(); + tagList.add(tag); + this.entityTagMap.put(e, tagList); + } lock.unlock(); } @@ -121,6 +137,10 @@ public class Scene { public void removeEntityFromTag(Entity e, String tag){ lock.lock(); tagEntityMap.get(tag).remove(e); + if(this.entityTagMap.containsKey(e)){ + List tagList = this.entityTagMap.get(e); + tagList.remove(tag); + } lock.unlock(); } @@ -133,9 +153,30 @@ public class Scene { for(String key : tagEntityMap.keySet()){ tagEntityMap.get(key).remove(e); } + this.entityTagMap.remove(e); entityIdMap.remove(e.getId()); lock.unlock(); } + + /** + * Extracts all tags this entity is registered to + * @param e The entity + * @return The list of tags this entity is registered to + */ + public List extractTags(Entity e){ + return this.entityTagMap.get(e); + } + + /** + * Registers an entity to a collection of tags + * @param e The entity + * @param tags The list of tags + */ + public void registerEntityToTags(Entity e, List tags){ + for(String tag : tags){ + this.registerEntityToTag(e, tag); + } + } /** * Recursively deregisters an entity and all entities attached via AttachUtils diff --git a/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java b/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java index f1cac8b6..f034c234 100644 --- a/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java +++ b/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java @@ -129,9 +129,9 @@ public class ServerAttackTree implements BehaviorTree { }, () -> { if(currentMoveCanHold && stillHold){ - setState(AttackTreeState.HOLD); + this.setState(AttackTreeState.HOLD); } else { - setState(AttackTreeState.ATTACK); + this.setState(AttackTreeState.ATTACK); } this.stateTransitionUtil.interrupt(AttackTreeState.WINDUP); } @@ -227,7 +227,7 @@ public class ServerAttackTree implements BehaviorTree { currentWeapon = null; attackingPoint = null; //figure out attack type we should be doing - String attackType = getAttackType(); + String attackType = this.getAttackType(); //if we can attack, setup doing so if(this.canAttack(attackType)){ this.setAttackMoveTypeActive(attackType); diff --git a/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java b/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java index 85f0b480..a76b43fc 100644 --- a/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java +++ b/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java @@ -25,6 +25,7 @@ import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityTags; +import electrosphere.entity.EntityUtils; import electrosphere.entity.ServerEntityUtils; import electrosphere.net.synchronization.enums.FieldIdEnums; import electrosphere.server.datacell.Realm; @@ -116,6 +117,7 @@ public class ServerToolbarState implements BehaviorTree { public void visuallyEquipCurrentSlot(){ RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(parent); RelationalInventoryState equipInventoryState = InventoryUtils.getEquipInventory(parent); + Vector3d parentPos = EntityUtils.getPosition(parent); Entity inInventoryEntity = toolbarInventory.getItemSlot(selectedSlot + ""); if(inInventoryEntity != null){ boolean targetHasWhitelist = ItemUtils.hasEquipList(inInventoryEntity); @@ -123,7 +125,7 @@ public class ServerToolbarState implements BehaviorTree { //hydrate inventory item String itemType = ItemUtils.getType(inInventoryEntity); Realm realm = Globals.realmManager.getEntityRealm(parent); - realWorldItem = ItemUtils.serverSpawnBasicItem(realm,new Vector3d(0,0,0),itemType); + realWorldItem = ItemUtils.serverSpawnBasicItem(realm,new Vector3d(parentPos),itemType); //bind in world with in inventory ItemUtils.setRealWorldEntity(inInventoryEntity, realWorldItem); diff --git a/src/main/java/electrosphere/entity/types/item/ItemUtils.java b/src/main/java/electrosphere/entity/types/item/ItemUtils.java index dac02aeb..f3ef5292 100644 --- a/src/main/java/electrosphere/entity/types/item/ItemUtils.java +++ b/src/main/java/electrosphere/entity/types/item/ItemUtils.java @@ -274,7 +274,7 @@ public class ItemUtils { String idleAnim = (String)item.getData(EntityDataStrings.ANIM_IDLE); if(!actor.isPlayingAnimation(idleAnim)){ actor.playAnimation(idleAnim,AnimationPriorities.getValue(AnimationPriorities.INTERACTION)); - actor.incrementAnimationTime(0.0001); + actor.incrementAnimationTime(Globals.timekeeper.getSimFrameTime()); } } } diff --git a/src/main/java/electrosphere/renderer/pipelines/debug/DebugContentPipeline.java b/src/main/java/electrosphere/renderer/pipelines/debug/DebugContentPipeline.java index 53348608..dd0724f6 100644 --- a/src/main/java/electrosphere/renderer/pipelines/debug/DebugContentPipeline.java +++ b/src/main/java/electrosphere/renderer/pipelines/debug/DebugContentPipeline.java @@ -1,5 +1,8 @@ package electrosphere.renderer.pipelines.debug; +import java.util.LinkedList; +import java.util.List; + import org.joml.Matrix4d; import org.joml.Quaterniond; import org.joml.Quaternionf; @@ -128,7 +131,8 @@ public class DebugContentPipeline implements RenderPipeline { int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId()); Entity serverPlayerEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity); Realm playerRealm = Globals.realmManager.getEntityRealm(serverPlayerEntity); - for(HitboxCollectionState hitboxState : playerRealm.getHitboxManager().getAllHitboxes()){ + List hitboxStates = new LinkedList(playerRealm.getHitboxManager().getAllHitboxes()); + for(HitboxCollectionState hitboxState : hitboxStates){ for(DGeom geom : hitboxState.getGeometries()){ if(geom instanceof DSphere){ DSphere sphereView = (DSphere)geom; diff --git a/src/main/java/electrosphere/server/datacell/ServerDataCell.java b/src/main/java/electrosphere/server/datacell/ServerDataCell.java index 358abb59..2cbf85a8 100644 --- a/src/main/java/electrosphere/server/datacell/ServerDataCell.java +++ b/src/main/java/electrosphere/server/datacell/ServerDataCell.java @@ -15,6 +15,7 @@ import electrosphere.net.server.player.Player; import electrosphere.server.pathfinding.navmesh.NavMesh; import java.util.HashSet; +import java.util.List; import java.util.Set; /** @@ -202,11 +203,14 @@ public class ServerDataCell { if(newCell == null){ throw new Error("Passed null newCell! " + newCell); } - //swap which holds the entity - if(oldCell != null){ - oldCell.getScene().deregisterEntity(entity); + if(oldCell == null){ + throw new Error("Passed null oldCell! " + oldCell); } + //swap which holds the entity + List tags = oldCell.getScene().extractTags(entity); + oldCell.getScene().deregisterEntity(entity); newCell.getScene().registerEntity(entity); + newCell.getScene().registerEntityToTags(entity, tags); //update entity data cell mapper Globals.entityDataCellMapper.updateEntityCell(entity, newCell); //send the entity to new players that should care about it @@ -224,15 +228,13 @@ public class ServerDataCell { } } //delete the entity for players that dont care about it - if(oldCell != null){ - for(Player player : oldCell.activePlayers){ - if( - !newCell.containsPlayer(player) && - (player.getPlayerEntity() == null || player.getPlayerEntity() != entity) - ){ - //if the player isn't also in the new cell, delete the entity - player.addMessage(EntityMessage.constructDestroyMessage(entity.getId())); - } + for(Player player : oldCell.activePlayers){ + if( + !newCell.containsPlayer(player) && + (player.getPlayerEntity() == null || player.getPlayerEntity() != entity) + ){ + //if the player isn't also in the new cell, delete the entity + player.addMessage(EntityMessage.constructDestroyMessage(entity.getId())); } } } diff --git a/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java index 347bff58..7feb9190 100644 --- a/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java @@ -37,6 +37,7 @@ import electrosphere.server.datacell.ServerDataCell; import electrosphere.server.datacell.interfaces.DataCellManager; import electrosphere.server.datacell.interfaces.VoxelCellManager; import electrosphere.server.datacell.physics.PhysicsDataCell; +import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.fluid.manager.ServerFluidChunk; import electrosphere.server.fluid.manager.ServerFluidManager; import electrosphere.server.terrain.manager.ServerTerrainManager; diff --git a/src/main/java/electrosphere/server/poseactor/PoseActor.java b/src/main/java/electrosphere/server/poseactor/PoseActor.java index 3d3674fb..7421cb7b 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseActor.java +++ b/src/main/java/electrosphere/server/poseactor/PoseActor.java @@ -348,7 +348,7 @@ public class PoseActor { * Applies an animation mask to the PoseModel * @param model The posemodel to apply the mask to */ - void applyAnimationMasks(PoseModel model){ + private void applyAnimationMasks(PoseModel model){ List bonesUsed = new LinkedList(); List currentAnimationMask = new LinkedList(); for(ActorAnimationMask mask : animationQueue){ @@ -375,7 +375,7 @@ public class PoseActor { * Calculates all node transforms for the PoseModel based on bone rotators and the static morph of this PoseActor * @param model The PoseModel to calculate transforms for */ - void calculateNodeTransforms(PoseModel model){ + private void calculateNodeTransforms(PoseModel model){ model.updateNodeTransform(boneRotators,staticMorph); for(Bone bone : model.getBones()){ //store position diff --git a/src/main/java/electrosphere/server/poseactor/PoseModel.java b/src/main/java/electrosphere/server/poseactor/PoseModel.java index 771dfd71..5a0779de 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseModel.java +++ b/src/main/java/electrosphere/server/poseactor/PoseModel.java @@ -182,7 +182,7 @@ public class PoseModel { */ public void updateNodeTransform(Map boneRotators, ActorStaticMorph staticMorph){ if(this.rootAnimNode != null){ - updateNodeTransform(this.rootAnimNode,boneRotators,staticMorph); + this.updateNodeTransform(this.rootAnimNode,boneRotators,staticMorph); } } @@ -199,7 +199,7 @@ public class PoseModel { * @param boneRotators The bone rotators * @param staticMorph The static morph */ - void updateNodeTransform(AnimNode n, Map boneRotators, ActorStaticMorph staticMorph){ + private void updateNodeTransform(AnimNode n, Map boneRotators, ActorStaticMorph staticMorph){ //grab parent transform if exists Matrix4d parentTransform = new Matrix4d(); if(n.parent != null){ @@ -238,7 +238,7 @@ public class PoseModel { Iterator node_iterator = n.children.iterator(); while(node_iterator.hasNext()){ AnimNode current_node = node_iterator.next(); - updateNodeTransform(current_node,boneRotators,staticMorph); + this.updateNodeTransform(current_node,boneRotators,staticMorph); } } diff --git a/src/main/java/electrosphere/server/simulation/MicroSimulation.java b/src/main/java/electrosphere/server/simulation/MicroSimulation.java index 8cf86026..1e9f572a 100644 --- a/src/main/java/electrosphere/server/simulation/MicroSimulation.java +++ b/src/main/java/electrosphere/server/simulation/MicroSimulation.java @@ -39,7 +39,7 @@ public class MicroSimulation { //update actor animations Set poseableEntities = dataCell.getScene().getEntitiesWithTag(EntityTags.POSEABLE); if(poseableEntities != null){ - for(Entity currentEntity : dataCell.getScene().getEntitiesWithTag(EntityTags.POSEABLE)){ + for(Entity currentEntity : poseableEntities){ //fetch actor PoseActor currentPoseActor = EntityUtils.getPoseActor(currentEntity); //increment animations @@ -66,7 +66,6 @@ public class MicroSimulation { for(Entity collidable : collidables){ ServerCollidableTree.getServerCollidableTree(collidable).simulate((float)Globals.timekeeper.getSimFrameTime()); } - //update actor transform caches poseableEntities = dataCell.getScene().getEntitiesWithTag(EntityTags.POSEABLE); if(poseableEntities != null){