life state synchronization
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
161f40ee04
commit
c5f16ae282
@ -8,6 +8,7 @@
|
||||
review combat code (lifestate, damage calculation, etc)
|
||||
audio fx for everything
|
||||
fix rendering pipelines (black when looking at character from angle with item, shadows are not darker color, etc)
|
||||
option to load all data cells in scene on initializing a scene (thereby loading spawn points into memory)
|
||||
|
||||
+ bug fixes
|
||||
fix client-attached models to viewmodel drawing on previous frame
|
||||
|
||||
@ -459,6 +459,8 @@ First animations flickering in first person (enforce animation priority requirem
|
||||
Debug third person animations flickering (attachments not reflecting animations that were played that frame)
|
||||
Small data fix
|
||||
Refactor spawn point to not be global
|
||||
Synchronize objects between client and server
|
||||
Synchronize life state between client and server
|
||||
|
||||
# TODO
|
||||
|
||||
@ -466,6 +468,10 @@ Refactor spawn point to not be global
|
||||
BIG BIG BIG BIG IMMEDIATE TO DO:
|
||||
always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible
|
||||
|
||||
Ability to fully reload game engine state without exiting client
|
||||
- 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
|
||||
|
||||
Unit Testing
|
||||
- Capture image from opengl to pixel-check
|
||||
- Ability to click through the ui via scripts
|
||||
|
||||
@ -284,6 +284,12 @@ public class EntityDataStrings {
|
||||
public static final String VIEW_PITCH = "aiViewPitch";
|
||||
public static final String AI = "ai";
|
||||
|
||||
/**
|
||||
* Life State
|
||||
*/
|
||||
public static final String TREE_CLIENTLIFETREE = "treeClientLifeTree";
|
||||
public static final String TREE_SERVERLIFETREE = "treeServerLifeTree";
|
||||
|
||||
/**
|
||||
* Pose actor
|
||||
*/
|
||||
|
||||
@ -294,6 +294,58 @@ public class StateTransitionUtil {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param stateEnum The enum value for this state
|
||||
* @param animPriority The priority of this state's animations
|
||||
* @param firstPersonAnimation The animation to play in first person. If this is null, it will not play any animation in first person
|
||||
* @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person
|
||||
* @param audioPath The path to an audio file to play on starting the animation. If null, no audio will be played
|
||||
*/
|
||||
public static StateTransitionUtilItem create(
|
||||
Object stateEnum,
|
||||
int animPriority,
|
||||
String firstPersonAnimation,
|
||||
String thirdPersonAnimation,
|
||||
String audioPath
|
||||
){
|
||||
return create(
|
||||
stateEnum,
|
||||
animPriority,
|
||||
firstPersonAnimation,
|
||||
null,
|
||||
thirdPersonAnimation,
|
||||
null,
|
||||
audioPath,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param stateEnum The enum value for this state
|
||||
* @param animPriority The priority of this state's animations
|
||||
* @param thirdPersonAnimation The animation to play in third person. If this is null, it will not play any animation in third person
|
||||
* @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,
|
||||
String thirdPersonAnimation,
|
||||
Runnable onComplete
|
||||
){
|
||||
return create(
|
||||
stateEnum,
|
||||
animPriority,
|
||||
null,
|
||||
null,
|
||||
thirdPersonAnimation,
|
||||
null,
|
||||
null,
|
||||
onComplete
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param stateEnum The enum value for this state
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package electrosphere.entity.state.equip;
|
||||
|
||||
|
||||
import electrosphere.net.synchronization.FieldIdEnums;
|
||||
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
||||
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
|
||||
|
||||
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||
|
||||
@ -0,0 +1,184 @@
|
||||
package electrosphere.entity.state.life;
|
||||
|
||||
|
||||
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
|
||||
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.HealthSystem;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.net.synchronization.annotation.SyncedField;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
|
||||
@SynchronizedBehaviorTree(name = "clientLifeTree", isServer = false, correspondingTree="serverLifeTree")
|
||||
/**
|
||||
* Client life state tree
|
||||
*/
|
||||
public class ClientLifeTree implements BehaviorTree {
|
||||
|
||||
@SynchronizableEnum
|
||||
/**
|
||||
* States available to the life tree
|
||||
*/
|
||||
public static enum LifeStateEnum {
|
||||
ALIVE,
|
||||
DYING,
|
||||
DEAD,
|
||||
}
|
||||
|
||||
//the current state of the tree
|
||||
@SyncedField
|
||||
LifeStateEnum state = LifeStateEnum.ALIVE;
|
||||
|
||||
//the parent entity of this life tree
|
||||
Entity parent;
|
||||
|
||||
//data used to construct the tree
|
||||
HealthSystem healthSystem;
|
||||
|
||||
//state transition util
|
||||
//state transition util
|
||||
StateTransitionUtil stateTransitionUtil;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Gets state.
|
||||
* </p>
|
||||
*/
|
||||
public LifeStateEnum getState(){
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Sets state and handles the synchronization logic for it.
|
||||
* </p>
|
||||
* @param state The value to set state to.
|
||||
*/
|
||||
public void setState(LifeStateEnum state){
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> (initially) Automatically generated </p>
|
||||
* <p> More parameters can be safely added to this method</p>
|
||||
* <p>
|
||||
* Attaches this tree to the entity.
|
||||
* </p>
|
||||
* @param entity The entity to attach to
|
||||
* @param tree The behavior tree to attach
|
||||
*/
|
||||
public static ClientLifeTree attachTree(Entity parent, HealthSystem healthSystem){
|
||||
ClientLifeTree rVal = new ClientLifeTree(parent,healthSystem);
|
||||
//put manual code here (setting params, etc)
|
||||
|
||||
|
||||
//!!WARNING!! from here below should not be touched
|
||||
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
|
||||
parent.putData(EntityDataStrings.TREE_CLIENTLIFETREE, rVal);
|
||||
Globals.clientSceneWrapper.getScene().registerBehaviorTree(rVal);
|
||||
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_CLIENTLIFETREE_ID);
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Detatches this tree from the entity.
|
||||
* </p>
|
||||
* @param entity The entity to detach to
|
||||
* @param tree The behavior tree to detach
|
||||
*/
|
||||
public static void detachTree(Entity entity, BehaviorTree tree){
|
||||
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_CLIENTLIFETREE_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> (initially) Automatically generated </p>
|
||||
* <p> Private constructor to enforce using the attach methods </p>
|
||||
* <p>
|
||||
* Constructor
|
||||
* </p>
|
||||
* @param parent The parent entity of this tree
|
||||
*/
|
||||
public ClientLifeTree(Entity parent, HealthSystem healthSystem){
|
||||
this.parent = parent;
|
||||
this.healthSystem = healthSystem;
|
||||
stateTransitionUtil = StateTransitionUtil.create(parent, false, new StateTransitionUtilItem[]{
|
||||
StateTransitionUtilItem.create(
|
||||
LifeStateEnum.DYING,
|
||||
AnimationPriorities.DEATH,
|
||||
healthSystem.getDyingFirstPersonAnimation(),
|
||||
healthSystem.getDyingThirdPersonAnimation(),
|
||||
healthSystem.getAudioPath()
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Gets the ClientLifeTree of the entity
|
||||
* </p>
|
||||
* @param entity the entity
|
||||
* @return The ClientLifeTree
|
||||
*/
|
||||
public static ClientLifeTree getClientLifeTree(Entity entity){
|
||||
return (ClientLifeTree)entity.getData(EntityDataStrings.TREE_CLIENTLIFETREE);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Converts this enum type to an equivalent short value
|
||||
* </p>
|
||||
* @param enumVal The enum value
|
||||
* @return The short value
|
||||
*/
|
||||
public static short getLifeStateEnumEnumAsShort(LifeStateEnum enumVal){
|
||||
switch(enumVal){
|
||||
case ALIVE:
|
||||
return 0;
|
||||
case DYING:
|
||||
return 1;
|
||||
case DEAD:
|
||||
return 2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Converts a short to the equivalent enum value
|
||||
* </p>
|
||||
* @param shortVal The short value
|
||||
* @return The enum value
|
||||
*/
|
||||
public static LifeStateEnum getLifeStateEnumShortAsEnum(short shortVal){
|
||||
switch(shortVal){
|
||||
case 0:
|
||||
return LifeStateEnum.ALIVE;
|
||||
case 1:
|
||||
return LifeStateEnum.DYING;
|
||||
case 2:
|
||||
return LifeStateEnum.DEAD;
|
||||
default:
|
||||
return LifeStateEnum.ALIVE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,202 +0,0 @@
|
||||
package electrosphere.entity.state.life;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.state.AnimationPriorities;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.game.data.creature.type.CreatureType;
|
||||
import electrosphere.game.data.creature.type.HealthSystem;
|
||||
import electrosphere.net.parser.net.message.CharacterMessage;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||
|
||||
/**
|
||||
* The status of the life value of a given entity
|
||||
*/
|
||||
public class LifeState implements BehaviorTree {
|
||||
|
||||
|
||||
public static enum LifeStateEnum {
|
||||
ALIVE,
|
||||
DYING,
|
||||
DEAD,
|
||||
}
|
||||
|
||||
LifeStateEnum state = LifeStateEnum.ALIVE;
|
||||
|
||||
Entity parent;
|
||||
|
||||
boolean isInvincible;
|
||||
int lifeCurrent;
|
||||
int lifeMax;
|
||||
int iFrameMaxCount;
|
||||
int iFrameCurrent;
|
||||
|
||||
int deathFrameCurrent = -1;
|
||||
|
||||
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
|
||||
|
||||
public LifeState(Entity parent, HealthSystem system){
|
||||
this.parent = parent;
|
||||
isInvincible = false;
|
||||
lifeMax = system.getMaxHealth();
|
||||
lifeCurrent = lifeMax;
|
||||
iFrameMaxCount = system.getOnDamageIFrames();
|
||||
iFrameCurrent = 0;
|
||||
}
|
||||
|
||||
public LifeState(Entity parent, boolean isInvincible, int lifeCurrent, int lifeMax, int iFrameMaxCount) {
|
||||
this.parent = parent;
|
||||
this.isInvincible = isInvincible;
|
||||
this.lifeCurrent = lifeCurrent;
|
||||
this.lifeMax = lifeMax;
|
||||
this.iFrameMaxCount = iFrameMaxCount;
|
||||
}
|
||||
|
||||
public boolean isIsAlive() {
|
||||
return state == LifeStateEnum.ALIVE;
|
||||
}
|
||||
|
||||
public boolean isIsInvincible() {
|
||||
return isInvincible;
|
||||
}
|
||||
|
||||
public int getLifeCurrent() {
|
||||
return lifeCurrent;
|
||||
}
|
||||
|
||||
public int getLifeMax() {
|
||||
return lifeMax;
|
||||
}
|
||||
|
||||
public void setState(LifeStateEnum state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void setIsInvincible(boolean isInvincible) {
|
||||
this.isInvincible = isInvincible;
|
||||
}
|
||||
|
||||
public void setLifeCurrent(int lifeCurrent) {
|
||||
this.lifeCurrent = lifeCurrent;
|
||||
}
|
||||
|
||||
public void setLifeMax(int lifeMax) {
|
||||
this.lifeMax = lifeMax;
|
||||
}
|
||||
|
||||
public int getiFrameMaxCount() {
|
||||
return iFrameMaxCount;
|
||||
}
|
||||
|
||||
public int getiFrameCurrent() {
|
||||
return iFrameCurrent;
|
||||
}
|
||||
|
||||
public void setiFrameMaxCount(int iFrameMaxCount) {
|
||||
this.iFrameMaxCount = iFrameMaxCount;
|
||||
}
|
||||
|
||||
public void setiFrameCurrent(int iFrameCurrent) {
|
||||
this.iFrameCurrent = iFrameCurrent;
|
||||
}
|
||||
|
||||
public void damage(int damage){
|
||||
if(!isInvincible){
|
||||
lifeCurrent = lifeCurrent - damage;
|
||||
isInvincible = true;
|
||||
if(lifeCurrent < 0){
|
||||
lifeCurrent = 0;
|
||||
if(Globals.RUN_SERVER){
|
||||
state = LifeStateEnum.DYING;
|
||||
Vector3d position = EntityUtils.getPosition(parent);
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(
|
||||
EntityMessage.constructKillMessage(
|
||||
Globals.timekeeper.getNumberOfSimFramesElapsed(),
|
||||
parent.getId()
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
iFrameCurrent = iFrameMaxCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void revive(){
|
||||
state = LifeStateEnum.ALIVE;
|
||||
isInvincible = false;
|
||||
lifeCurrent = lifeMax;
|
||||
}
|
||||
|
||||
public void simulate(float deltaTime){
|
||||
for(EntityMessage message : networkMessageQueue){
|
||||
networkMessageQueue.remove(message);
|
||||
long updateTime = message.gettime();
|
||||
switch(message.getMessageSubtype()){
|
||||
case KILL:
|
||||
//start death
|
||||
if(Globals.RUN_CLIENT){
|
||||
state = LifeStateEnum.DYING;
|
||||
lifeCurrent = 0;
|
||||
int frameskip = (int)(Globals.timekeeper.getNumberOfSimFramesElapsed() - message.gettime());
|
||||
deathFrameCurrent = frameskip;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch(state){
|
||||
case ALIVE:
|
||||
if(iFrameCurrent > 0){
|
||||
iFrameCurrent--;
|
||||
if(iFrameCurrent == 0){
|
||||
isInvincible = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DYING:
|
||||
CreatureType creatureType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(CreatureUtils.getType(parent));
|
||||
if(deathFrameCurrent > creatureType.getHealthSystem().getDeathFrames()){
|
||||
state = LifeStateEnum.DEAD;
|
||||
}
|
||||
Actor entityActor = EntityUtils.getActor(parent);
|
||||
if(entityActor != null){
|
||||
String animationToPlay = creatureType.getHealthSystem().getDeathAnimation();
|
||||
if(
|
||||
!entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(animationToPlay)
|
||||
){
|
||||
entityActor.playAnimation(animationToPlay,AnimationPriorities.DEATH);
|
||||
entityActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEAD:
|
||||
if(Globals.RUN_CLIENT && parent == Globals.playerEntity){
|
||||
if(!Globals.RUN_SERVER){
|
||||
//destroy current (client) world stuff
|
||||
//only if not also running server
|
||||
}
|
||||
//submit respawn request
|
||||
Globals.clientConnection.queueOutgoingMessage(
|
||||
CharacterMessage.constructRequestSpawnCharacterMessage()
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void addNetworkMessage(EntityMessage networkMessage) {
|
||||
networkMessageQueue.add(networkMessage);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package electrosphere.entity.state.life;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
|
||||
/**
|
||||
* Utility functions for dealing with life state
|
||||
*/
|
||||
public class LifeUtils {
|
||||
|
||||
|
||||
public static LifeState getLifeState(Entity e){
|
||||
return (LifeState)e.getData(EntityDataStrings.LIFE_STATE);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,200 @@
|
||||
package electrosphere.entity.state.life;
|
||||
|
||||
|
||||
import electrosphere.net.synchronization.FieldIdEnums;
|
||||
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.btree.StateTransitionUtil;
|
||||
import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.state.AnimationPriorities;
|
||||
import electrosphere.entity.state.life.ClientLifeTree.LifeStateEnum;
|
||||
import electrosphere.game.data.creature.type.HealthSystem;
|
||||
import electrosphere.net.synchronization.annotation.SyncedField;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
|
||||
@SynchronizedBehaviorTree(name = "serverLifeTree", isServer = true, correspondingTree="clientLifeTree")
|
||||
/**
|
||||
* Server life state tree
|
||||
*/
|
||||
public class ServerLifeTree implements BehaviorTree {
|
||||
|
||||
//the current state of the tree
|
||||
@SyncedField
|
||||
LifeStateEnum state = LifeStateEnum.ALIVE;
|
||||
|
||||
//the parent entity of this life tree
|
||||
Entity parent;
|
||||
|
||||
//data used to construct the tree
|
||||
HealthSystem healthSystem;
|
||||
|
||||
//state transition util
|
||||
StateTransitionUtil stateTransitionUtil;
|
||||
|
||||
//is the entity invincible
|
||||
boolean isInvincible = false;
|
||||
//the current life value
|
||||
int lifeCurrent = 1;
|
||||
//the maximum life value
|
||||
int lifeMax = 1;
|
||||
//the maximum iframes
|
||||
int iFrameMaxCount = 1;
|
||||
//the current iframe count
|
||||
int iFrameCurrent = 0;
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime) {
|
||||
switch(state){
|
||||
case ALIVE: {
|
||||
if(iFrameCurrent > 0){
|
||||
iFrameCurrent--;
|
||||
if(iFrameCurrent == 0){
|
||||
isInvincible = false;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case DYING: {
|
||||
this.stateTransitionUtil.simulate(LifeStateEnum.DYING);
|
||||
} break;
|
||||
case DEAD: {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revives the entity
|
||||
*/
|
||||
public void revive(){
|
||||
this.setState(LifeStateEnum.ALIVE);
|
||||
isInvincible = false;
|
||||
lifeCurrent = lifeMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Damages the entity
|
||||
* @param damage The amount of damage to inflict
|
||||
*/
|
||||
public void damage(int damage){
|
||||
if(!isInvincible){
|
||||
lifeCurrent = lifeCurrent - damage;
|
||||
isInvincible = true;
|
||||
if(lifeCurrent < 0){
|
||||
lifeCurrent = 0;
|
||||
this.setState(LifeStateEnum.DYING);
|
||||
} else {
|
||||
iFrameCurrent = iFrameMaxCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity is alive
|
||||
* @return true if alive, false otherwise
|
||||
*/
|
||||
public boolean isAlive(){
|
||||
return this.state == LifeStateEnum.ALIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Gets state.
|
||||
* </p>
|
||||
*/
|
||||
public LifeStateEnum getState(){
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Sets state and handles the synchronization logic for it.
|
||||
* </p>
|
||||
* @param state The value to set state to.
|
||||
*/
|
||||
public void setState(LifeStateEnum state){
|
||||
this.state = state;
|
||||
int value = ClientLifeTree.getLifeStateEnumEnumAsShort(state);
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), BehaviorTreeIdEnums.BTREE_SERVERLIFETREE_ID, FieldIdEnums.TREE_SERVERLIFETREE_SYNCEDFIELD_STATE_ID, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> (initially) Automatically generated </p>
|
||||
* <p> More parameters can be safely added to this method</p>
|
||||
* <p>
|
||||
* Attaches this tree to the entity.
|
||||
* </p>
|
||||
* @param entity The entity to attach to
|
||||
* @param tree The behavior tree to attach
|
||||
*/
|
||||
public static ServerLifeTree attachTree(Entity parent, HealthSystem healthSystem){
|
||||
ServerLifeTree rVal = new ServerLifeTree(parent, healthSystem);
|
||||
//put manual code here (setting params, etc)
|
||||
|
||||
|
||||
//!!WARNING!! from here below should not be touched
|
||||
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
|
||||
ServerBehaviorTreeUtils.attachBTreeToEntity(parent, rVal);
|
||||
parent.putData(EntityDataStrings.TREE_SERVERLIFETREE, rVal);
|
||||
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_SERVERLIFETREE_ID);
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Detatches this tree from the entity.
|
||||
* </p>
|
||||
* @param entity The entity to detach to
|
||||
* @param tree The behavior tree to detach
|
||||
*/
|
||||
public static void detachTree(Entity entity, BehaviorTree tree){
|
||||
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_SERVERLIFETREE_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> (initially) Automatically generated </p>
|
||||
* <p> Private constructor to enforce using the attach methods </p>
|
||||
* <p>
|
||||
* Constructor
|
||||
* </p>
|
||||
* @param parent The parent entity of this tree
|
||||
*/
|
||||
public ServerLifeTree(Entity parent, HealthSystem healthSystem){
|
||||
this.parent = parent;
|
||||
this.lifeMax = healthSystem.getMaxHealth();
|
||||
this.lifeCurrent = this.lifeMax;
|
||||
this.iFrameMaxCount = healthSystem.getOnDamageIFrames();
|
||||
this.iFrameCurrent = 0;
|
||||
this.healthSystem = healthSystem;
|
||||
stateTransitionUtil = StateTransitionUtil.create(parent, true, new StateTransitionUtilItem[]{
|
||||
StateTransitionUtilItem.create(
|
||||
LifeStateEnum.DYING,
|
||||
AnimationPriorities.DEATH,
|
||||
this.healthSystem.getDyingThirdPersonAnimation(),
|
||||
() -> {
|
||||
this.setState(LifeStateEnum.DEAD);
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Gets the ServerLifeTree of the entity
|
||||
* </p>
|
||||
* @param entity the entity
|
||||
* @return The ServerLifeTree
|
||||
*/
|
||||
public static ServerLifeTree getServerLifeTree(Entity entity){
|
||||
return (ServerLifeTree)entity.getData(EntityDataStrings.TREE_SERVERLIFETREE);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package electrosphere.entity.state.movement.groundmove;
|
||||
|
||||
|
||||
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||
import electrosphere.net.synchronization.FieldIdEnums;
|
||||
|
||||
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
||||
|
||||
@ -30,7 +30,8 @@ import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.state.inventory.RelationalInventoryState;
|
||||
import electrosphere.entity.state.inventory.ServerInventoryState;
|
||||
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
|
||||
import electrosphere.entity.state.life.LifeState;
|
||||
import electrosphere.entity.state.life.ClientLifeTree;
|
||||
import electrosphere.entity.state.life.ServerLifeTree;
|
||||
import electrosphere.entity.state.movement.AirplaneMovementTree;
|
||||
import electrosphere.entity.state.movement.FallTree;
|
||||
import electrosphere.entity.state.movement.JumpTree;
|
||||
@ -359,8 +360,10 @@ public class CreatureUtils {
|
||||
Globals.clientScene.registerBehaviorTree(rotatorTree);
|
||||
}
|
||||
//add health system
|
||||
rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));
|
||||
Globals.clientScene.registerEntityToTag(rVal, EntityTags.LIFE_STATE);
|
||||
if(rawType.getHealthSystem() != null){
|
||||
ClientLifeTree.attachTree(rVal,rawType.getHealthSystem());
|
||||
Globals.clientScene.registerEntityToTag(rVal, EntityTags.LIFE_STATE);
|
||||
}
|
||||
//idle tree & generic stuff all creatures have
|
||||
ClientIdleTree idleTree = new ClientIdleTree(rVal);
|
||||
rVal.putData(EntityDataStrings.TREE_IDLE, idleTree);
|
||||
@ -661,8 +664,10 @@ public class CreatureUtils {
|
||||
}
|
||||
|
||||
//add health system
|
||||
rVal.putData(EntityDataStrings.LIFE_STATE, new LifeState(rVal, rawType.getHealthSystem()));
|
||||
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.LIFE_STATE);
|
||||
if(rawType.getHealthSystem() != null){
|
||||
ServerLifeTree.attachTree(rVal, rawType.getHealthSystem());
|
||||
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.LIFE_STATE);
|
||||
}
|
||||
//idle tree & generic stuff all creatures have
|
||||
ServerIdleTree.attachTree(rVal);
|
||||
CreatureUtils.setFacingVector(rVal, MathUtils.getOriginVector());
|
||||
|
||||
@ -4,32 +4,71 @@ package electrosphere.game.data.creature.type;
|
||||
* Data about the health of a creature
|
||||
*/
|
||||
public class HealthSystem {
|
||||
int maxHealth;
|
||||
int onDamageIFrames;
|
||||
int deathFrames;
|
||||
String deathAnimation;
|
||||
|
||||
//the maximum health
|
||||
int maxHealth;
|
||||
|
||||
//the number of iframes on taking damage
|
||||
int onDamageIFrames;
|
||||
|
||||
//the third person animation to play when the entity is dying
|
||||
String dyingThirdPersonAnimation;
|
||||
|
||||
//the first person animation to play when the entity is dying
|
||||
String dyingFirstPersonAnimation;
|
||||
|
||||
//The audio file to play when the entity dies
|
||||
String audioPath;
|
||||
|
||||
/**
|
||||
* Gets the maximum health
|
||||
* @return The maximum health
|
||||
*/
|
||||
public int getMaxHealth() {
|
||||
return maxHealth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of iframes on damage
|
||||
* @return The number of iframes
|
||||
*/
|
||||
public int getOnDamageIFrames() {
|
||||
return onDamageIFrames;
|
||||
}
|
||||
|
||||
public int getDeathFrames(){
|
||||
return deathFrames;
|
||||
/**
|
||||
* Gets the animation to play in third person when the entity is dying
|
||||
* @return The animation
|
||||
*/
|
||||
public String getDyingThirdPersonAnimation(){
|
||||
return dyingThirdPersonAnimation;
|
||||
}
|
||||
|
||||
public String getDeathAnimation(){
|
||||
return deathAnimation;
|
||||
/**
|
||||
* Gets the animation to play in first person when the entity is dying
|
||||
* @return The animation
|
||||
*/
|
||||
public String getDyingFirstPersonAnimation(){
|
||||
return dyingFirstPersonAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the audio path to play when the entity is dying
|
||||
* @return The audio path
|
||||
*/
|
||||
public String getAudioPath(){
|
||||
return audioPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones health system data
|
||||
*/
|
||||
public HealthSystem clone(){
|
||||
HealthSystem rVal = new HealthSystem();
|
||||
rVal.maxHealth = maxHealth;
|
||||
rVal.onDamageIFrames = onDamageIFrames;
|
||||
rVal.deathFrames = deathFrames;
|
||||
rVal.dyingThirdPersonAnimation = dyingThirdPersonAnimation;
|
||||
rVal.dyingFirstPersonAnimation = dyingFirstPersonAnimation;
|
||||
return rVal;
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,8 @@ public class BehaviorTreeIdEnums {
|
||||
public static final int BTREE_SERVERGRAVITY_ID = 7;
|
||||
public static final int BTREE_IDLE_ID = 8;
|
||||
public static final int BTREE_SERVERIDLE_ID = 9;
|
||||
public static final int BTREE_CLIENTLIFETREE_ID = 6;
|
||||
public static final int BTREE_SERVERLIFETREE_ID = 13;
|
||||
public static final int BTREE_CLIENTGROUNDMOVEMENTTREE_ID = 10;
|
||||
public static final int BTREE_SERVERGROUNDMOVEMENTTREE_ID = 11;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package electrosphere.net.synchronization;
|
||||
|
||||
|
||||
import electrosphere.entity.state.life.ClientLifeTree;
|
||||
import electrosphere.net.synchronization.FieldIdEnums;
|
||||
import electrosphere.entity.state.block.ClientBlockTree;
|
||||
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
|
||||
@ -165,6 +166,14 @@ public class ClientSynchronizationManager {
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case BehaviorTreeIdEnums.BTREE_SERVERLIFETREE_ID: {
|
||||
switch(message.getfieldId()){
|
||||
case FieldIdEnums.TREE_SERVERLIFETREE_SYNCEDFIELD_STATE_ID:{
|
||||
ClientLifeTree tree = ClientLifeTree.getClientLifeTree(entity);
|
||||
tree.setState(ClientLifeTree.getLifeStateEnumShortAsEnum((short)message.getbTreeValue()));
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case BehaviorTreeIdEnums.BTREE_SERVERGROUNDMOVEMENTTREE_ID: {
|
||||
switch(message.getfieldId()){
|
||||
case FieldIdEnums.TREE_SERVERGROUNDMOVEMENTTREE_SYNCEDFIELD_FACING_ID:{
|
||||
|
||||
@ -19,6 +19,8 @@ public class FieldIdEnums {
|
||||
public static final int TREE_SERVERGRAVITY_SYNCEDFIELD_STATE_ID = 11;
|
||||
public static final int TREE_IDLE_SYNCEDFIELD_STATE_ID = 12;
|
||||
public static final int TREE_SERVERIDLE_SYNCEDFIELD_STATE_ID = 13;
|
||||
public static final int TREE_CLIENTLIFETREE_SYNCEDFIELD_STATE_ID = 10;
|
||||
public static final int TREE_SERVERLIFETREE_SYNCEDFIELD_STATE_ID = 17;
|
||||
public static final int TREE_CLIENTGROUNDMOVEMENTTREE_SYNCEDFIELD_FACING_ID = 14;
|
||||
public static final int TREE_SERVERGROUNDMOVEMENTTREE_SYNCEDFIELD_FACING_ID = 15;
|
||||
|
||||
|
||||
@ -6,18 +6,15 @@ import org.ode4j.ode.DGeom;
|
||||
|
||||
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
||||
import electrosphere.entity.state.life.LifeUtils;
|
||||
import electrosphere.entity.state.life.ServerLifeTree;
|
||||
import electrosphere.entity.state.movement.ProjectileTree;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
|
||||
/**
|
||||
* Callback for managing collisions on the server
|
||||
@ -62,12 +59,13 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
if(isItem){
|
||||
if(hitboxAttachParent != receiverParent){
|
||||
int damage = ItemUtils.getWeaponDataRaw(impactorParent).getDamage();
|
||||
LifeUtils.getLifeState(receiverParent).damage(damage);
|
||||
if(!LifeUtils.getLifeState(receiverParent).isIsAlive()){
|
||||
System.out.println("ServerHitboxResolutionCallback - Unimplemented!!");
|
||||
Realm entityRealm = Globals.realmManager.getEntityRealm(receiverParent);
|
||||
EntityUtils.getPosition(receiverParent).set(entityRealm.getSpawnPoint());
|
||||
LifeUtils.getLifeState(receiverParent).revive();
|
||||
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();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -81,12 +79,13 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
damage = (int)ProjectileTree.getProjectileTree(impactorParent).getDamage();
|
||||
}
|
||||
}
|
||||
LifeUtils.getLifeState(receiverParent).damage(damage);
|
||||
if(!LifeUtils.getLifeState(receiverParent).isIsAlive()){
|
||||
System.out.println("ServerHitboxResolutionCallback - Unimplemented!!");
|
||||
Realm entityRealm = Globals.realmManager.getEntityRealm(receiverParent);
|
||||
EntityUtils.getPosition(receiverParent).set(entityRealm.getSpawnPoint());
|
||||
LifeUtils.getLifeState(receiverParent).revive();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user