From f4f288c8d5df7785019e18fae7d1dc77bc0d2bd2 Mon Sep 17 00:00:00 2001 From: austin Date: Mon, 9 Sep 2024 17:08:02 -0400 Subject: [PATCH] recoil on attack block --- assets/Data/creatures/human.json | 8 ++ assets/Models/creatures/person2/person2_1.glb | Bin 1876764 -> 1911052 bytes assets/Models/creatures/viewmodel.glb | Bin 850052 -> 889180 bytes docs/src/progress/renderertodo.md | 4 + src/main/java/electrosphere/engine/Main.java | 2 - .../entity/state/attack/ClientAttackTree.java | 59 ++++++++-- .../entity/state/attack/ServerAttackTree.java | 62 +++++++++-- .../data/creature/type/attack/AttackMove.java | 9 ++ .../renderer/RenderingEngine.java | 3 +- .../electrosphere/renderer/actor/Actor.java | 16 ++- .../renderer/anim/AnimChannel.java | 101 +++++++++++++++--- .../renderer/anim/Animation.java | 79 ++++++++++---- .../electrosphere/renderer/anim/Keyframe.java | 24 +++++ .../electrosphere/renderer/model/Model.java | 2 +- .../ServerHitboxResolutionCallback.java | 9 +- .../server/poseactor/PoseActor.java | 28 ++++- .../server/poseactor/PoseActorUtils.java | 5 +- .../server/poseactor/PoseModel.java | 2 +- 18 files changed, 345 insertions(+), 68 deletions(-) diff --git a/assets/Data/creatures/human.json b/assets/Data/creatures/human.json index 2d91c98b..c47c14cf 100644 --- a/assets/Data/creatures/human.json +++ b/assets/Data/creatures/human.json @@ -477,6 +477,14 @@ "audioData" : { "audioPath" : "Audio/weapons/swoosh-03.ogg" } + }, + "blockRecoilState" : { + "animation" : { + "nameFirstPerson" : "SwordR2HSlash1Recoil", + "nameThirdPerson" : "SwordR2HSlash1Recoil", + "priorityCategory" : "MOVEMENT_MODIFIER", + "boneGroups" : ["armLeft", "armRight", "handLeft", "handRight"] + } } }, { diff --git a/assets/Models/creatures/person2/person2_1.glb b/assets/Models/creatures/person2/person2_1.glb index 2a5e2724125f2f79afbdb06e355a124eae208b74..93e091cdcf6817cd8ba9c350ec5483d9d047cbce 100644 GIT binary patch delta 16062 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 Q#B2#VQ+A?p@WA>12lt)C-~a#s delta 8027 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 diff --git a/assets/Models/creatures/viewmodel.glb b/assets/Models/creatures/viewmodel.glb index 9a9a32f6d6fdf173e52eb41f7f7777dd01fd636a..69377b958a95ccbd011f4f08d3ed0b20608a2793 100644 GIT binary patch delta 10380 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 delta 108 zcmcb!$gJg~F@Jhah#M0F14GLX9)>R;*&6v<`59aJnYQvXtE9C%E@TE`mhFxUS(91Y ztxmIUw>r({(>7fumtC6I*wVzp%%V27RzabJt=%b?9f&!Am=lP(fS4PIdA2*{@>a0{ E0H3TPbN~PV diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 8db04bec..ea83114d 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -703,6 +703,10 @@ par_shapes integration Directed graph datastructure Framebuffer + RenderingEngine tests +(09/09/2024) +Fix obnoxious opengl state caching bug w/ framebuffers in junit context +Recoil on attack block + # TODO diff --git a/src/main/java/electrosphere/engine/Main.java b/src/main/java/electrosphere/engine/Main.java index 70c7149f..c448780a 100644 --- a/src/main/java/electrosphere/engine/Main.java +++ b/src/main/java/electrosphere/engine/Main.java @@ -1,6 +1,5 @@ package electrosphere.engine; -import static org.lwjgl.glfw.GLFW.glfwTerminate; import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose; import java.util.concurrent.TimeUnit; @@ -16,7 +15,6 @@ import electrosphere.controls.ControlHandler.ControlsState; import electrosphere.engine.cli.CLIParser; import electrosphere.engine.loadingthreads.LoadingThread; import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType; -import electrosphere.engine.threads.LabeledThread.ThreadLabel; import electrosphere.engine.time.Timekeeper; import electrosphere.game.server.world.MacroData; import electrosphere.logger.LoggerInterface; diff --git a/src/main/java/electrosphere/entity/state/attack/ClientAttackTree.java b/src/main/java/electrosphere/entity/state/attack/ClientAttackTree.java index 2a32c732..eddb0b99 100644 --- a/src/main/java/electrosphere/entity/state/attack/ClientAttackTree.java +++ b/src/main/java/electrosphere/entity/state/attack/ClientAttackTree.java @@ -29,28 +29,29 @@ import java.util.List; import org.joml.Vector3d; -@SynchronizedBehaviorTree(name = "clientAttackTree", isServer = false, correspondingTree="serverAttackTree") /** * Client basic attack tree */ +@SynchronizedBehaviorTree(name = "clientAttackTree", isServer = false, correspondingTree="serverAttackTree") public class ClientAttackTree implements BehaviorTree { - @SynchronizableEnum /** * States available to the attack tree */ + @SynchronizableEnum public static enum AttackTreeState { WINDUP, HOLD, ATTACK, + BLOCK_RECOIL, COOLDOWN, IDLE, } - @SynchronizableEnum /** * The state of drifting forward during the attack */ + @SynchronizableEnum public static enum AttackTreeDriftState { DRIFT, NO_DRIFT, @@ -177,6 +178,32 @@ public class ClientAttackTree implements BehaviorTree { }, false ), + StateTransitionUtilItem.create( + AttackTreeState.BLOCK_RECOIL, + () -> { + TreeDataState state = null; + if(currentMove != null){ + state = currentMove.getBlockRecoilState(); + } + if(state == null){ + return null; + } else { + return state.getAnimation(); + } + }, + () -> { + TreeDataState state = null; + if(currentMove != null){ + state = currentMove.getBlockRecoilState(); + } + if(state == null){ + return null; + } else { + return state.getAudioData(); + } + }, + false + ), StateTransitionUtilItem.create( AttackTreeState.COOLDOWN, () -> { @@ -320,6 +347,19 @@ public class ClientAttackTree implements BehaviorTree { } } } break; + case BLOCK_RECOIL: { + this.stateTransitionUtil.simulate(AttackTreeState.BLOCK_RECOIL); + //activate hitboxes + List attachedEntities = AttachUtils.getChildrenList(parent); + if(attachedEntities != null){ + for(Entity currentAttached : attachedEntities){ + if(HitboxCollectionState.hasHitboxState(currentAttached)){ + HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached); + currentState.setActive(false); + } + } + } + } break; case COOLDOWN: { this.stateTransitionUtil.simulate(AttackTreeState.COOLDOWN); //deactive hitboxes @@ -535,10 +575,12 @@ public class ClientAttackTree implements BehaviorTree { return 1; case ATTACK: return 2; - case COOLDOWN: + case BLOCK_RECOIL: return 3; - case IDLE: + case COOLDOWN: return 4; + case IDLE: + return 5; default: return 0; } @@ -560,8 +602,10 @@ public class ClientAttackTree implements BehaviorTree { case 2: return AttackTreeState.ATTACK; case 3: - return AttackTreeState.COOLDOWN; + return AttackTreeState.BLOCK_RECOIL; case 4: + return AttackTreeState.COOLDOWN; + case 5: return AttackTreeState.IDLE; default: return AttackTreeState.WINDUP; @@ -632,6 +676,9 @@ public class ClientAttackTree implements BehaviorTree { */ public void transitionState(AttackTreeState newState){ this.stateTransitionUtil.reset(); + if(newState == AttackTreeState.BLOCK_RECOIL){ + this.stateTransitionUtil.interrupt(AttackTreeState.ATTACK); + } this.setState(newState); } diff --git a/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java b/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java index fbcd78d8..f0927f21 100644 --- a/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java +++ b/src/main/java/electrosphere/entity/state/attack/ServerAttackTree.java @@ -45,18 +45,18 @@ import org.joml.Quaterniond; import org.joml.Vector3d; import org.joml.Vector3f; -@SynchronizedBehaviorTree(name = "serverAttackTree", isServer = true, correspondingTree="clientAttackTree") /** * Server basic attack tree */ +@SynchronizedBehaviorTree(name = "serverAttackTree", isServer = true, correspondingTree="clientAttackTree") public class ServerAttackTree implements BehaviorTree { - @SyncedField(serverSendTransitionPacket = true) //the state of the attack tree + @SyncedField(serverSendTransitionPacket = true) AttackTreeState state; - @SyncedField //the state of drifting caused by the attack animation + @SyncedField AttackTreeDriftState driftState; Entity parent; @@ -91,6 +91,11 @@ public class ServerAttackTree implements BehaviorTree { //The state transition util StateTransitionUtil stateTransitionUtil; + /** + * Private constructor + * @param e The parent entity + * @param params The data to construct the tree with + */ private ServerAttackTree(Entity e, Object ... params){ state = AttackTreeState.IDLE; driftState = AttackTreeDriftState.NO_DRIFT; @@ -126,11 +131,10 @@ public class ServerAttackTree implements BehaviorTree { StateTransitionUtilItem.create( AttackTreeState.HOLD, () -> { - TreeDataState state = currentMove.getHoldState(); - if(state == null){ + if(currentMove != null && currentMove.getHoldState() == null){ return null; } else { - return state.getAnimation(); + return currentMove.getHoldState().getAnimation(); } }, () -> { @@ -159,6 +163,21 @@ public class ServerAttackTree implements BehaviorTree { this.setState(AttackTreeState.COOLDOWN); } ), + StateTransitionUtilItem.create( + AttackTreeState.BLOCK_RECOIL, + () -> { + if(currentMove != null && currentMove.getBlockRecoilState() != null){ + return currentMove.getBlockRecoilState().getAnimation(); + } else { + return null; + } + }, + null, + () -> { + this.stateTransitionUtil.interrupt(AttackTreeState.BLOCK_RECOIL); + this.setState(AttackTreeState.COOLDOWN); + } + ), StateTransitionUtilItem.create( AttackTreeState.COOLDOWN, () -> { @@ -188,6 +207,9 @@ public class ServerAttackTree implements BehaviorTree { return state; } + /** + * Starts an attack + */ public void start(){ currentMoveCanHold = false; currentMoveHasWindup = false; @@ -260,6 +282,23 @@ public class ServerAttackTree implements BehaviorTree { } } + /** + * Causes the attack tree to instead enter recoil state + */ + public void recoilFromBlock(){ + if(currentMove != null){ + setState(AttackTreeState.BLOCK_RECOIL); + //deactivate hitboxes + List attachedEntities = AttachUtils.getChildrenList(parent); + for(Entity currentAttached : attachedEntities){ + if(HitboxCollectionState.hasHitboxState(currentAttached)){ + HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached); + currentState.setActive(false); + } + } + } + } + @Override public void simulate(float deltaTime){ frameCurrent = frameCurrent + (float)Globals.timekeeper.getDeltaFrames(); @@ -365,6 +404,17 @@ public class ServerAttackTree implements BehaviorTree { projectileToFire = null; } } break; + case BLOCK_RECOIL: { + this.stateTransitionUtil.simulate(AttackTreeState.BLOCK_RECOIL); + //activate hitboxes + List attachedEntities = AttachUtils.getChildrenList(parent); + for(Entity currentAttached : attachedEntities){ + if(HitboxCollectionState.hasHitboxState(currentAttached)){ + HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached); + currentState.setActive(false); + } + } + } break; case COOLDOWN: { this.stateTransitionUtil.simulate(AttackTreeState.COOLDOWN); //deactive hitboxes diff --git a/src/main/java/electrosphere/game/data/creature/type/attack/AttackMove.java b/src/main/java/electrosphere/game/data/creature/type/attack/AttackMove.java index c12f3349..bbaec94a 100644 --- a/src/main/java/electrosphere/game/data/creature/type/attack/AttackMove.java +++ b/src/main/java/electrosphere/game/data/creature/type/attack/AttackMove.java @@ -19,6 +19,7 @@ public class AttackMove { TreeDataState windupState; TreeDataState holdState; TreeDataState attackState; + TreeDataState blockRecoilState; TreeDataState cooldownState; /* @@ -85,6 +86,14 @@ public class AttackMove { return attackState; } + /** + * Gets the state to play for the recoil + * @return the state data + */ + public TreeDataState getBlockRecoilState() { + return blockRecoilState; + } + /** * Gets the state to play for the cooldown * @return the state data diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index 2c1f3bf9..9fcd8094 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -39,7 +39,6 @@ import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL45; -import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.opengl.GLDebugMessageCallback; import org.lwjgl.system.MemoryStack; @@ -271,7 +270,7 @@ public class RenderingEngine { // setTitleBarDimensions(); //Creates the OpenGL capabilities for the program.) - GLCapabilities glCapabilities = GL.createCapabilities(); + GL.createCapabilities(); GL45.glEnable(GL45.GL_DEBUG_OUTPUT); //register error callback diff --git a/src/main/java/electrosphere/renderer/actor/Actor.java b/src/main/java/electrosphere/renderer/actor/Actor.java index 3a538a72..322bf25a 100644 --- a/src/main/java/electrosphere/renderer/actor/Actor.java +++ b/src/main/java/electrosphere/renderer/actor/Actor.java @@ -77,12 +77,24 @@ public class Actor { //Controls whether the actor should obey frustum culling boolean frustumCull = true; + + /** + * Used for caching animation masks that should be removed + */ + List toRemoveMasks = new LinkedList(); + /** + * Creates an achor + * @param modelPath The path of the model associated with the actor + */ public Actor(String modelPath){ this.modelPath = modelPath; } - - List toRemoveMasks = new LinkedList(); + + /** + * Increments the animation time of the actor + * @param deltaTime The amount of time to increment by + */ public void incrementAnimationTime(double deltaTime){ toRemoveMasks.clear(); for(ActorAnimationMask mask : animationQueue){ diff --git a/src/main/java/electrosphere/renderer/anim/AnimChannel.java b/src/main/java/electrosphere/renderer/anim/AnimChannel.java index 2454a100..2553b4dd 100644 --- a/src/main/java/electrosphere/renderer/anim/AnimChannel.java +++ b/src/main/java/electrosphere/renderer/anim/AnimChannel.java @@ -15,22 +15,57 @@ import electrosphere.logger.LoggerInterface; */ public class AnimChannel { + /** + * The current time of the channel + */ double timeCurrent = 0; + + /** + * The total time of the channel + */ double timeTotal; + + /** + * The ticks per second of the channel + */ double ticksPerSecond; + + /** + * The bone id associated with the channel + */ String nodeID; - + /** + * The starting position of the bone + */ Vector3f startingPosition; + + /** + * All position frames + */ TreeMap positionFrameTree; - + /** + * The starting rotation of the bone + */ Quaterniond startingRotation; + + /** + * All rotation frames + */ TreeMap rotationFrameTree; + /** + * All scale frames + */ TreeMap scaleFrameTree; + /** + * Creates an anim channel + * @param maxTime The max time of the channel + * @param ticksPerSecond The ticks per second + */ public AnimChannel(double maxTime, double ticksPerSecond){ timeTotal = maxTime; this.ticksPerSecond = ticksPerSecond; @@ -269,43 +304,60 @@ public class AnimChannel { return rVal; } + /** + * Increments time on the channel + * @param incrementValue The amount to increment by + */ public void incrementTime(double incrementValue){ timeCurrent = timeCurrent + incrementValue; } + /** + * Sets the current time of the channel + * @param time The time + */ public void setTime(double time){ this.timeCurrent = time; } + /** + * Rewinds the channel + */ public void rewind(){ timeCurrent = 0; } + /** + * Describes the channel at a high level + */ public void describeChannel(){ - System.out.println("Target object: " + nodeID); - System.out.println("Time: " + timeCurrent + "/" + timeTotal); - System.out.println(positionFrameTree.size() + " position Frames"); - System.out.println(rotationFrameTree.size() + " rotation Frames"); - System.out.println(scaleFrameTree.size() + " scale Frames"); + LoggerInterface.loggerEngine.INFO("Target object: " + nodeID); + LoggerInterface.loggerEngine.INFO("Time: " + timeCurrent + "/" + timeTotal); + LoggerInterface.loggerEngine.INFO(positionFrameTree.size() + " position Frames"); + LoggerInterface.loggerEngine.INFO(rotationFrameTree.size() + " rotation Frames"); + LoggerInterface.loggerEngine.INFO(scaleFrameTree.size() + " scale Frames"); } + /** + * Fully describes the channel + */ public void fullDescribeChannel(){ - System.out.println("Target object: " + nodeID); - System.out.println("Time: " + timeCurrent + "/" + timeTotal); - System.out.println(positionFrameTree.size() + " position Frames"); + LoggerInterface.loggerEngine.INFO("Target object: " + nodeID); + LoggerInterface.loggerEngine.INFO("Time: " + timeCurrent + "/" + timeTotal); + LoggerInterface.loggerEngine.INFO(positionFrameTree.size() + " position Frames"); Iterator> frameIterator = positionFrameTree.entrySet().iterator(); while(frameIterator.hasNext()){ - System.out.println(frameIterator.next()); + LoggerInterface.loggerEngine.INFO(frameIterator.next() + ""); } - System.out.println(rotationFrameTree.size() + " rotation Frames"); + LoggerInterface.loggerEngine.INFO(rotationFrameTree.size() + " rotation Frames"); frameIterator = rotationFrameTree.entrySet().iterator(); while(frameIterator.hasNext()){ - System.out.println(frameIterator.next()); + LoggerInterface.loggerEngine.INFO(frameIterator.next() + ""); } - System.out.println(scaleFrameTree.size() + " scale Frames"); + LoggerInterface.loggerEngine.INFO(scaleFrameTree.size() + " scale Frames"); frameIterator = scaleFrameTree.entrySet().iterator(); while(frameIterator.hasNext()){ - System.out.println(frameIterator.next()); + LoggerInterface.loggerEngine.INFO(frameIterator.next() + ""); } } @@ -363,18 +415,37 @@ public class AnimChannel { } } + /** + * Gets the name of the bone associated with the channel + * @return The name of the bone + */ public String getNodeID(){ return nodeID; } + /** + * Adds a position frame to the channel + * @param time The time the frame occurs at + * @param frame The frame itself + */ public void addPositionFrame(double time, Keyframe frame){ positionFrameTree.put(time, frame); } + /** + * Adds a rotation frame to the channel + * @param time The time the frame occurs at + * @param frame The frame itself + */ public void addRotationFrame(double time, Keyframe frame){ rotationFrameTree.put(time, frame); } + /** + * Adds a scale frame to the channel + * @param time The time the frame occurs at + * @param frame The frame itself + */ public void addScaleFrame(double time, Keyframe frame){ scaleFrameTree.put(time, frame); } diff --git a/src/main/java/electrosphere/renderer/anim/Animation.java b/src/main/java/electrosphere/renderer/anim/Animation.java index 3cba8385..46edef68 100644 --- a/src/main/java/electrosphere/renderer/anim/Animation.java +++ b/src/main/java/electrosphere/renderer/anim/Animation.java @@ -9,7 +9,6 @@ import org.joml.Quaterniond; import org.joml.Vector3f; import org.joml.Vector4d; import org.lwjgl.assimp.AIAnimation; -import org.lwjgl.assimp.AIMeshAnim; import org.lwjgl.assimp.AINodeAnim; import org.lwjgl.assimp.AIQuatKey; import org.lwjgl.assimp.AIVectorKey; @@ -17,11 +16,11 @@ import org.lwjgl.assimp.AIVectorKey; import electrosphere.logger.LoggerInterface; /** - * - * @author satellite + * An animation on a model */ public class Animation { + //common animations public static final String ANIMATION_MOVEMENT_STARTUP = "WalkStart"; public static final String ANIMATION_MOVEMENT_MOVE = "Walk"; public static final String ANIMATION_IDLE_1 = "Idle1"; @@ -34,19 +33,46 @@ public class Animation { + /** + * The anim data associated with the animation + */ AIAnimation animData; + + /** + * The name of the animation + */ public String name; - public int ID; - ArrayList nodeChannelData; - ArrayList meshChannelData; + + /** + * The channels that contain the animation data + */ public ArrayList channels; + + /** + * The duration of the animation + */ public double duration = 0; + + /** + * The current time of the animation + */ public double timeCurrent = 0; + + /** + * The ticks per second of animation + */ public double ticksPerSecond; + /** + * The map of bone name to animation channel + */ Map channelMap; - public Animation(AIAnimation animData, int ID){ + /** + * Creates an animation + * @param animData The data for the animation + */ + public Animation(AIAnimation animData){ // //Create structures // @@ -59,16 +85,6 @@ public class Animation { name = animData.mName().dataString(); this.ticksPerSecond = animData.mTicksPerSecond(); this.duration = animData.mDuration() / this.ticksPerSecond; - this.ID = ID; - // - //Print metadata - // - // System.out.println("Animation name: \"" + name + "\""); - // System.out.println("ID:(" + ID + ")"); - // System.out.println("Ticks per second: " + ticksPerSecond); - // System.out.println("Anim sizeof: " + animData.sizeof()); - // System.out.println("Duration: " + duration); - // //Read in anim channels (bone modifications) @@ -200,14 +216,14 @@ public class Animation { } } - //gotta free things - nodeChannelData = null; - meshChannelData = null; } + + /** + * Describes the animation at high level + */ public void describeAnimation(){ LoggerInterface.loggerRenderer.DEBUG("====================="); LoggerInterface.loggerRenderer.DEBUG("Name: \"" + name + "\""); - LoggerInterface.loggerRenderer.DEBUG("ID: " + ID); LoggerInterface.loggerRenderer.DEBUG("Duration: " + duration); LoggerInterface.loggerRenderer.DEBUG("Ticks per second: " + ticksPerSecond); Iterator channelIterator = channels.iterator(); @@ -218,10 +234,13 @@ public class Animation { } LoggerInterface.loggerRenderer.DEBUG("====================="); } + + /** + * Describes the animation is as much detail as possible + */ public void fullDescribeAnimation(){ LoggerInterface.loggerRenderer.DEBUG("====================="); LoggerInterface.loggerRenderer.DEBUG("Name: " + name); - LoggerInterface.loggerRenderer.DEBUG("ID: " + ID); LoggerInterface.loggerRenderer.DEBUG("Duration: " + duration); LoggerInterface.loggerRenderer.DEBUG("Ticks per second: " + ticksPerSecond); Iterator channelIterator = channels.iterator(); @@ -233,19 +252,33 @@ public class Animation { LoggerInterface.loggerRenderer.DEBUG("====================="); } + /** + * Increments time on the animation + * @param time The amount of time to increment by + * @return true if the animation has completed, false otherwise + */ public boolean incrementTime(double time){ timeCurrent += time; - if(timeCurrent > duration){ + if(timeCurrent > duration || timeCurrent < 0){ return true; } else { return false; } } + /** + * Sets the time of the animation + * @param time The time + */ public void setTime(double time){ timeCurrent = time; } + /** + * Gets the channel data for a given bone + * @param name The name of the bone + * @return The channel data if it exists, null otherwise + */ public AnimChannel getChannel(String name){ return channelMap.get(name); } diff --git a/src/main/java/electrosphere/renderer/anim/Keyframe.java b/src/main/java/electrosphere/renderer/anim/Keyframe.java index 5f999c20..bc69afe4 100644 --- a/src/main/java/electrosphere/renderer/anim/Keyframe.java +++ b/src/main/java/electrosphere/renderer/anim/Keyframe.java @@ -7,11 +7,31 @@ import org.joml.Vector3f; * A single keyframe of a single node within an animation */ public class Keyframe implements Comparable{ + + /** + * The time the keyframe occurs at + */ double time; + + /** + * The position of the keyframe + */ Vector3f position; + + /** + * The rotation of the keyframe + */ Quaterniond rotation; + + /** + * The scale of the keyframe + */ Vector3f scale; + /** + * Creates a keyframe + * @param time The time the keyframe occurs at + */ public Keyframe(double time){ this.time = time; } @@ -27,6 +47,10 @@ public class Keyframe implements Comparable{ } } + /** + * Gets the time of the keyframe + * @return The time + */ public double getTime(){ return time; } diff --git a/src/main/java/electrosphere/renderer/model/Model.java b/src/main/java/electrosphere/renderer/model/Model.java index b7f78f6b..ebea22b0 100644 --- a/src/main/java/electrosphere/renderer/model/Model.java +++ b/src/main/java/electrosphere/renderer/model/Model.java @@ -187,7 +187,7 @@ public class Model { rVal.animations = new ArrayList(); rVal.animMap = new HashMap(); for(int i = 0; i < animCount; i++){ - Animation newAnim = new Animation(AIAnimation.create(animBuffer.get(i)), i); + Animation newAnim = new Animation(AIAnimation.create(animBuffer.get(i))); rVal.animations.add(newAnim); rVal.animMap.put(newAnim.name,newAnim); } diff --git a/src/main/java/electrosphere/server/collision/ServerHitboxResolutionCallback.java b/src/main/java/electrosphere/server/collision/ServerHitboxResolutionCallback.java index ab24566b..7c345342 100644 --- a/src/main/java/electrosphere/server/collision/ServerHitboxResolutionCallback.java +++ b/src/main/java/electrosphere/server/collision/ServerHitboxResolutionCallback.java @@ -168,7 +168,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba // //handle attacker - this.handleAttackerCollision(impactorEntity,receiverEntity); + this.handleAttackerCollision(impactorEntity,receiverEntity, isDamageEvent); } if(isBlockEvent){ @@ -192,7 +192,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba // //handle attacker - this.handleAttackerCollision(impactorEntity,receiverEntity); + this.handleAttackerCollision(impactorEntity,receiverEntity, isBlockEvent); } } @@ -200,8 +200,9 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba * Handles collision tracking from the impactor's side * @param impactorEntity The impactor hitbox's parent entity * @param receiverParent The receiver hitbox's parent entity + * @param isBlock true if this is a block, false otherwise */ - private void handleAttackerCollision(Entity impactorEntity, Entity receiverEntity){ + private void handleAttackerCollision(Entity impactorEntity, Entity receiverEntity, boolean isBlock){ boolean receiverIsItem = ItemUtils.isItem(receiverEntity); boolean receiverHasParent = AttachUtils.hasParent(receiverEntity); @@ -210,6 +211,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba if(impactorEntity != null && ServerAttackTree.getServerAttackTree(impactorEntity) != null){ ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorEntity); impactorAttackTree.collideEntity(receiverEntity); + impactorAttackTree.recoilFromBlock(); //if the receiver is an item that is equipped, collide with parent too if(receiverIsItem && receiverHasParent){ impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity)); @@ -222,6 +224,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba } 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); + impactorAttackTree.recoilFromBlock(); //if the receiver is an item that is equipped, collide with parent too if(receiverIsItem && receiverHasParent){ impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity)); diff --git a/src/main/java/electrosphere/server/poseactor/PoseActor.java b/src/main/java/electrosphere/server/poseactor/PoseActor.java index c51fb9d0..38d40883 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseActor.java +++ b/src/main/java/electrosphere/server/poseactor/PoseActor.java @@ -29,17 +29,34 @@ import electrosphere.renderer.model.Bone; */ public class PoseActor { + /** + * The path of the model for the pose actor + */ String modelPath; - //scalar on the speed of animation playback + + /** + * Scalar on the speed of animation playback + */ float animationScalar = 1.0f; - //priority queue of animations to play. Allows masking a higher priority animation over a lower priority one. + + /** + * Priority queue of animations to play. Allows masking a higher priority animation over a lower priority one. + */ Set animationQueue = new TreeSet(); - //bone rotation map. Used to apply rotator functionality to bones (think hair, cloth, and camera rotation on looking) + + /** + * Bone rotation map. Used to apply rotator functionality to bones (think hair, cloth, and camera rotation on looking) + */ Map boneRotators = new HashMap(); - //static morph used to apply an initial, static modification to the layout of bones in the pose model + + /** + * 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 + /** + * The bone groups for this pose actor + */ List boneGroups; @@ -55,6 +72,7 @@ public class PoseActor { //Used to keep track of which animations have completed and therefore should be removed //Separate variable so no concurrent modification to anim lists/maps List toRemoveMasks = new LinkedList(); + /** * Increments time of all currently played animations * @param deltaTime diff --git a/src/main/java/electrosphere/server/poseactor/PoseActorUtils.java b/src/main/java/electrosphere/server/poseactor/PoseActorUtils.java index 14cd9b7c..4a5e58a1 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseActorUtils.java +++ b/src/main/java/electrosphere/server/poseactor/PoseActorUtils.java @@ -1,9 +1,10 @@ package electrosphere.server.poseactor; import electrosphere.engine.Globals; -import electrosphere.entity.Entity; -import electrosphere.entity.EntityUtils; +/** + * Utilities for working with pose actors + */ public class PoseActorUtils { /** diff --git a/src/main/java/electrosphere/server/poseactor/PoseModel.java b/src/main/java/electrosphere/server/poseactor/PoseModel.java index d6335075..e03c3e54 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseModel.java +++ b/src/main/java/electrosphere/server/poseactor/PoseModel.java @@ -98,7 +98,7 @@ public class PoseModel { animations = new ArrayList(); animMap = new HashMap(); for(int i = 0; i < animCount; i++){ - Animation newAnim = new Animation(AIAnimation.create(animBuffer.get(i)), i); + Animation newAnim = new Animation(AIAnimation.create(animBuffer.get(i))); animations.add(newAnim); animMap.put(newAnim.name,newAnim); } -- 2.45.2