diff --git a/assets/Data/creatures/human.json b/assets/Data/creatures/human.json index 649bfafb..44787af9 100644 --- a/assets/Data/creatures/human.json +++ b/assets/Data/creatures/human.json @@ -299,8 +299,12 @@ "variants": [ { "variantId": "blockWeaponRight", - "mainAnimation" : "HoldItemR2HBlock", - "mainFirstPersonAnimation" : "HoldItemR2HBlock", + "mainAnimation" : { + "nameThirdPerson": "HoldItemR2HBlock", + "nameFirstPerson": "HoldItemR2HBlock", + "priorityCategory": "MOVEMENT_MODIFIER", + "boneGroups" : ["armLeft", "armRight", "handLeft", "handRight"] + }, "defaults" : [ { "equipPoint" : "handRight", diff --git a/src/main/java/electrosphere/engine/Main.java b/src/main/java/electrosphere/engine/Main.java index c6f9bda5..902ffeb4 100644 --- a/src/main/java/electrosphere/engine/Main.java +++ b/src/main/java/electrosphere/engine/Main.java @@ -244,7 +244,7 @@ public class Main { try { Globals.profiler.beginRootCpuSample("frame"); - LoggerInterface.loggerEngine.DEBUG("Begin Main Loop Frame"); + LoggerInterface.loggerEngine.DEBUG_LOOP("Begin Main Loop Frame"); // //Update timekeeper @@ -258,7 +258,7 @@ public class Main { /// if(Globals.RUN_CLIENT){ Globals.profiler.beginCpuSample("Load Assets"); - LoggerInterface.loggerEngine.DEBUG("Begin load assets"); + LoggerInterface.loggerEngine.DEBUG_LOOP("Begin load assets"); Globals.assetManager.loadAssetsInQueue(); Globals.profiler.endCpuSample(); } @@ -272,7 +272,7 @@ public class Main { //Why is this its own function? Just to get the networking code out of main() if(Globals.clientConnection != null){ Globals.profiler.beginCpuSample("Client networking"); - LoggerInterface.loggerEngine.DEBUG("Begin parse client messages"); + LoggerInterface.loggerEngine.DEBUG_LOOP("Begin parse client messages"); Globals.clientConnection.parseMessages(); Globals.profiler.endCpuSample(); } @@ -285,7 +285,7 @@ public class Main { //Poll controls if(Globals.RUN_CLIENT){ Globals.profiler.beginCpuSample("Poll Controls"); - LoggerInterface.loggerEngine.DEBUG("Begin recapture screen"); + LoggerInterface.loggerEngine.DEBUG_LOOP("Begin recapture screen"); Globals.controlHandler.pollControls(); RenderingEngine.recaptureIfNecessary(); Globals.profiler.endCpuSample(); @@ -312,7 +312,7 @@ public class Main { /// /// C L I E N T S I M U L A T I O N S T U F F /// - LoggerInterface.loggerEngine.DEBUG("Begin client simulation"); + LoggerInterface.loggerEngine.DEBUG_LOOP("Begin client simulation"); if(Globals.clientSimulation != null){ Globals.profiler.beginCpuSample("Client simulation"); Globals.clientSimulation.simulate(); @@ -343,7 +343,7 @@ public class Main { /// /// M A I N R E N D E R F U N C T I O N /// - LoggerInterface.loggerEngine.DEBUG("Begin rendering call"); + LoggerInterface.loggerEngine.DEBUG_LOOP("Begin rendering call"); if(Globals.RUN_CLIENT && !Globals.HEADLESS){ Globals.profiler.beginCpuSample("render"); Globals.renderingEngine.drawScreen(); @@ -404,7 +404,7 @@ public class Main { // // End main loop // - LoggerInterface.loggerEngine.DEBUG("End Main Loop Frame"); + LoggerInterface.loggerEngine.DEBUG_LOOP("End Main Loop Frame"); Globals.profiler.endCpuSample(); } catch (NullPointerException ex){ diff --git a/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java b/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java index 601eb54a..389a7425 100644 --- a/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java +++ b/src/main/java/electrosphere/entity/btree/StateTransitionUtil.java @@ -6,6 +6,7 @@ import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType; import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityUtils; +import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.game.data.common.TreeDataAnimation; import electrosphere.game.data.common.TreeDataAudio; @@ -101,23 +102,21 @@ public class StateTransitionUtil { private static void simulateClientState(Entity parent, StateTransitionUtilItem state){ Actor actor = EntityUtils.getActor(parent); if(actor != null){ - //determine the third person animation to play - String thirdPersonAnimation = state.getThirdPersonAnimation(); - - //determine the first person animation to play - String firstPersonAnimation = state.getFirstPersonAnimation(); - - + //get the animation to play + TreeDataAnimation animation = state.animation; + if(state.getAnimation != null && state.getAnimation.get() != null){ + animation = state.getAnimation.get(); + } //Main simulation - if(!actor.isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true && thirdPersonAnimation != null){ + if(!actor.isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true){ //state transition if this isn't set to loop state.onComplete.run(); state.startedAnimation = false; - } else if(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(thirdPersonAnimation)){ + } else if(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animation)){ //play animation, audio, etc, for state - if(parent == Globals.playerEntity && !Globals.controlHandler.cameraIsThirdPerson() && thirdPersonAnimation != null){ + if(parent == Globals.playerEntity && !Globals.controlHandler.cameraIsThirdPerson() && animation != null){ //first person //play first person audio if(state.audioData != null && state.audioData.getAudioPath() != null){ @@ -130,21 +129,17 @@ public class StateTransitionUtil { } } - if(state.animation == null){ - actor.playAnimation(firstPersonAnimation, state.getAnimationPriority()); - } else { - actor.playAnimation(state.animation,true); + if(animation != null){ + actor.playAnimation(animation,true); } actor.incrementAnimationTime(0.0001); state.startedAnimation = true; - } else if(thirdPersonAnimation == null && state.onComplete != null){ + } else if(state.animation == null && state.onComplete != null){ state.onComplete.run(); state.startedAnimation = false; } - if(state.animation == null){ - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, firstPersonAnimation, state.getAnimationPriority()); - } else if(firstPersonAnimation != null){ - FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, state.animation); + if(animation != null){ + FirstPersonTree.conditionallyPlayAnimation(Globals.firstPersonEntity, animation); } } } @@ -157,25 +152,24 @@ public class StateTransitionUtil { private static void simulateServerState(Entity parent, StateTransitionUtilItem state){ PoseActor poseActor = EntityUtils.getPoseActor(parent); if(poseActor != null){ - //determine the third person animation to play - String thirdPersonAnimation = state.getThirdPersonAnimation(); - + //get the animation to play + TreeDataAnimation animation = state.animation; + if(state.getAnimation != null && state.getAnimation.get() != null){ + animation = state.getAnimation.get(); + } + //Main simulation - if(!poseActor.isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true && thirdPersonAnimation != null){ + if(!poseActor.isPlayingAnimation() && state.onComplete != null && state.startedAnimation == true && animation != null){ //state transition if this isn't set to loop state.onComplete.run(); state.startedAnimation = false; - } else if(thirdPersonAnimation != null && (!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(thirdPersonAnimation))){ + } else if(state.animation != null && (!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animation))){ //play animation for state - if(state.animation == null){ - poseActor.playAnimation(thirdPersonAnimation, state.getAnimationPriority()); - } else { - poseActor.playAnimation(state.animation,true); - } + poseActor.playAnimation(animation, true); poseActor.incrementAnimationTime(0.0001); state.startedAnimation = true; - } else if(thirdPersonAnimation == null && state.onComplete != null){ + } else if(state.animation == null && state.onComplete != null){ state.onComplete.run(); state.startedAnimation = false; } @@ -190,17 +184,11 @@ public class StateTransitionUtil { //The enum value for this state Object stateEnum; - //the priority of this animation in particular - int animPriority; - //The animation to play TreeDataAnimation animation; - //Gets the first person animation's name - Supplier getFirstPersonAnimation; - - //Gets the third person animation's name - Supplier getThirdPersonAnimation; + //Gets the first person animation + Supplier getAnimation; //The audio data TreeDataAudio audioData; @@ -211,44 +199,17 @@ public class StateTransitionUtil { //Tracks whether the animation has been played or not boolean startedAnimation = false; - /** - * Gets the animation to play for third person - * @return The animation's name - */ - String getThirdPersonAnimation(){ - String toPlay = null; - if(animation != null){ - toPlay = animation.getNameThirdPerson(); - } - if(getThirdPersonAnimation != null){ - toPlay = getThirdPersonAnimation.get(); - } - return toPlay; - } - - /** - * Gets the animation to play for first person - * @return The animation's name - */ - String getFirstPersonAnimation(){ - String toPlay = null; - if(animation != null){ - toPlay = animation.getNameFirstPerson(); - } - if(getFirstPersonAnimation != null){ - toPlay = getFirstPersonAnimation.get(); - } - return toPlay; - } /** * Gets the animation priority * @return The animation priority */ int getAnimationPriority(){ - int priority = this.animPriority; + int priority = AnimationPriorities.getValue(AnimationPriorities.DEFAULT); if(animation != null && animation.getPriority() != null){ priority = animation.getPriority(); + } else if(getAnimation != null && getAnimation.get().getPriority() != null){ + priority = getAnimation.get().getPriority(); } return priority; } @@ -273,16 +234,12 @@ public class StateTransitionUtil { */ private StateTransitionUtilItem( Object stateEnum, - int animPriority, - Supplier getFirstPersonAnimation, - Supplier getThirdPersonAnimation, + Supplier getAnimation, TreeDataAudio audioData, Runnable onComplete ){ this.stateEnum = stateEnum; - this.animPriority = animPriority; - this.getFirstPersonAnimation = getFirstPersonAnimation; - this.getThirdPersonAnimation = getThirdPersonAnimation; + this.getAnimation = getAnimation; this.audioData = audioData; this.onComplete = onComplete; } @@ -292,25 +249,19 @@ public class StateTransitionUtil { * This decouples the animations from the initialization of the tree. * The intended usecase is if the animation could change based on some state in the tree. * @param stateEnum The enum value for this state - * @param animPriority The priority of this state's animations - * @param getFirstPersonAnimation The supplier for a first person animation name. If it is null, it will not play any animation in first person - * @param getThirdPersonAnimation The supplier for a third person animation name. If it is null, it will not play any animation in the third person + * @param getAnimationData The supplier for the animation data. If it is null, it will not play any animation * @param audioData The path to an audio file to play on starting the animation. If null, no audio will be played * @param onComplete !!Must transition to the next state!! Fires when the animation completes. If not supplied, animations and autio will loop */ public static StateTransitionUtilItem create( Object stateEnum, - int animPriority, - Supplier getFirstPersonAnimation, - Supplier getThirdPersonAnimation, + Supplier getAnimation, TreeDataAudio audioData, Runnable onComplete ){ return new StateTransitionUtilItem( stateEnum, - animPriority, - getFirstPersonAnimation, - getThirdPersonAnimation, + getAnimation, audioData, onComplete ); diff --git a/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java b/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java index 4e1674da..ada16137 100644 --- a/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java +++ b/src/main/java/electrosphere/entity/state/block/ClientBlockTree.java @@ -7,7 +7,6 @@ import electrosphere.entity.EntityDataStrings; import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.btree.StateTransitionUtil; import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem; -import electrosphere.entity.state.AnimationPriorities; import electrosphere.game.data.creature.type.block.BlockSystem; import electrosphere.net.synchronization.BehaviorTreeIdEnums; @@ -56,24 +55,18 @@ public class ClientBlockTree implements BehaviorTree { this.stateTransitionUtil = StateTransitionUtil.create(parent, false, new StateTransitionUtilItem[]{ StateTransitionUtilItem.create( BlockState.WIND_UP, - AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH), - () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpFirstPersonAnimation();}, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpAnimation();}, null, null ), StateTransitionUtilItem.create( BlockState.BLOCKING, - AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH), - () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainFirstPersonAnimation();}, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainAnimation();}, null, null ), StateTransitionUtilItem.create( BlockState.COOLDOWN, - AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH), - () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownFirstPersonAnimation();}, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownAnimation();}, null, null diff --git a/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java b/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java index b6826025..9ef52839 100644 --- a/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java +++ b/src/main/java/electrosphere/entity/state/block/ServerBlockTree.java @@ -14,7 +14,6 @@ import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.net.parser.net.message.SynchronizationMessage; import electrosphere.server.datacell.utils.DataCellSearchUtils; -import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.block.ClientBlockTree.BlockState; import electrosphere.game.data.creature.type.block.BlockSystem; import electrosphere.net.synchronization.annotation.SyncedField; @@ -50,24 +49,18 @@ public class ServerBlockTree implements BehaviorTree { this.stateTransitionUtil = StateTransitionUtil.create(parent, true, new StateTransitionUtilItem[]{ StateTransitionUtilItem.create( BlockState.WIND_UP, - AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH), - null, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getWindUpAnimation();}, null, () -> {this.setState(BlockState.BLOCKING);} ), StateTransitionUtilItem.create( BlockState.BLOCKING, - AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH), - null, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getMainAnimation();}, null, null ), StateTransitionUtilItem.create( BlockState.COOLDOWN, - AnimationPriorities.getValue(AnimationPriorities.MODIFIER_HIGH), - null, () -> {return this.blockSystem.getBlockVariant(this.currentBlockVariant).getCooldownAnimation();}, null, () -> {this.setState(BlockState.NOT_BLOCKING);} diff --git a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java index bc3ea2e3..d9cd9b32 100644 --- a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java +++ b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java @@ -18,6 +18,7 @@ import electrosphere.entity.state.attack.ServerAttackTree; import electrosphere.entity.state.attack.ShooterTree; import electrosphere.entity.state.block.ClientBlockTree; import electrosphere.entity.state.block.ServerBlockTree; +import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.equip.ClientEquipState; import electrosphere.entity.state.equip.ServerEquipState; import electrosphere.entity.state.gravity.ClientGravityTree; @@ -359,6 +360,10 @@ public class CreatureUtils { rVal.putData(EntityDataStrings.CLIENT_ROTATOR_TREE, rotatorTree); Globals.clientScene.registerBehaviorTree(rotatorTree); } + //bone groups + if(rawType.getBoneGroups() != null){ + creatureActor.setBoneGroups(rawType.getBoneGroups()); + } //add health system if(rawType.getHealthSystem() != null){ ClientLifeTree.attachTree(rVal,rawType.getHealthSystem()); @@ -648,6 +653,11 @@ public class CreatureUtils { ServerBehaviorTreeUtils.attachBTreeToEntity(rVal, rotatorTree); } + //bone groups + if(rawType.getBoneGroups() != null){ + creatureActor.setBoneGroups(rawType.getBoneGroups()); + } + /// /// /// AI (This SHOULD only be applied on the server with the way AI architected currently) @@ -681,6 +691,37 @@ public class CreatureUtils { return rVal; } + + /** + * Creates a viewmodel entity on the client side + * @param type The type of creature + * @param template The template for the creature + * @return The entity + */ + public static Entity clientCreateViewModel( + String type, + CreatureTemplate template + ){ + CreatureData rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type); + Entity rVal = EntityCreationUtils.createClientSpatialEntity(); + + if(rawType.getViewModelData() != null){ + EntityCreationUtils.makeEntityDrawable(rVal, rawType.getViewModelData().getFirstPersonModelPath()); + FirstPersonTree.attachTree( + rVal, + rawType.getViewModelData().getHeightFromOrigin(), + rawType.getViewModelData().getCameraViewDirOffsetY(), + rawType.getViewModelData().getCameraViewDirOffsetZ() + ); + } + Actor creatureActor = EntityUtils.getActor(rVal); + + if(rawType.getBoneGroups() != null){ + creatureActor.setBoneGroups(rawType.getBoneGroups()); + } + + return rVal; + } public static void sendEntityToPlayer(Player player, Entity creature){ int id = creature.getId(); diff --git a/src/main/java/electrosphere/game/data/creature/type/block/BlockVariant.java b/src/main/java/electrosphere/game/data/creature/type/block/BlockVariant.java index b1fde802..f992bf23 100644 --- a/src/main/java/electrosphere/game/data/creature/type/block/BlockVariant.java +++ b/src/main/java/electrosphere/game/data/creature/type/block/BlockVariant.java @@ -2,6 +2,8 @@ package electrosphere.game.data.creature.type.block; import java.util.List; +import electrosphere.game.data.common.TreeDataAnimation; + /** * A variant of data that can be loaded into the block system. Variants are for different types of equip states. * IE: holding just a sword in your right hand will have a different block animation vs a shield in your right @@ -13,22 +15,13 @@ public class BlockVariant { String variantId; //the animation to play when winding up - String windUpAnimation; + TreeDataAnimation windUpAnimation; //the main animation to play while blocking - String mainAnimation; + TreeDataAnimation mainAnimation; //the animation to play when cooling down - String cooldownAnimation; - - //the animation to play in first person when winding up - String windUpFirstPersonAnimation; - - //the main animation to play in first person while blocking - String mainFirstPersonAnimation; - - //the animation to play in first person when cooling down - String cooldownFirstPersonAnimation; + TreeDataAnimation cooldownAnimation; //the list of default equipment cases that this variant should be used for List defaults; @@ -45,7 +38,7 @@ public class BlockVariant { * The animation to play when winding up * @return */ - public String getWindUpAnimation(){ + public TreeDataAnimation getWindUpAnimation(){ return windUpAnimation; } @@ -53,7 +46,7 @@ public class BlockVariant { * The main animation to play while blocking * @return */ - public String getMainAnimation(){ + public TreeDataAnimation getMainAnimation(){ return mainAnimation; } @@ -61,34 +54,10 @@ public class BlockVariant { * The animation to play when cooling down * @return */ - public String getCooldownAnimation(){ + public TreeDataAnimation getCooldownAnimation(){ return cooldownAnimation; } - /** - * The animation to play in first person when winding up - * @return - */ - public String getWindUpFirstPersonAnimation(){ - return windUpFirstPersonAnimation; - } - - /** - * The main animation to play in first person while blocking - * @return - */ - public String getMainFirstPersonAnimation(){ - return mainFirstPersonAnimation; - } - - /** - * The animation to play in first person when cooling down - * @return - */ - public String getCooldownFirstPersonAnimation(){ - return cooldownFirstPersonAnimation; - } - /** * the list of default equipment cases that this variant should be used for * @return diff --git a/src/main/java/electrosphere/menu/debug/ImGuiEntityMacros.java b/src/main/java/electrosphere/menu/debug/ImGuiEntityMacros.java index 7537cd1f..4112ffec 100644 --- a/src/main/java/electrosphere/menu/debug/ImGuiEntityMacros.java +++ b/src/main/java/electrosphere/menu/debug/ImGuiEntityMacros.java @@ -2,7 +2,7 @@ package electrosphere.menu.debug; import java.util.LinkedList; import java.util.List; -import java.util.PriorityQueue; +import java.util.Set; import org.joml.Quaterniond; import org.joml.Vector3d; @@ -162,7 +162,7 @@ public class ImGuiEntityMacros { //animation queue if(ImGui.collapsingHeader("Animation Queue")){ - PriorityQueue animationQueue = actor.getAnimationQueue(); + Set animationQueue = actor.getAnimationQueue(); for(ActorAnimationMask mask : animationQueue){ ImGui.text(mask.getAnimationName() + " - " + mask.getPriority()); ImGui.text(mask.getDuration() + " " + mask.getTime()); diff --git a/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java b/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java index 6227fbcc..f244d73a 100644 --- a/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java @@ -175,9 +175,10 @@ public class EntityProtocol { Globals.clientCharacterID = message.getentityID(); Globals.playerEntity = target; if(viewModelData != null && viewModelData.getFirstPersonModelPath() != null){ - Globals.firstPersonEntity = EntityCreationUtils.createClientSpatialEntity(); - EntityCreationUtils.makeEntityDrawable(Globals.firstPersonEntity, viewModelData.getFirstPersonModelPath()); - FirstPersonTree.attachTree(Globals.firstPersonEntity, viewModelData.getHeightFromOrigin(), viewModelData.getCameraViewDirOffsetY(), viewModelData.getCameraViewDirOffsetZ()); + Globals.firstPersonEntity = CreatureUtils.clientCreateViewModel( + creatureTypeRaw, + null + ); } } } diff --git a/src/main/java/electrosphere/renderer/actor/Actor.java b/src/main/java/electrosphere/renderer/actor/Actor.java index eb6cec96..10dc6552 100644 --- a/src/main/java/electrosphere/renderer/actor/Actor.java +++ b/src/main/java/electrosphere/renderer/actor/Actor.java @@ -3,6 +3,8 @@ package electrosphere.renderer.actor; import electrosphere.engine.Globals; import electrosphere.entity.state.AnimationPriorities; import electrosphere.game.data.common.TreeDataAnimation; +import electrosphere.game.data.creature.type.bonegroups.BoneGroup; +import electrosphere.logger.LoggerInterface; import electrosphere.renderer.OpenGLState; import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.model.Bone; @@ -13,7 +15,8 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.PriorityQueue; +import java.util.Set; +import java.util.TreeSet; import org.joml.AxisAngle4f; import org.joml.Matrix4d; @@ -47,7 +50,7 @@ public class Actor { float animationScalar = 1.0f; //The stack of animations being applied to a given actor - PriorityQueue animationQueue = new PriorityQueue(); + Set animationQueue = new TreeSet(); //Mask for overwriting meshes in a given actor ActorMeshMask meshMask = new ActorMeshMask(); @@ -64,6 +67,9 @@ public class Actor { //static morph for this specific actor ActorStaticMorph staticMorph; + //The list of bone groups + List boneGroups; + //Controls whether the actor should obey frustum culling boolean frustumCull = true; @@ -111,6 +117,26 @@ public class Actor { return false; } + /** + * Checks if an animation is being played on any meshes + * @param animationData The animation data + * @return true if the animation is being played on any meshes, false if the provided animation name is null or the animation is not being played on any meshes + */ + public boolean isPlayingAnimation(TreeDataAnimation animationData){ + if(animationData == null){ + return false; + } + for(ActorAnimationMask mask : animationQueue){ + if(mask.getAnimationName().contains(animationData.getNameFirstPerson())){ + return true; + } + if(mask.getAnimationName().contains(animationData.getNameThirdPerson())){ + return true; + } + } + return false; + } + public boolean isPlayingAnimation(){ return animationQueue.size() > 0; } @@ -183,9 +209,27 @@ public class Actor { //Gets the mask List boneMask = null; - if(animation.getBoneGroups() != null){ + if(animation.getBoneGroups() != null && this.boneGroups != null){ boneMask = new LinkedList(); + for(String boneGroupName : animation.getBoneGroups()){ + BoneGroup group = null; + for(BoneGroup currentGroup : this.boneGroups){ + if(currentGroup.getId().equals(boneGroupName)){ + group = currentGroup; + break; + } + } + + if(group != null && isThirdPerson == true && group.getBoneNamesThirdPerson() != null && group.getBoneNamesThirdPerson().size() > 0){ + boneMask.addAll(group.getBoneNamesThirdPerson()); + } + if(group != null && isThirdPerson == false && group.getBoneNamesFirstPerson() != null && group.getBoneNamesFirstPerson().size() > 0){ + boneMask.addAll(group.getBoneNamesFirstPerson()); + } + } + } else if(this.boneGroups == null){ + LoggerInterface.loggerRenderer.WARNING("Trying to play animation on pose actor that uses bone groups, but the actor's bone group isn't defined!"); } @@ -258,10 +302,14 @@ public class Actor { * Gets the animation queue * @return The animation queue */ - public PriorityQueue getAnimationQueue(){ + public Set getAnimationQueue(){ return animationQueue; } + /** + * Applies the animation masks in this actor to the provided model + * @param model The model + */ void applyAnimationMasks(Model model){ List bonesUsed = new LinkedList(); List currentAnimationMask = new LinkedList(); @@ -532,6 +580,14 @@ public class Actor { return frustumCull; } + /** + * Sets the bone groups in the actor + * @param boneGroups The bone groups + */ + public void setBoneGroups(List boneGroups){ + this.boneGroups = boneGroups; + } + /** diff --git a/src/main/java/electrosphere/server/MainServerFunctions.java b/src/main/java/electrosphere/server/MainServerFunctions.java index 2245b47e..fc7e28ed 100644 --- a/src/main/java/electrosphere/server/MainServerFunctions.java +++ b/src/main/java/electrosphere/server/MainServerFunctions.java @@ -24,14 +24,14 @@ public class MainServerFunctions { // //Micro simulation (ie simulating each scene on the server) Globals.profiler.beginCpuSample("Server micro simulation"); - LoggerInterface.loggerEngine.DEBUG("Begin server micro simulation"); + LoggerInterface.loggerEngine.DEBUG_LOOP("Begin server micro simulation"); if(Globals.realmManager != null){ Globals.realmManager.simulate(); } // //Macro simulation (ie simulating the larger world macro data) - LoggerInterface.loggerEngine.DEBUG("Server macro simulation"); + LoggerInterface.loggerEngine.DEBUG_LOOP("Server macro simulation"); if(Globals.macroSimulation != null && Globals.macroSimulation.isReady()){ Globals.macroSimulation.simulate(); } diff --git a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java index c2e46a8e..295bc1e0 100644 --- a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java @@ -312,6 +312,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager ){ LoggerInterface.loggerEngine.DEBUG("Get server data cell key: " + getServerDataCellKey(worldPos)); rVal = groundDataCells.get(getServerDataCellKey(worldPos)); + } else { + LoggerInterface.loggerEngine.DEBUG("Failed to get server data cell at: " + worldPos); } return rVal; } diff --git a/src/main/java/electrosphere/server/poseactor/PoseActor.java b/src/main/java/electrosphere/server/poseactor/PoseActor.java index 9d7a98d9..ff2eee5b 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseActor.java +++ b/src/main/java/electrosphere/server/poseactor/PoseActor.java @@ -16,6 +16,8 @@ import org.joml.Vector4d; import electrosphere.engine.Globals; import electrosphere.entity.state.AnimationPriorities; import electrosphere.game.data.common.TreeDataAnimation; +import electrosphere.game.data.creature.type.bonegroups.BoneGroup; +import electrosphere.logger.LoggerInterface; import electrosphere.renderer.actor.ActorAnimationMask; import electrosphere.renderer.actor.ActorBoneRotator; import electrosphere.renderer.actor.ActorStaticMorph; @@ -36,6 +38,9 @@ public class PoseActor { //static morph used to apply an initial, static modification to the layout of bones in the pose model ActorStaticMorph staticMorph; + //The bone groups for this pose actor + List boneGroups; + /** * Constructor @@ -94,6 +99,20 @@ public class PoseActor { return false; } + /** + * Gets whether the animation is currently playing or not + * @param animationName The animation + * @return True if the animation is playing, false otherwise + */ + public boolean isPlayingAnimation(TreeDataAnimation animationName){ + for(ActorAnimationMask mask : animationQueue){ + if(mask.getAnimationName().contains(animationName.getNameThirdPerson())){ + return true; + } + } + return false; + } + /** * Gets whether the actor is playing ANY animation * @return True if the actor is playing ANY animation, false otherwise @@ -171,9 +190,27 @@ public class PoseActor { //Gets the mask List boneMask = null; - if(animation.getBoneGroups() != null){ + if(animation.getBoneGroups() != null && this.boneGroups != null){ boneMask = new LinkedList(); + for(String boneGroupName : animation.getBoneGroups()){ + BoneGroup group = null; + for(BoneGroup currentGroup : this.boneGroups){ + if(currentGroup.getId().equals(boneGroupName)){ + group = currentGroup; + break; + } + } + + if(group != null && isThirdPerson == true){ + boneMask.addAll(group.getBoneNamesThirdPerson()); + } + if(group != null && isThirdPerson == false){ + boneMask.addAll(group.getBoneNamesFirstPerson()); + } + } + } else if(this.boneGroups == null){ + LoggerInterface.loggerRenderer.WARNING("Trying to play animation on pose actor that uses bone groups, but the actor's bone group isn't defined!"); } @@ -359,6 +396,14 @@ public class PoseActor { return rVal; } + /** + * Sets the bone groups + * @param boneGroups The bone groups + */ + public void setBoneGroups(List boneGroups){ + this.boneGroups = boneGroups; + } + /** * Checks if the pose model is loaded * @return True if the pose model is loaded, false otherwise