block synchronization
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
e671cda62d
commit
8c0a7697d0
@ -257,6 +257,7 @@
|
||||
"firstPersonBone" : "hand.R",
|
||||
"offsetVector" : [0,0,0],
|
||||
"offsetRotation" : [-0.334,0.145,-0.28,0.89],
|
||||
"canBlock" : true,
|
||||
"equipClassWhitelist" : [
|
||||
"tool",
|
||||
"weapon",
|
||||
@ -284,6 +285,22 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"blockSystem" : {
|
||||
"variants": [
|
||||
{
|
||||
"variantId": "blockWeaponRight",
|
||||
"windUpAnimation" : "Jump",
|
||||
"mainAnimation" : "Fall",
|
||||
"cooldownAnimation" : "Land",
|
||||
"defaults" : [
|
||||
{
|
||||
"equipPoint" : "handRight",
|
||||
"itemClassEquipped" : "weapon"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"collidable" : {
|
||||
"type" : "CYLINDER",
|
||||
"dimension1" : 0.1,
|
||||
|
||||
@ -362,6 +362,9 @@ Fix equipping an item spawning two items
|
||||
Fix inventory ui not closing when you hit 'i' key (will need to update utility functions to manage input mode so you're not doing it in callback)
|
||||
Develop debug ui for equip points
|
||||
|
||||
(06/18/2024)
|
||||
Block state synchronization between client and server
|
||||
|
||||
# TODO
|
||||
|
||||
|
||||
@ -375,15 +378,16 @@ Audio FX for everything
|
||||
|
||||
|
||||
= Coding =
|
||||
Sour spot, sweet spot for damage hitboxes and hurtboxes
|
||||
Fix items falling below the ground
|
||||
Control rebinding menu from title screen
|
||||
Sub menu on title screen that allows changing control mappings
|
||||
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
|
||||
- Introduce block hitbox (blockbox) type
|
||||
Enemy AI
|
||||
Probably some kind of tutorial text
|
||||
Network-able ui messages
|
||||
Ability to display video both on title screen as well as in game windows for tutorials
|
||||
better scaffolding for scripting engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
|
||||
better scaffolding for scriptig engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
|
||||
Ability for private realms to have time start/stop based on the player's feedback <-- sync this up to tutorial ui via script
|
||||
|
||||
|
||||
|
||||
@ -24,6 +24,14 @@
|
||||
{
|
||||
"name" : "containerType",
|
||||
"type" : "FIXED_INT"
|
||||
},
|
||||
{
|
||||
"name" : "itemActionCode",
|
||||
"type" : "FIXED_INT"
|
||||
},
|
||||
{
|
||||
"name" : "itemActionCodeState",
|
||||
"type" : "FIXED_INT"
|
||||
}
|
||||
],
|
||||
"messageTypes" : [
|
||||
@ -81,6 +89,15 @@
|
||||
"data" : [
|
||||
"equipPointId"
|
||||
]
|
||||
},
|
||||
{
|
||||
"messageName" : "clientRequestPerformItemAction",
|
||||
"description" : "Requests that the server have the entity perform its equipped item's action for the given equip point",
|
||||
"data" : [
|
||||
"equipPointId",
|
||||
"itemActionCode",
|
||||
"itemActionCodeState"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
40
src/main/java/electrosphere/client/item/ItemActions.java
Normal file
40
src/main/java/electrosphere/client/item/ItemActions.java
Normal file
@ -0,0 +1,40 @@
|
||||
package electrosphere.client.item;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.net.parser.net.message.InventoryMessage;
|
||||
|
||||
/**
|
||||
* Utilities for telling the server to perform actions with an item that the player has equipped
|
||||
*/
|
||||
public class ItemActions {
|
||||
|
||||
//the item action code for left clicking
|
||||
public static final int ITEM_ACTION_CODE_PRIMARY = 0;
|
||||
//the item action code for right clicking
|
||||
public static final int ITEM_ACTION_CODE_SECONDARY = 1;
|
||||
|
||||
//the state for performing the item action code
|
||||
public static final int ITEM_ACTION_CODE_STATE_ON = 1;
|
||||
|
||||
//the state for releasing the item action code
|
||||
public static final int ITEM_ACTION_CODE_STATE_OFF = 0;
|
||||
|
||||
/**
|
||||
* Attempts to perform the secondary item action
|
||||
*/
|
||||
public static void attemptSecondaryItemAction(){
|
||||
//tell the server we want the secondary hand item to START doing something
|
||||
Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage("handRight", ITEM_ACTION_CODE_SECONDARY, ITEM_ACTION_CODE_STATE_ON));
|
||||
//TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server)
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the secondary item action
|
||||
*/
|
||||
public static void releaseSecondaryItemAction(){
|
||||
//tell the server we want the secondary hand item to STOP doing something
|
||||
Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage("handRight", ITEM_ACTION_CODE_SECONDARY, ITEM_ACTION_CODE_STATE_OFF));
|
||||
//TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server)
|
||||
}
|
||||
|
||||
}
|
||||
@ -71,6 +71,7 @@ import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
|
||||
import electrosphere.client.item.ItemActions;
|
||||
import electrosphere.client.targeting.crosshair.Crosshair;
|
||||
import electrosphere.client.terrain.editing.TerrainEditing;
|
||||
import electrosphere.collision.CollisionEngine;
|
||||
@ -85,7 +86,6 @@ import electrosphere.entity.state.attack.ShooterTree;
|
||||
import electrosphere.entity.state.equip.ClientEquipState;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
|
||||
import electrosphere.entity.state.ironsight.IronSightTree;
|
||||
import electrosphere.entity.state.movement.JumpTree;
|
||||
import electrosphere.entity.state.movement.SprintTree;
|
||||
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
|
||||
@ -130,7 +130,7 @@ public class ControlHandler {
|
||||
public static final String INPUT_CODE_DROP = "drop";
|
||||
public static final String INPUT_CODE_INVENTORY_OPEN = "inventoryOpen";
|
||||
public static final String INPUT_CODE_CHARACTER_OPEN = "characterOpen";
|
||||
public static final String INPUT_CODE_IRON_SIGHT = "ironSight";
|
||||
public static final String ITEM_SECONDARY = "actionItemSecondary";
|
||||
public static final String INPUT_CODE_PLACE_TERRAIN = "placeTerrain";
|
||||
public static final String INPUT_CODE_REMOVE_TERRAIN = "removeTerrain";
|
||||
|
||||
@ -312,7 +312,7 @@ public class ControlHandler {
|
||||
handler.addControl(INPUT_CODE_DROP, new Control(ControlType.KEY,GLFW_KEY_Y));
|
||||
handler.addControl(INPUT_CODE_INVENTORY_OPEN, new Control(ControlType.KEY,GLFW_KEY_I));
|
||||
handler.addControl(INPUT_CODE_CHARACTER_OPEN, new Control(ControlType.KEY,GLFW_KEY_C));
|
||||
handler.addControl(INPUT_CODE_IRON_SIGHT, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_RIGHT));
|
||||
handler.addControl(ITEM_SECONDARY, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_RIGHT));
|
||||
|
||||
/*
|
||||
Map the menu navigation controls
|
||||
@ -837,22 +837,12 @@ public class ControlHandler {
|
||||
}
|
||||
}});
|
||||
|
||||
mainGameControlList.add(controls.get(INPUT_CODE_IRON_SIGHT));
|
||||
controls.get(INPUT_CODE_IRON_SIGHT).setOnPress(new ControlMethod() {public void execute() {
|
||||
if(Globals.playerEntity != null){
|
||||
IronSightTree ironSightTree = IronSightTree.getIronSightTree(Globals.playerEntity);
|
||||
if(ironSightTree != null){
|
||||
ironSightTree.start();
|
||||
}
|
||||
}
|
||||
mainGameControlList.add(controls.get(ITEM_SECONDARY));
|
||||
controls.get(ITEM_SECONDARY).setOnPress(new ControlMethod() {public void execute() {
|
||||
ItemActions.attemptSecondaryItemAction();
|
||||
}});
|
||||
controls.get(INPUT_CODE_IRON_SIGHT).setOnRelease(new ControlMethod() {public void execute() {
|
||||
if(Globals.playerEntity != null){
|
||||
IronSightTree ironSightTree = IronSightTree.getIronSightTree(Globals.playerEntity);
|
||||
if(ironSightTree != null){
|
||||
ironSightTree.release();
|
||||
}
|
||||
}
|
||||
controls.get(ITEM_SECONDARY).setOnRelease(new ControlMethod() {public void execute() {
|
||||
ItemActions.releaseSecondaryItemAction();
|
||||
}});
|
||||
|
||||
/*
|
||||
|
||||
@ -20,6 +20,7 @@ import electrosphere.game.server.world.MacroData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.menu.debug.ImGuiWindowMacros;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
import electrosphere.server.MainServerFunctions;
|
||||
import electrosphere.server.simulation.MacroSimulation;
|
||||
|
||||
|
||||
@ -319,21 +320,10 @@ public class Main {
|
||||
|
||||
|
||||
///
|
||||
/// S E R V E R M I C R O S I M U L A T I O N
|
||||
/// S E R V E R M A I N R O U T I N E S
|
||||
///
|
||||
Globals.profiler.beginCpuSample("Server simulation");
|
||||
LoggerInterface.loggerEngine.DEBUG("Begin server micro simulation");
|
||||
if(Globals.realmManager != null){
|
||||
Globals.realmManager.simulate();
|
||||
}
|
||||
|
||||
///
|
||||
/// M A C R O S I M U L A T I O N S T U F F
|
||||
///
|
||||
LoggerInterface.loggerEngine.DEBUG("Begin server macro simulation");
|
||||
if(Globals.macroSimulation != null && Globals.macroSimulation.isReady()){
|
||||
Globals.macroSimulation.simulate();
|
||||
}
|
||||
Globals.profiler.beginCpuSample("Main Server Functions");
|
||||
MainServerFunctions.simulate();
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
|
||||
|
||||
@ -272,6 +272,12 @@ public class EntityDataStrings {
|
||||
*/
|
||||
public static final String IRON_SIGHT_TREE = "ironSightTree";
|
||||
|
||||
/*
|
||||
* Block trees
|
||||
*/
|
||||
public static final String TREE_CLIENTBLOCKTREE = "treeClientBlockTree";
|
||||
public static final String TREE_SERVERBLOCKTREE = "treeServerBlockTree";
|
||||
|
||||
/*
|
||||
AI stuff
|
||||
*/
|
||||
|
||||
@ -1,27 +1,224 @@
|
||||
package electrosphere.entity.state.block;
|
||||
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.game.data.creature.type.block.BlockSystem;
|
||||
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
|
||||
|
||||
import electrosphere.net.synchronization.annotation.SyncedField;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
|
||||
@SynchronizedBehaviorTree(name = "clientBlockTree", isServer = false, correspondingTree="serverBlockTree")
|
||||
/**
|
||||
* Client block tree
|
||||
*/
|
||||
public class ClientBlockTree {
|
||||
public class ClientBlockTree implements BehaviorTree {
|
||||
|
||||
@SynchronizableEnum
|
||||
/**
|
||||
* The state of the block tree
|
||||
*/
|
||||
public enum BlockState {
|
||||
WIND_UP,
|
||||
BLOCKING,
|
||||
COOLDOWN,
|
||||
NOT_BLOCKING,
|
||||
}
|
||||
|
||||
@SyncedField
|
||||
BlockState state;
|
||||
BlockState state = BlockState.NOT_BLOCKING; //the current state
|
||||
|
||||
//the parent entity to this tree
|
||||
Entity parent;
|
||||
|
||||
@SyncedField
|
||||
String currentBlockVariant = null; //The current block variant (depends on equipped items)
|
||||
|
||||
//The data for block animations
|
||||
BlockSystem blockSystem;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private ClientBlockTree(Entity parent, BlockSystem blockSystem){
|
||||
this.parent = parent;
|
||||
this.blockSystem = blockSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime) {
|
||||
Actor actor = EntityUtils.getActor(parent);
|
||||
switch(state){
|
||||
case WIND_UP: {
|
||||
if(actor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
|
||||
String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getWindUpAnimation();
|
||||
if(
|
||||
!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationToPlay)
|
||||
){
|
||||
actor.playAnimation(animationToPlay,1);
|
||||
actor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case BLOCKING: {
|
||||
if(actor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
|
||||
String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getMainAnimation();
|
||||
if(
|
||||
!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationToPlay)
|
||||
){
|
||||
actor.playAnimation(animationToPlay,1);
|
||||
actor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case COOLDOWN: {
|
||||
if(actor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
|
||||
String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getCooldownAnimation();
|
||||
if(
|
||||
!actor.isPlayingAnimation() || !actor.isPlayingAnimation(animationToPlay)
|
||||
){
|
||||
actor.playAnimation(animationToPlay,1);
|
||||
actor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case NOT_BLOCKING: {
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Gets state.
|
||||
* </p>
|
||||
*/
|
||||
public BlockState 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(BlockState 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 ClientBlockTree attachTree(Entity parent, BlockSystem blockSystem){
|
||||
ClientBlockTree rVal = new ClientBlockTree(parent, blockSystem);
|
||||
//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_CLIENTBLOCKTREE, rVal);
|
||||
Globals.clientSceneWrapper.getScene().registerBehaviorTree(rVal);
|
||||
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_CLIENTBLOCKTREE_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_CLIENTBLOCKTREE_ID);
|
||||
}
|
||||
/**
|
||||
* <p>
|
||||
* Gets the ClientBlockTree of the entity
|
||||
* </p>
|
||||
* @param entity the entity
|
||||
* @return The ClientBlockTree
|
||||
*/
|
||||
public static ClientBlockTree getClientBlockTree(Entity entity){
|
||||
return (ClientBlockTree)entity.getData(EntityDataStrings.TREE_CLIENTBLOCKTREE);
|
||||
}
|
||||
/**
|
||||
* <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 getBlockStateEnumAsShort(BlockState enumVal){
|
||||
switch(enumVal){
|
||||
case WIND_UP:
|
||||
return 0;
|
||||
case BLOCKING:
|
||||
return 1;
|
||||
case COOLDOWN:
|
||||
return 2;
|
||||
case NOT_BLOCKING:
|
||||
return 3;
|
||||
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 BlockState getBlockStateShortAsEnum(short shortVal){
|
||||
switch(shortVal){
|
||||
case 0:
|
||||
return BlockState.WIND_UP;
|
||||
case 1:
|
||||
return BlockState.BLOCKING;
|
||||
case 2:
|
||||
return BlockState.COOLDOWN;
|
||||
case 3:
|
||||
return BlockState.NOT_BLOCKING;
|
||||
default:
|
||||
return BlockState.WIND_UP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Gets currentBlockVariant.
|
||||
* </p>
|
||||
*/
|
||||
public String getCurrentBlockVariant(){
|
||||
return currentBlockVariant;
|
||||
}
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Sets currentBlockVariant and handles the synchronization logic for it.
|
||||
* </p>
|
||||
* @param currentBlockVariant The value to set currentBlockVariant to.
|
||||
*/
|
||||
public void setCurrentBlockVariant(String currentBlockVariant){
|
||||
this.currentBlockVariant = currentBlockVariant;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,21 @@
|
||||
package electrosphere.entity.state.block;
|
||||
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
|
||||
|
||||
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||
import electrosphere.server.poseactor.PoseActor;
|
||||
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
||||
|
||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
||||
|
||||
import electrosphere.entity.state.block.ClientBlockTree.BlockState;
|
||||
import electrosphere.game.data.creature.type.block.BlockSystem;
|
||||
import electrosphere.net.synchronization.annotation.SyncedField;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
|
||||
@ -8,9 +23,175 @@ import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
/**
|
||||
* Server block tree
|
||||
*/
|
||||
public class ServerBlockTree {
|
||||
public class ServerBlockTree implements BehaviorTree {
|
||||
|
||||
@SyncedField
|
||||
BlockState state;
|
||||
BlockState state = BlockState.NOT_BLOCKING; //the current state of the tree
|
||||
|
||||
//the parent entity to this tree
|
||||
Entity parent;
|
||||
|
||||
@SyncedField
|
||||
String currentBlockVariant = null; //The current block variant (depends on equipped items)
|
||||
|
||||
//The data for block animations
|
||||
BlockSystem blockSystem;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private ServerBlockTree(Entity parent, BlockSystem blockSystem){
|
||||
this.parent = parent;
|
||||
this.blockSystem = blockSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the block tree
|
||||
*/
|
||||
public void start(){
|
||||
setState(BlockState.WIND_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the block tree
|
||||
*/
|
||||
public void stop(){
|
||||
setState(BlockState.COOLDOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime) {
|
||||
PoseActor poseActor = EntityUtils.getPoseActor(parent);
|
||||
switch(state){
|
||||
case WIND_UP: {
|
||||
if(poseActor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
|
||||
String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getWindUpAnimation();
|
||||
if(
|
||||
!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay)
|
||||
){
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case BLOCKING: {
|
||||
if(poseActor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
|
||||
String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getMainAnimation();
|
||||
if(
|
||||
!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay)
|
||||
){
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case COOLDOWN: {
|
||||
if(poseActor != null && blockSystem.getBlockVariant(currentBlockVariant) != null){
|
||||
String animationToPlay = blockSystem.getBlockVariant(currentBlockVariant).getCooldownAnimation();
|
||||
if(
|
||||
!poseActor.isPlayingAnimation() || !poseActor.isPlayingAnimation(animationToPlay)
|
||||
){
|
||||
poseActor.playAnimation(animationToPlay,1);
|
||||
poseActor.incrementAnimationTime(0.0001);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case NOT_BLOCKING: {
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block system data for this tree
|
||||
* @return the data if it exists, otherwise null
|
||||
*/
|
||||
public BlockSystem getBlockSystem(){
|
||||
return this.blockSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Gets state.
|
||||
* </p>
|
||||
*/
|
||||
public BlockState 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(BlockState state){
|
||||
this.state = state;
|
||||
int value = ClientBlockTree.getBlockStateEnumAsShort(state);
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 3, 8, 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 ServerBlockTree attachTree(Entity parent, BlockSystem blockSystem){
|
||||
ServerBlockTree rVal = new ServerBlockTree(parent, blockSystem);
|
||||
//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_SERVERBLOCKTREE, rVal);
|
||||
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_SERVERBLOCKTREE_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_SERVERBLOCKTREE_ID);
|
||||
}
|
||||
/**
|
||||
* <p>
|
||||
* Gets the ServerBlockTree of the entity
|
||||
* </p>
|
||||
* @param entity the entity
|
||||
* @return The ServerBlockTree
|
||||
*/
|
||||
public static ServerBlockTree getServerBlockTree(Entity entity){
|
||||
return (ServerBlockTree)entity.getData(EntityDataStrings.TREE_SERVERBLOCKTREE);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Gets currentBlockVariant.
|
||||
* </p>
|
||||
*/
|
||||
public String getCurrentBlockVariant(){
|
||||
return currentBlockVariant;
|
||||
}
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
* <p>
|
||||
* Sets currentBlockVariant and handles the synchronization logic for it.
|
||||
* </p>
|
||||
* @param currentBlockVariant The value to set currentBlockVariant to.
|
||||
*/
|
||||
public void setCurrentBlockVariant(String currentBlockVariant){
|
||||
this.currentBlockVariant = currentBlockVariant;
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStringStateMessage(parent.getId(), 3, 9, currentBlockVariant));
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,8 +107,11 @@ public class ClientEquipState implements BehaviorTree {
|
||||
List<String> pointEquipClassList = point.getEquipClassWhitelist();
|
||||
boolean itemIsInPointWhitelist = pointEquipClassList.contains(equipItemClass);
|
||||
if(!hasEquipped && targetIsItem && !targetIsAttached && itemIsInPointWhitelist){
|
||||
|
||||
//
|
||||
//visual transforms
|
||||
if(targetHasWhitelist){
|
||||
//by attaching are we going to be replacing meshes?
|
||||
//depends on the type of creature, must be replacing a mesh
|
||||
String parentCreatureId = CreatureUtils.getType(parent);
|
||||
List<EquipWhitelist> whitelist = ItemUtils.getEquipWhitelist(toEquip);
|
||||
for(EquipWhitelist whitelistItem : whitelist){
|
||||
@ -141,7 +144,7 @@ public class ClientEquipState implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//since we're not replacing meshes we must be attaching to a bone
|
||||
//does not depend on the type of creature, must be attaching to a bone
|
||||
equipMap.put(point.getEquipPointId(),toEquip);
|
||||
if(Globals.controlHandler.cameraIsThirdPerson()){
|
||||
AttachUtils.clientAttachEntityToEntityAtBone(parent, toEquip, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
|
||||
@ -284,8 +287,11 @@ public class ClientEquipState implements BehaviorTree {
|
||||
Entity equipped = equipMap.remove(pointId);
|
||||
if(equipped != null){
|
||||
boolean targetHasWhitelist = ItemUtils.hasEquipList(equipped);
|
||||
|
||||
//
|
||||
//visual transforms
|
||||
if(targetHasWhitelist){
|
||||
//by attaching are we going to be replacing meshes?
|
||||
//depends on the type of creature, must be replacing meshes
|
||||
String parentCreatureId = CreatureUtils.getType(parent);
|
||||
List<EquipWhitelist> whitelist = ItemUtils.getEquipWhitelist(equipped);
|
||||
for(EquipWhitelist whitelistItem : whitelist){
|
||||
@ -304,6 +310,7 @@ public class ClientEquipState implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//does not depend on the type of creature
|
||||
AttachUtils.clientDetatchEntityFromEntityAtBone(parent, equipped);
|
||||
EntityUtils.cleanUpEntity(equipped);
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityTags;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.state.block.ServerBlockTree;
|
||||
import electrosphere.entity.state.gravity.GravityUtils;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.state.inventory.RelationalInventoryState;
|
||||
@ -28,6 +29,8 @@ import electrosphere.entity.state.inventory.UnrelationalInventoryState;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.game.data.creature.type.block.BlockSystem;
|
||||
import electrosphere.game.data.creature.type.block.BlockVariant;
|
||||
import electrosphere.game.data.creature.type.equip.EquipPoint;
|
||||
import electrosphere.game.data.item.type.EquipWhitelist;
|
||||
import electrosphere.net.parser.net.message.InventoryMessage;
|
||||
@ -46,9 +49,12 @@ import electrosphere.server.datacell.utils.ServerEntityTagUtils;
|
||||
*/
|
||||
public class ServerEquipState implements BehaviorTree {
|
||||
|
||||
//the parent entity of this equip state
|
||||
Entity parent;
|
||||
|
||||
//the list of available equip points
|
||||
List<EquipPoint> equipPoints = new LinkedList<EquipPoint>();
|
||||
//the map of equip point id -> entity equipped at said point
|
||||
Map<String,Entity> equipMap = new HashMap<String,Entity>();
|
||||
|
||||
public ServerEquipState(Entity parent, List<EquipPoint> equipPoints){
|
||||
@ -76,6 +82,11 @@ public class ServerEquipState implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to equip an item
|
||||
* @param inInventoryEntity The item to equip
|
||||
* @param point The point to equip to
|
||||
*/
|
||||
public void serverAttemptEquip(Entity inInventoryEntity, EquipPoint point){
|
||||
boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId());
|
||||
boolean targetIsItem = ItemUtils.isItem(inInventoryEntity);
|
||||
@ -91,8 +102,10 @@ public class ServerEquipState implements BehaviorTree {
|
||||
//bind in world with in inventory
|
||||
ItemUtils.setRealWorldEntity(inInventoryEntity, inWorldItem);
|
||||
|
||||
//
|
||||
//Visual transforms
|
||||
if(targetHasWhitelist){
|
||||
//by attaching are we going to be replacing meshes?
|
||||
//depends on the type of creature
|
||||
String parentCreatureId = CreatureUtils.getType(parent);
|
||||
List<EquipWhitelist> whitelist = ItemUtils.getEquipWhitelist(inWorldItem);
|
||||
for(EquipWhitelist whitelistItem : whitelist){
|
||||
@ -117,7 +130,7 @@ public class ServerEquipState implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//since we're not replacing meshes we must be attaching to a bone
|
||||
//does not depend on the type of creature
|
||||
equipMap.put(point.getEquipPointId(),inWorldItem);
|
||||
AttachUtils.serverAttachEntityToEntityAtBone(parent, inWorldItem, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotation()));
|
||||
if(inWorldItem.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && inWorldItem.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){
|
||||
@ -128,6 +141,11 @@ public class ServerEquipState implements BehaviorTree {
|
||||
ServerEntityTagUtils.removeTagFromEntity(inWorldItem, EntityTags.TARGETABLE);
|
||||
GravityUtils.serverAttemptDeactivateGravity(inWorldItem);
|
||||
}
|
||||
|
||||
//
|
||||
//update block state based on what we have equipped
|
||||
this.updateBlockVariant();
|
||||
|
||||
//we need to send two packets
|
||||
//1) Remove item from original inventory
|
||||
//2) Add item with ID to "equipped" inventory
|
||||
@ -171,6 +189,11 @@ public class ServerEquipState implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an equip point by its name
|
||||
* @param name The name of the equip point
|
||||
* @return The equip point if it exists, null otherwise
|
||||
*/
|
||||
public EquipPoint getEquipPoint(String name){
|
||||
for(EquipPoint point : equipPoints){
|
||||
if(point.getEquipPointId().equals(name)){
|
||||
@ -180,6 +203,11 @@ public class ServerEquipState implements BehaviorTree {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item equipped at a point
|
||||
* @param point The point id
|
||||
* @return The item if it exists, null otherwise
|
||||
*/
|
||||
public Entity getEquippedItemAtPoint(String point){
|
||||
return equipMap.get(point);
|
||||
}
|
||||
@ -223,6 +251,10 @@ public class ServerEquipState implements BehaviorTree {
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Commands the equip state to unequip an item at a given equip point
|
||||
* @param pointId The equip point
|
||||
*/
|
||||
public void commandAttemptUnequip(String pointId){
|
||||
boolean hasEquipped = hasEquippedAtPoint(pointId);
|
||||
if(hasEquipped){
|
||||
@ -278,10 +310,17 @@ public class ServerEquipState implements BehaviorTree {
|
||||
// inventory.addItem(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the transform to unequip an item from an equip point
|
||||
* @param pointId The equip point id
|
||||
*/
|
||||
public void serverTransformUnequipPoint(String pointId){
|
||||
Entity equipped = equipMap.remove(pointId);
|
||||
if(equipped != null){
|
||||
boolean targetHasWhitelist = ItemUtils.hasEquipList(equipped);
|
||||
|
||||
//
|
||||
//Visual transforms
|
||||
if(targetHasWhitelist){
|
||||
//have to do fancy mesh removal nonsense
|
||||
//basically the reverse of below
|
||||
@ -319,13 +358,50 @@ public class ServerEquipState implements BehaviorTree {
|
||||
AttachUtils.serverDetatchEntityFromEntityAtBone(parent, equipped);
|
||||
EntityUtils.cleanUpEntity(equipped);
|
||||
}
|
||||
|
||||
//
|
||||
//update block state based on what we have equipped
|
||||
this.updateBlockVariant();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether an item is equipped at a point or not
|
||||
* @param point THe point to check
|
||||
* @return true if an item is equipped at the point, false otherwise
|
||||
*/
|
||||
public boolean hasEquippedAtPoint(String point){
|
||||
return equipMap.containsKey(point);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the server block variant based on what item is equipped
|
||||
*/
|
||||
private void updateBlockVariant(){
|
||||
ServerBlockTree blockTree = ServerBlockTree.getServerBlockTree(parent);
|
||||
if(blockTree != null){
|
||||
|
||||
List<EquipPoint> pointsThatCanBlock = new LinkedList<EquipPoint>();
|
||||
for(EquipPoint point : equipPoints){
|
||||
if(point.getCanBlock()){
|
||||
pointsThatCanBlock.add(point);
|
||||
}
|
||||
}
|
||||
|
||||
BlockSystem blockData = blockTree.getBlockSystem();
|
||||
for(EquipPoint point : pointsThatCanBlock){
|
||||
Entity item = getEquippedItemAtPoint(point.getEquipPointId());
|
||||
if(item != null){
|
||||
BlockVariant blockVariant = blockData.getVariantForPointWithItem(point.getEquipPointId(),ItemUtils.getEquipClass(item));
|
||||
|
||||
//TODO: refactor to allow sending more than one variant at a time
|
||||
//ie if you have two items equipped and you want to block with both
|
||||
blockTree.setCurrentBlockVariant(blockVariant.getVariantId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime) {
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ public class ServerGravityTree implements BehaviorTree {
|
||||
public void setState(GravityTreeState state){
|
||||
this.state = state;
|
||||
int value = ClientGravityTree.getGravityTreeStateEnumAsShort(state);
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 5, 7, value));
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 7, 11, value));
|
||||
}
|
||||
/**
|
||||
* <p> (initially) Automatically generated </p>
|
||||
|
||||
@ -215,4 +215,14 @@ public class ClientIdleTree implements BehaviorTree {
|
||||
public void setState(IdleTreeState state){
|
||||
this.state = state;
|
||||
}
|
||||
/**
|
||||
* <p>
|
||||
* Gets the ClientIdleTree of the entity
|
||||
* </p>
|
||||
* @param entity the entity
|
||||
* @return The ClientIdleTree
|
||||
*/
|
||||
public static ClientIdleTree getClientIdleTree(Entity entity){
|
||||
return (ClientIdleTree)entity.getData(EntityDataStrings.TREE_IDLE);
|
||||
}
|
||||
}
|
||||
@ -190,7 +190,7 @@ public class ServerIdleTree implements BehaviorTree {
|
||||
public void setState(IdleTreeState state){
|
||||
this.state = state;
|
||||
int value = ClientIdleTree.getIdleTreeStateEnumAsShort(state);
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 7, 9, value));
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 9, 13, value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
package electrosphere.entity.state.ironsight;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.types.camera.CameraEntityUtils;
|
||||
|
||||
public class IronSightTree implements BehaviorTree {
|
||||
|
||||
static enum IronSightTreeState {
|
||||
ACTIVE,
|
||||
INACTIVE,
|
||||
}
|
||||
|
||||
IronSightTreeState state = IronSightTreeState.INACTIVE;
|
||||
boolean cameraZoomedIn = false;
|
||||
|
||||
float regularRadius = 1.0f;
|
||||
float zoomedInRadius = 0.1f;
|
||||
Vector3f offcenterOffset = new Vector3f(-0.1f,1,0);
|
||||
|
||||
|
||||
public void start(){
|
||||
state = IronSightTreeState.ACTIVE;
|
||||
}
|
||||
|
||||
public void release(){
|
||||
state = IronSightTreeState.INACTIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime) {
|
||||
switch(state){
|
||||
case ACTIVE:
|
||||
if(!cameraZoomedIn){
|
||||
cameraZoomedIn = true;
|
||||
CameraEntityUtils.setOrbitalCameraDistance(Globals.playerCamera, zoomedInRadius);
|
||||
Globals.cameraHandler.updateRadialOffset(new Vector3f(0,1,0.5f));
|
||||
Globals.cameraHandler.updateGlobalCamera();
|
||||
}
|
||||
break;
|
||||
case INACTIVE:
|
||||
if(cameraZoomedIn){
|
||||
cameraZoomedIn = false;
|
||||
CameraEntityUtils.setOrbitalCameraDistance(Globals.playerCamera, regularRadius);
|
||||
Globals.cameraHandler.updateRadialOffset(new Vector3f(0,1,0));
|
||||
Globals.cameraHandler.updateGlobalCamera();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static IronSightTree getIronSightTree(Entity creature){
|
||||
Object rVal;
|
||||
if((rVal = creature.getData(EntityDataStrings.IRON_SIGHT_TREE)) != null && rVal instanceof IronSightTree){
|
||||
return (IronSightTree) rVal;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void attachIronSightTree(Entity player){
|
||||
IronSightTree ironSightTree = new IronSightTree();
|
||||
player.putData(EntityDataStrings.IRON_SIGHT_TREE, ironSightTree);
|
||||
Globals.clientSceneWrapper.getScene().registerBehaviorTree(ironSightTree);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
package electrosphere.entity.state.movement.groundmove;
|
||||
|
||||
|
||||
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
|
||||
|
||||
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
||||
|
||||
import electrosphere.net.synchronization.BehaviorTreeIdEnums;
|
||||
@ -676,7 +678,7 @@ public class ServerGroundMovementTree implements BehaviorTree {
|
||||
public void setFacing(MovementRelativeFacing facing){
|
||||
this.facing = facing;
|
||||
int value = ClientGroundMovementTree.getMovementRelativeFacingEnumAsShort(facing);
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 9, 11, value));
|
||||
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 11, 15, value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -540,18 +540,42 @@ public class AttachUtils {
|
||||
return (Matrix4f)e.getData(EntityDataStrings.ATTACH_TRANSFORM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the parent entity has attached child entities
|
||||
* @param e The parent entity
|
||||
* @return true if there are attached child entities, false otherwise
|
||||
*/
|
||||
public static boolean hasChildren(Entity e){
|
||||
return e.containsKey(EntityDataStrings.ATTACH_CHILDREN_LIST) && !getChildrenList(e).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attached entity's posiiton offset
|
||||
* @param e The attached entity
|
||||
* @return The position offset
|
||||
*/
|
||||
public static Vector3d getAttachPositionOffset(Entity e){
|
||||
return (Vector3d)e.getData(EntityDataStrings.ATTACH_POSITION_OFFSET);
|
||||
}
|
||||
|
||||
public static LinkedList<Entity> getChildrenList(Entity e){
|
||||
return (LinkedList<Entity>)e.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
|
||||
/**
|
||||
* Gets the list of entities attached to this parent entity
|
||||
* <p>
|
||||
* NOTE: This can return an empty list of an entity has been attached to this one prior
|
||||
* EVEN if it has since been unattached
|
||||
* </p>
|
||||
* @param parentEntity
|
||||
* @return The list of entities that are attached to this parent entity, or null if undefined
|
||||
*/
|
||||
public static LinkedList<Entity> getChildrenList(Entity parentEntity){
|
||||
return (LinkedList<Entity>)parentEntity.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the equip point's rotation offset in quaterniond form
|
||||
* @param values The list of raw float values
|
||||
* @return The quaterniond containing those values or an identity quaterniond if no such values exist
|
||||
*/
|
||||
public static Quaterniond getEquipPointRotationOffset(List<Float> values){
|
||||
if(values.size() > 0){
|
||||
return new Quaterniond(values.get(0),values.get(1),values.get(2),values.get(3));
|
||||
|
||||
@ -24,6 +24,8 @@ import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.state.attack.ClientAttackTree;
|
||||
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.collidable.ClientCollidableTree;
|
||||
import electrosphere.entity.state.collidable.ServerCollidableTree;
|
||||
import electrosphere.entity.state.equip.ClientEquipState;
|
||||
@ -229,6 +231,9 @@ public class CreatureUtils {
|
||||
ClientEquipState.attachTree(rVal, rawType.getEquipPoints());
|
||||
rVal.putData(EntityDataStrings.EQUIP_INVENTORY, RelationalInventoryState.buildRelationalInventoryStateFromEquipList(rawType.getEquipPoints()));
|
||||
}
|
||||
if(rawType.getBlockSystem() != null){
|
||||
ClientBlockTree.attachTree(rVal, rawType.getBlockSystem());
|
||||
}
|
||||
for(String token : rawType.getTokens()){
|
||||
switch(token){
|
||||
case "BLENDER_TRANSFORM":
|
||||
@ -517,6 +522,9 @@ public class CreatureUtils {
|
||||
ServerEquipState.setEquipState(rVal, new ServerEquipState(rVal,rawType.getEquipPoints()));
|
||||
rVal.putData(EntityDataStrings.EQUIP_INVENTORY, RelationalInventoryState.buildRelationalInventoryStateFromEquipList(rawType.getEquipPoints()));
|
||||
}
|
||||
if(rawType.getBlockSystem() != null){
|
||||
ServerBlockTree.attachTree(rVal, rawType.getBlockSystem());
|
||||
}
|
||||
for(String token : rawType.getTokens()){
|
||||
switch(token){
|
||||
case "BLENDER_TRANSFORM": {
|
||||
|
||||
@ -4,6 +4,7 @@ import electrosphere.game.data.collidable.CollidableTemplate;
|
||||
import electrosphere.game.data.collidable.HitboxData;
|
||||
import electrosphere.game.data.creature.type.attack.AttackMove;
|
||||
import electrosphere.game.data.creature.type.attack.AttackMoveResolver;
|
||||
import electrosphere.game.data.creature.type.block.BlockSystem;
|
||||
import electrosphere.game.data.creature.type.equip.EquipPoint;
|
||||
import electrosphere.game.data.creature.type.movement.MovementSystem;
|
||||
import electrosphere.game.data.creature.type.rotator.RotatorSystem;
|
||||
@ -29,6 +30,7 @@ public class CreatureType {
|
||||
String modelPath;
|
||||
ViewModelData viewModelData;
|
||||
IdleData idleData;
|
||||
BlockSystem blockSystem;
|
||||
|
||||
AttackMoveResolver attackMoveResolver;
|
||||
|
||||
@ -95,6 +97,10 @@ public class CreatureType {
|
||||
public IdleData getIdleData(){
|
||||
return idleData;
|
||||
}
|
||||
|
||||
public BlockSystem getBlockSystem(){
|
||||
return blockSystem;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
package electrosphere.game.data.creature.type.block;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Stores data related to an entity blocking attacks
|
||||
*/
|
||||
public class BlockSystem {
|
||||
|
||||
//blocking with a weapon equipped in the right hand
|
||||
//NOTE: the names provided here should line up with the actual field names on this object
|
||||
public static final String BLOCK_VARIANT_WEAPON_RIGHT = "blockWeaponRight";
|
||||
|
||||
//the list of block variants
|
||||
List<BlockVariant> variants;
|
||||
|
||||
/**
|
||||
* Gets the list of block variants
|
||||
* @return the list
|
||||
*/
|
||||
public List<BlockVariant> getAllVariants(){
|
||||
return variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a block variant from its variant string
|
||||
* @param variantString The variant string
|
||||
* @return The block variant if it exists, null otherwise
|
||||
*/
|
||||
public BlockVariant getBlockVariant(String variantString){
|
||||
for(BlockVariant variant : variants){
|
||||
if(variant.variantId.equals(variantString)){
|
||||
return variant;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block variant that is default for the provided equip point when the provided item class is equipped to that point
|
||||
* @param equipPoint The equip point
|
||||
* @param itemClass The item class
|
||||
* @return The block variant if it exists, null otherwise
|
||||
*/
|
||||
public BlockVariant getVariantForPointWithItem(String equipPoint, String itemClass){
|
||||
for(BlockVariant variant : variants){
|
||||
for(VariantDefaults variantDefault : variant.getDefaults()){
|
||||
if(variantDefault.equipPoint.equals(equipPoint) && variantDefault.itemClassEquipped.equals(itemClass)){
|
||||
return variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
package electrosphere.game.data.creature.type.block;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* hand vs two handing a sword with your right hand.
|
||||
*/
|
||||
public class BlockVariant {
|
||||
|
||||
//The id of the block variant
|
||||
String variantId;
|
||||
|
||||
//the animation to play when winding up
|
||||
String windUpAnimation;
|
||||
|
||||
//the main animation to play while blocking
|
||||
String mainAnimation;
|
||||
|
||||
//the animation to play when cooling down
|
||||
String cooldownAnimation;
|
||||
|
||||
//the list of default equipment cases that this variant should be used for
|
||||
List<VariantDefaults> defaults;
|
||||
|
||||
/**
|
||||
* The id of the block variant
|
||||
* @return
|
||||
*/
|
||||
public String getVariantId(){
|
||||
return variantId;
|
||||
}
|
||||
|
||||
/**
|
||||
* The animation to play when winding up
|
||||
* @return
|
||||
*/
|
||||
public String getWindUpAnimation(){
|
||||
return windUpAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main animation to play while blocking
|
||||
* @return
|
||||
*/
|
||||
public String getMainAnimation(){
|
||||
return mainAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* The animation to play when cooling down
|
||||
* @return
|
||||
*/
|
||||
public String getCooldownAnimation(){
|
||||
return cooldownAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* the list of default equipment cases that this variant should be used for
|
||||
* @return
|
||||
*/
|
||||
public List<VariantDefaults> getDefaults(){
|
||||
return defaults;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package electrosphere.game.data.creature.type.block;
|
||||
|
||||
/**
|
||||
* Equip point cases that this variant is used as the default for
|
||||
* IE, if you create a variant default for "handRight, weapon",
|
||||
* that means this should be used as the default variant for when
|
||||
* the handRight equip point has a weapon equipped and the block
|
||||
* tree is triggered
|
||||
*/
|
||||
public class VariantDefaults {
|
||||
|
||||
//the equip point
|
||||
String equipPoint;
|
||||
|
||||
//the class of item equipped to that equip point
|
||||
String itemClassEquipped;
|
||||
|
||||
/**
|
||||
* the equip point
|
||||
* @return
|
||||
*/
|
||||
public String getEquipPoint(){
|
||||
return equipPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* the class of item equipped to that equip point
|
||||
* @return
|
||||
*/
|
||||
public String getItemClassEquipped(){
|
||||
return itemClassEquipped;
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,6 +17,8 @@ public class EquipPoint {
|
||||
List<Float> offsetVector;
|
||||
//the rotation to apply to the items that are attached to the bone
|
||||
List<Float> offsetRotation;
|
||||
//signals that this equip point can block
|
||||
boolean canBlock;
|
||||
//the equip classes that are whitelisted for this equip point
|
||||
List<String> equipClassWhitelist;
|
||||
|
||||
@ -68,6 +70,14 @@ public class EquipPoint {
|
||||
this.offsetRotation = offsetRotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that this equip point can block
|
||||
* @return true if can block, false otherwise
|
||||
*/
|
||||
public boolean getCanBlock(){
|
||||
return canBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the equip classes that are whitelisted for this equip point
|
||||
* @return the classes
|
||||
|
||||
@ -4,50 +4,97 @@ import electrosphere.game.data.collidable.CollidableTemplate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Data on a given item
|
||||
*/
|
||||
public class Item {
|
||||
|
||||
//the id of the item
|
||||
String itemId;
|
||||
//the model path of the item
|
||||
String modelPath;
|
||||
//tokens associated with this item type
|
||||
List<String> tokens;
|
||||
//the collidable data for the item
|
||||
CollidableTemplate collidable;
|
||||
//the equip whitelist for this item (what creatures can equip this item?)
|
||||
List<EquipWhitelist> equipWhitelist;
|
||||
//the idle animation for the item
|
||||
String idleAnim;
|
||||
//the path for the icon texture for this item
|
||||
String iconPath;
|
||||
//the class of item
|
||||
String equipClass;
|
||||
//weapon data for this item if it is an item
|
||||
WeaponData weaponData;
|
||||
|
||||
/**
|
||||
* the id of the item
|
||||
* @return
|
||||
*/
|
||||
public String getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* the model path of the item
|
||||
* @return
|
||||
*/
|
||||
public String getModelPath() {
|
||||
return modelPath;
|
||||
}
|
||||
|
||||
/*
|
||||
* tokens associated with this item type
|
||||
*/
|
||||
public List<String> getTokens() {
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* the collidable data for the item
|
||||
* @return
|
||||
*/
|
||||
public CollidableTemplate getCollidable(){
|
||||
return collidable;
|
||||
}
|
||||
|
||||
/**
|
||||
* the equip whitelist for this item (what creatures can equip this item?)
|
||||
* @return
|
||||
*/
|
||||
public List<EquipWhitelist> getEquipWhitelist(){
|
||||
return equipWhitelist;
|
||||
}
|
||||
|
||||
/**
|
||||
* the idle animation for the item
|
||||
* @return
|
||||
*/
|
||||
public String getIdleAnim(){
|
||||
return idleAnim;
|
||||
}
|
||||
|
||||
/**
|
||||
* the path for the icon texture for this item
|
||||
* @return
|
||||
*/
|
||||
public String getIconPath(){
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* the class of item
|
||||
* @return
|
||||
*/
|
||||
public String getEquipClass(){
|
||||
return equipClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* weapon data for this item if it is an item
|
||||
* @return
|
||||
*/
|
||||
public WeaponData getWeaponData(){
|
||||
return weaponData;
|
||||
}
|
||||
|
||||
@ -1,14 +1,6 @@
|
||||
package electrosphere.net.client.protocol;
|
||||
|
||||
import electrosphere.client.scene.ClientWorldData;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.Main;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.parser.net.message.AuthMessage;
|
||||
import electrosphere.net.parser.net.message.CharacterMessage;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
@ -19,8 +11,6 @@ import electrosphere.net.parser.net.message.PlayerMessage;
|
||||
import electrosphere.net.parser.net.message.ServerMessage;
|
||||
import electrosphere.net.parser.net.message.SynchronizationMessage;
|
||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class ClientProtocol {
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.equip.ClientEquipState;
|
||||
import electrosphere.entity.state.inventory.ClientInventoryState;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.game.data.creature.type.equip.EquipPoint;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.parser.net.message.InventoryMessage;
|
||||
@ -70,6 +69,7 @@ public class InventoryProtocol {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLIENTREQUESTPERFORMITEMACTION:
|
||||
case CLIENTREQUESTUNEQUIPITEM:
|
||||
case CLIENTREQUESTEQUIPITEM:
|
||||
//silently ignore
|
||||
|
||||
@ -15,6 +15,7 @@ public class InventoryMessage extends NetworkMessage {
|
||||
SERVERCOMMANDEQUIPITEM,
|
||||
SERVERCOMMANDUNEQUIPITEM,
|
||||
CLIENTREQUESTUNEQUIPITEM,
|
||||
CLIENTREQUESTPERFORMITEMACTION,
|
||||
}
|
||||
|
||||
InventoryMessageType messageType;
|
||||
@ -23,6 +24,8 @@ public class InventoryMessage extends NetworkMessage {
|
||||
int entityId;
|
||||
int equipperId;
|
||||
int containerType;
|
||||
int itemActionCode;
|
||||
int itemActionCodeState;
|
||||
|
||||
InventoryMessage(InventoryMessageType messageType){
|
||||
this.type = MessageType.INVENTORY_MESSAGE;
|
||||
@ -73,6 +76,22 @@ public class InventoryMessage extends NetworkMessage {
|
||||
this.containerType = containerType;
|
||||
}
|
||||
|
||||
public int getitemActionCode() {
|
||||
return itemActionCode;
|
||||
}
|
||||
|
||||
public void setitemActionCode(int itemActionCode) {
|
||||
this.itemActionCode = itemActionCode;
|
||||
}
|
||||
|
||||
public int getitemActionCodeState() {
|
||||
return itemActionCodeState;
|
||||
}
|
||||
|
||||
public void setitemActionCodeState(int itemActionCodeState) {
|
||||
this.itemActionCodeState = itemActionCodeState;
|
||||
}
|
||||
|
||||
static void stripPacketHeader(CircularByteBuffer byteBuffer){
|
||||
byteBuffer.read(2);
|
||||
}
|
||||
@ -97,6 +116,8 @@ public class InventoryMessage extends NetworkMessage {
|
||||
return InventoryMessage.canParseserverCommandUnequipItemMessage(byteBuffer);
|
||||
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM:
|
||||
return InventoryMessage.canParseclientRequestUnequipItemMessage(byteBuffer);
|
||||
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION:
|
||||
return InventoryMessage.canParseclientRequestPerformItemActionMessage(byteBuffer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -363,6 +384,49 @@ public class InventoryMessage extends NetworkMessage {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static boolean canParseclientRequestPerformItemActionMessage(CircularByteBuffer byteBuffer){
|
||||
int currentStreamLength = byteBuffer.getRemaining();
|
||||
List<Byte> temporaryByteQueue = new LinkedList();
|
||||
int equipPointIdSize = 0;
|
||||
if(currentStreamLength < 6){
|
||||
return false;
|
||||
} else {
|
||||
temporaryByteQueue.add(byteBuffer.peek(2 + 0));
|
||||
temporaryByteQueue.add(byteBuffer.peek(2 + 1));
|
||||
temporaryByteQueue.add(byteBuffer.peek(2 + 2));
|
||||
temporaryByteQueue.add(byteBuffer.peek(2 + 3));
|
||||
equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
|
||||
}
|
||||
if(currentStreamLength < 6 + equipPointIdSize){
|
||||
return false;
|
||||
}
|
||||
if(currentStreamLength < 10 + equipPointIdSize){
|
||||
return false;
|
||||
}
|
||||
if(currentStreamLength < 14 + equipPointIdSize){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static InventoryMessage parseclientRequestPerformItemActionMessage(CircularByteBuffer byteBuffer){
|
||||
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTPERFORMITEMACTION);
|
||||
stripPacketHeader(byteBuffer);
|
||||
rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
|
||||
rVal.setitemActionCode(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||
rVal.setitemActionCodeState(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static InventoryMessage constructclientRequestPerformItemActionMessage(String equipPointId,int itemActionCode,int itemActionCodeState){
|
||||
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTPERFORMITEMACTION);
|
||||
rVal.setequipPointId(equipPointId);
|
||||
rVal.setitemActionCode(itemActionCode);
|
||||
rVal.setitemActionCodeState(itemActionCodeState);
|
||||
rVal.serialize();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
void serialize(){
|
||||
byte[] intValues = new byte[8];
|
||||
@ -505,6 +569,29 @@ public class InventoryMessage extends NetworkMessage {
|
||||
rawBytes[6+i] = stringBytes[i];
|
||||
}
|
||||
break;
|
||||
case CLIENTREQUESTPERFORMITEMACTION:
|
||||
rawBytes = new byte[2+4+equipPointId.length()+4+4];
|
||||
//message header
|
||||
rawBytes[0] = TypeBytes.MESSAGE_TYPE_INVENTORY;
|
||||
//entity messaage header
|
||||
rawBytes[1] = TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION;
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(equipPointId.length());
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[2+i] = intValues[i];
|
||||
}
|
||||
stringBytes = equipPointId.getBytes();
|
||||
for(int i = 0; i < equipPointId.length(); i++){
|
||||
rawBytes[6+i] = stringBytes[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(itemActionCode);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[6+equipPointId.length()+i] = intValues[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(itemActionCodeState);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[10+equipPointId.length()+i] = intValues[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
serialized = true;
|
||||
}
|
||||
|
||||
@ -311,6 +311,11 @@ SYNCHRONIZATION_MESSAGE,
|
||||
rVal = InventoryMessage.parseclientRequestUnequipItemMessage(byteBuffer);
|
||||
}
|
||||
break;
|
||||
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION:
|
||||
if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
|
||||
rVal = InventoryMessage.parseclientRequestPerformItemActionMessage(byteBuffer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TypeBytes.MESSAGE_TYPE_SYNCHRONIZATION:
|
||||
|
||||
@ -133,6 +133,7 @@ Message categories
|
||||
public static final byte INVENTORY_MESSAGE_TYPE_SERVERCOMMANDEQUIPITEM = 4;
|
||||
public static final byte INVENTORY_MESSAGE_TYPE_SERVERCOMMANDUNEQUIPITEM = 5;
|
||||
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM = 6;
|
||||
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION = 7;
|
||||
/*
|
||||
Inventory packet sizes
|
||||
*/
|
||||
|
||||
@ -5,41 +5,45 @@ import electrosphere.engine.Main;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.NetUtils;
|
||||
import electrosphere.net.parser.net.message.NetworkMessage;
|
||||
import electrosphere.server.saves.SaveUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.BindException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
* Lowest level networking class for the server
|
||||
*/
|
||||
public class Server implements Runnable{
|
||||
|
||||
//the port the server is running on
|
||||
int port;
|
||||
|
||||
//the socket for the server
|
||||
ServerSocket serverSocket;
|
||||
|
||||
//the map of ip->connection handler
|
||||
Map<String,ServerConnectionHandler> clientMap = new HashMap<String,ServerConnectionHandler>();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Inits the server
|
||||
*/
|
||||
void initServer(){
|
||||
// clientMap = new HashMap<String,ServerConnectionHandler>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param port The port to run the server on
|
||||
*/
|
||||
public Server(int port){
|
||||
this.port = port;
|
||||
}
|
||||
@ -76,7 +80,19 @@ public class Server implements Runnable{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously handles queued packets for each client connection
|
||||
*/
|
||||
public void synchronousPacketHandling(){
|
||||
for(ServerConnectionHandler connectionHandler : this.clientMap.values()){
|
||||
connectionHandler.handleSynchronousPacketQueue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the server socket
|
||||
*/
|
||||
public void close(){
|
||||
try {
|
||||
if(serverSocket != null){
|
||||
@ -87,6 +103,10 @@ public class Server implements Runnable{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a message to all clients
|
||||
* @param message The message to broadcast
|
||||
*/
|
||||
public void broadcastMessage(NetworkMessage message){
|
||||
for(ServerConnectionHandler client : clientMap.values()){
|
||||
if(Globals.clientPlayer == null || client.playerID != Globals.clientPlayer.getId()){
|
||||
@ -95,6 +115,12 @@ public class Server implements Runnable{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a connection created manually by two streams instead of receiving the streams from the server socket
|
||||
* @param serverInputStream The input stream
|
||||
* @param serverOutputStream The output stream
|
||||
* @return The connection object for the provided streams
|
||||
*/
|
||||
public ServerConnectionHandler addLocalPlayer(InputStream serverInputStream, OutputStream serverOutputStream){
|
||||
ServerConnectionHandler newClient = new ServerConnectionHandler(serverInputStream,serverOutputStream);
|
||||
clientMap.put("127.0.0.1", newClient);
|
||||
|
||||
@ -1,21 +1,12 @@
|
||||
package electrosphere.net.server;
|
||||
|
||||
import electrosphere.entity.types.creature.CreatureTemplate;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.Main;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.ironsight.IronSightTree;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||
import electrosphere.entity.ServerEntityUtils;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.NetUtils;
|
||||
import electrosphere.net.parser.net.message.AuthMessage;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.net.parser.net.message.NetworkMessage;
|
||||
import electrosphere.net.parser.net.message.PlayerMessage;
|
||||
import electrosphere.net.parser.net.message.ServerMessage;
|
||||
import electrosphere.net.parser.net.raw.NetworkParser;
|
||||
import electrosphere.net.server.player.Player;
|
||||
@ -24,30 +15,20 @@ import electrosphere.net.server.protocol.ServerProtocol;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.spec.RSAKeyGenParameterSpec;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author satellite
|
||||
* A connection to the server
|
||||
*/
|
||||
public class ServerConnectionHandler implements Runnable {
|
||||
|
||||
//the player id associated with this connection
|
||||
static int playerIdIncrementer = 0;
|
||||
|
||||
//local carrier variables
|
||||
@ -55,17 +36,30 @@ public class ServerConnectionHandler implements Runnable {
|
||||
|
||||
//socket carrier variables
|
||||
Socket socket;
|
||||
|
||||
//the streams for the connection
|
||||
// CryptoInputStream inputStream;
|
||||
// CryptoOutputStream outputStream;
|
||||
InputStream inputStream;
|
||||
OutputStream outputStream;
|
||||
boolean initialized;
|
||||
boolean isAuthenticated = false;
|
||||
|
||||
//the network parser for the streams
|
||||
NetworkParser networkParser;
|
||||
|
||||
//initialized status
|
||||
boolean initialized;
|
||||
//authentication status
|
||||
boolean isAuthenticated = false;
|
||||
|
||||
//the player id
|
||||
int playerID;
|
||||
int playerCharacterID;
|
||||
//the player's entity id
|
||||
int playerEntityID;
|
||||
|
||||
//the creature template associated with this player
|
||||
CreatureTemplate currentCreatureTemplate;
|
||||
|
||||
//the server protocol object associated with this player
|
||||
ServerProtocol serverProtocol;
|
||||
|
||||
//thresholds for determining when to send pings and when a client has disconnected
|
||||
@ -82,13 +76,27 @@ public class ServerConnectionHandler implements Runnable {
|
||||
String netMonitorHandle;
|
||||
//Used to copy messages from network parser to NetMonitor
|
||||
List<NetworkMessage> netMonitorCache = new LinkedList<NetworkMessage>();
|
||||
|
||||
//the lock used for synchronizing the synchronous message queue
|
||||
Semaphore synchronousMessageLock = new Semaphore(1);
|
||||
//the queue of synchonous network messages
|
||||
List<NetworkMessage> synchronousMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
|
||||
|
||||
/**
|
||||
* Constructs a connection from a socket
|
||||
* @param socket the socket
|
||||
*/
|
||||
public ServerConnectionHandler(Socket socket) {
|
||||
this.socket = socket;
|
||||
playerID = getNewPlayerID();
|
||||
LoggerInterface.loggerNetworking.INFO("Player ID: " + playerID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a connection from an arbitrary input and output stream
|
||||
* @param serverInputStream the input stream
|
||||
* @param serverOutputStream the output stream
|
||||
*/
|
||||
public ServerConnectionHandler(InputStream serverInputStream, OutputStream serverOutputStream){
|
||||
this.local = true;
|
||||
playerID = getNewPlayerID();
|
||||
@ -114,6 +122,8 @@ public class ServerConnectionHandler implements Runnable {
|
||||
} catch (SocketException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
//TODO: use this commented block of code as a reference for implementing encryption on top of the game connection
|
||||
// final SecretKeySpec key = new SecretKeySpec(("1234567890123456").getBytes(),"AES");
|
||||
// final Properties properties = new Properties();
|
||||
// final RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(4096, BigInteger.probablePrime(4000, new Random()));
|
||||
@ -210,7 +220,13 @@ public class ServerConnectionHandler implements Runnable {
|
||||
//ponder incoming messages
|
||||
while(networkParser.hasIncomingMessaage()){
|
||||
NetworkMessage message = networkParser.popIncomingMessage();
|
||||
serverProtocol.handleMessage(message);
|
||||
NetworkMessage bouncedMessage = serverProtocol.handleAsyncMessage(message);
|
||||
//if the message bounces back from the async handle function, means we need to handle synchronously
|
||||
if(bouncedMessage != null){
|
||||
this.synchronousMessageLock.acquireUninterruptibly();
|
||||
this.synchronousMessageQueue.add(bouncedMessage);
|
||||
this.synchronousMessageLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
if(Globals.netMonitor != null){
|
||||
@ -231,6 +247,18 @@ public class ServerConnectionHandler implements Runnable {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles synchronous packets in the queue
|
||||
*/
|
||||
public void handleSynchronousPacketQueue(){
|
||||
synchronousMessageLock.acquireUninterruptibly();
|
||||
for(NetworkMessage message : synchronousMessageQueue){
|
||||
this.serverProtocol.handleSynchronousMessage(message);
|
||||
}
|
||||
synchronousMessageQueue.clear();
|
||||
synchronousMessageLock.release();
|
||||
}
|
||||
|
||||
public void setPlayerId(int id){
|
||||
playerID = id;
|
||||
@ -245,12 +273,12 @@ public class ServerConnectionHandler implements Runnable {
|
||||
return playerIdIncrementer;
|
||||
}
|
||||
|
||||
public void setPlayerCharacterId(int id){
|
||||
playerCharacterID = id;
|
||||
public void setPlayerEntityId(int id){
|
||||
playerEntityID = id;
|
||||
}
|
||||
|
||||
public int getPlayerCharacterId(){
|
||||
return playerCharacterID;
|
||||
public int getPlayerEntityId(){
|
||||
return playerEntityID;
|
||||
}
|
||||
|
||||
public String getIPAddress(){
|
||||
@ -266,7 +294,7 @@ public class ServerConnectionHandler implements Runnable {
|
||||
}
|
||||
|
||||
boolean isConnectionPlayerEntity(int id){
|
||||
return id == this.playerCharacterID;
|
||||
return id == this.playerEntityID;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -303,13 +331,8 @@ public class ServerConnectionHandler implements Runnable {
|
||||
}
|
||||
//figure out what player we are
|
||||
Player playerObject = Globals.playerManager.getPlayerFromId(getPlayerId());
|
||||
//get player entity & position
|
||||
Entity playerEntity = playerObject.getPlayerEntity();
|
||||
Vector3d position = EntityUtils.getPosition(playerEntity);
|
||||
//deregister entity
|
||||
EntityUtils.cleanUpEntity(playerObject.getPlayerEntity());
|
||||
//TODO: tell all clients to destroy the entity
|
||||
EntityUtils.cleanUpEntity(playerEntity);
|
||||
//tell all clients to destroy the entity
|
||||
ServerEntityUtils.destroyEntity(playerObject.getPlayerEntity());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -39,4 +39,20 @@ public class AuthProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the network message from the context of the main server simulation thread
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The network message
|
||||
*/
|
||||
protected static void handleSynchronousAuthMessage(ServerConnectionHandler connectionHandler, AuthMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case AUTHDETAILS:
|
||||
case AUTHFAILURE:
|
||||
case AUTHREQUEST:
|
||||
case AUTHSUCCESS:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -37,6 +37,25 @@ public class CharacterProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the network message from the context of the main server simulation thread
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The network message
|
||||
*/
|
||||
protected static void handleSynchronousCharacterMessage(ServerConnectionHandler connectionHandler, CharacterMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case REQUESTCHARACTERLIST:
|
||||
case REQUESTCREATECHARACTER:
|
||||
case REQUESTSPAWNCHARACTER:
|
||||
case RESPONSECHARACTERLIST:
|
||||
case RESPONSECREATECHARACTERFAILURE:
|
||||
case RESPONSECREATECHARACTERSUCCESS:
|
||||
case RESPONSESPAWNCHARACTER:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the player's entity
|
||||
* @param connectionHandler The connection handler for the player
|
||||
|
||||
@ -52,5 +52,29 @@ public class EntityProtocol {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the network message from the context of the main server simulation thread
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The network message
|
||||
*/
|
||||
protected static void handleSynchronousEntityMessage(ServerConnectionHandler connectionHandler, EntityMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case MOVEUPDATE:
|
||||
case ATTACKUPDATE:
|
||||
case STARTATTACK:
|
||||
case UPDATEENTITYVIEWDIR:
|
||||
case KILL:
|
||||
case SPAWNCREATURE:
|
||||
case DESTROY:
|
||||
case CREATE:
|
||||
case ATTACHENTITYTOENTITY:
|
||||
case SETPROPERTY:
|
||||
case SPAWNFOLIAGESEED:
|
||||
case SPAWNITEM:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,54 +1,88 @@
|
||||
package electrosphere.net.server.protocol;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.equip.ClientEquipState;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.game.data.creature.type.equip.EquipPoint;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.parser.net.message.InventoryMessage;
|
||||
import electrosphere.net.server.ServerConnectionHandler;
|
||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||
import electrosphere.server.player.PlayerActions;
|
||||
|
||||
/**
|
||||
* Server protocol for dealing with inventory messages
|
||||
*/
|
||||
public class InventoryProtocol {
|
||||
|
||||
|
||||
//the entity's equip inventory
|
||||
public static final int INVENTORY_TYPE_EQUIP = 0;
|
||||
//the natural inventory of the entity
|
||||
public static final int INVENTORY_TYPE_NATURAL = 1;
|
||||
|
||||
protected static void handleInventoryMessage(ServerConnectionHandler connectionHandler, InventoryMessage message){
|
||||
Entity characterEntity;
|
||||
/**
|
||||
* Handles asynchronous inventory messages
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The message to handle
|
||||
* @return The network message if it should be handled synchronously, otherwise null
|
||||
*/
|
||||
protected static InventoryMessage handleAsyncInventoryMessage(ServerConnectionHandler connectionHandler, InventoryMessage message){
|
||||
Entity target;
|
||||
switch(message.getMessageSubtype()){
|
||||
case ADDITEMTOINVENTORY:
|
||||
LoggerInterface.loggerNetworking.DEBUG("[SERVER] ADD ITEM TO INVENTORY " + message.getentityId());
|
||||
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerCharacterId());
|
||||
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
|
||||
if(InventoryUtils.hasNaturalInventory(target)){
|
||||
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
|
||||
}
|
||||
break;
|
||||
case REMOVEITEMFROMINVENTORY:
|
||||
LoggerInterface.loggerNetworking.DEBUG("[SERVER] REMOVE ITEM FROM INVENTORY " + message.getentityId());
|
||||
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerCharacterId());
|
||||
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
|
||||
if(InventoryUtils.hasNaturalInventory(target)){
|
||||
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
|
||||
}
|
||||
break;
|
||||
case CLIENTREQUESTEQUIPITEM:
|
||||
LoggerInterface.loggerNetworking.DEBUG("[SERVER] REQUEST EQUIP ITEM " + message.getentityId());
|
||||
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerCharacterId());
|
||||
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
|
||||
if(InventoryUtils.hasNaturalInventory(target)){
|
||||
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
|
||||
}
|
||||
break;
|
||||
case CLIENTREQUESTUNEQUIPITEM:
|
||||
LoggerInterface.loggerNetworking.DEBUG("[SERVER] REQUEST UNEQUIP ITEM " + message.getentityId());
|
||||
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerCharacterId());
|
||||
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
|
||||
if(InventoryUtils.hasNaturalInventory(target)){
|
||||
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
|
||||
}
|
||||
break;
|
||||
case CLIENTREQUESTPERFORMITEMACTION: {
|
||||
//perform some action on the server based on what the client has equipped
|
||||
return message;
|
||||
}
|
||||
case SERVERCOMMANDUNEQUIPITEM:
|
||||
case SERVERCOMMANDMOVEITEMCONTAINER:
|
||||
case SERVERCOMMANDEQUIPITEM:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the network message from the context of the main server simulation thread
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The network message
|
||||
*/
|
||||
protected static void handleSynchronousInventoryMessage(ServerConnectionHandler connectionHandler, InventoryMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case CLIENTREQUESTPERFORMITEMACTION: {
|
||||
PlayerActions.attemptPlayerAction(connectionHandler, message);
|
||||
} break;
|
||||
case ADDITEMTOINVENTORY:
|
||||
case REMOVEITEMFROMINVENTORY:
|
||||
case CLIENTREQUESTEQUIPITEM:
|
||||
case CLIENTREQUESTUNEQUIPITEM:
|
||||
case SERVERCOMMANDUNEQUIPITEM:
|
||||
case SERVERCOMMANDMOVEITEMCONTAINER:
|
||||
case SERVERCOMMANDEQUIPITEM:
|
||||
|
||||
@ -22,5 +22,19 @@ public class LoreProtocol {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the network message from the context of the main server simulation thread
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The network message
|
||||
*/
|
||||
protected static void handleSynchronousLoreMessage(ServerConnectionHandler connectionHandler, LoreMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case REQUESTRACES:
|
||||
case RESPONSERACES:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3,11 +3,36 @@ package electrosphere.net.server.protocol;
|
||||
import electrosphere.net.parser.net.message.PlayerMessage;
|
||||
import electrosphere.net.server.ServerConnectionHandler;
|
||||
|
||||
/**
|
||||
* Player protocol handling
|
||||
*/
|
||||
public class PlayerProtocol {
|
||||
|
||||
|
||||
/**
|
||||
* Handles a player network message
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The player message
|
||||
*/
|
||||
protected static void handlePlayerMessage(ServerConnectionHandler connectionHandler, PlayerMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case SETINITIALDISCRETEPOSITION:
|
||||
case SET_ID:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the network message from the context of the main server simulation thread
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The network message
|
||||
*/
|
||||
protected static void handleSynchronousPlayerMessage(ServerConnectionHandler connectionHandler, PlayerMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case SETINITIALDISCRETEPOSITION:
|
||||
case SET_ID:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,6 @@
|
||||
package electrosphere.net.server.protocol;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.Main;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.ironsight.IronSightTree;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.NetUtils;
|
||||
import electrosphere.net.parser.net.message.AuthMessage;
|
||||
import electrosphere.net.parser.net.message.CharacterMessage;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
@ -25,53 +13,110 @@ import electrosphere.net.parser.net.message.TerrainMessage;
|
||||
import electrosphere.net.parser.net.message.NetworkMessage.MessageType;
|
||||
import electrosphere.net.parser.net.message.ServerMessage.ServerMessageType;
|
||||
import electrosphere.net.server.ServerConnectionHandler;
|
||||
import electrosphere.net.server.player.Player;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
import electrosphere.server.terrain.models.TerrainModification;
|
||||
|
||||
/**
|
||||
* The server's protocol for handling a message
|
||||
*/
|
||||
public class ServerProtocol {
|
||||
|
||||
//the connection handler associated with this protocol object
|
||||
ServerConnectionHandler connectionHandler;
|
||||
//if set to true, will log ping messages
|
||||
boolean echoPings = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param connectionHandler the associated connection handler
|
||||
*/
|
||||
public ServerProtocol(ServerConnectionHandler connectionHandler){
|
||||
this.connectionHandler = connectionHandler;
|
||||
}
|
||||
|
||||
public void handleMessage(NetworkMessage message){
|
||||
/**
|
||||
* Handles a given network message
|
||||
* @param message The network message to handle
|
||||
* @return Returns the message if it should be synchronously handled with the main server thread instead
|
||||
*/
|
||||
public NetworkMessage handleAsyncMessage(NetworkMessage message){
|
||||
//print out message
|
||||
printMessage(message);
|
||||
//actually handle message
|
||||
switch(message.getType()){
|
||||
case ENTITY_MESSAGE:
|
||||
case ENTITY_MESSAGE: {
|
||||
EntityProtocol.handleEntityMessage(connectionHandler, (EntityMessage)message);
|
||||
break;
|
||||
case TERRAIN_MESSAGE:
|
||||
} break;
|
||||
case TERRAIN_MESSAGE: {
|
||||
TerrainProtocol.handleTerrainMessage(connectionHandler, (TerrainMessage)message);
|
||||
break;
|
||||
case PLAYER_MESSAGE:
|
||||
} break;
|
||||
case PLAYER_MESSAGE: {
|
||||
PlayerProtocol.handlePlayerMessage(connectionHandler, (PlayerMessage)message);
|
||||
break;
|
||||
case AUTH_MESSAGE:
|
||||
} break;
|
||||
case AUTH_MESSAGE: {
|
||||
AuthProtocol.handleAuthenticationMessage(connectionHandler, (AuthMessage)message);
|
||||
break;
|
||||
case SERVER_MESSAGE:
|
||||
} break;
|
||||
case SERVER_MESSAGE: {
|
||||
handleServerMessage((ServerMessage)message);
|
||||
break;
|
||||
case CHARACTER_MESSAGE:
|
||||
} break;
|
||||
case CHARACTER_MESSAGE: {
|
||||
CharacterProtocol.handleCharacterMessage(connectionHandler, (CharacterMessage)message);
|
||||
break;
|
||||
case LORE_MESSAGE:
|
||||
} break;
|
||||
case LORE_MESSAGE: {
|
||||
LoreProtocol.handleLoreMessage(connectionHandler, (LoreMessage)message);
|
||||
} break;
|
||||
case INVENTORY_MESSAGE: {
|
||||
return InventoryProtocol.handleAsyncInventoryMessage(connectionHandler, (InventoryMessage)message);
|
||||
}
|
||||
case SYNCHRONIZATION_MESSAGE:
|
||||
//silently ignore sync messages from client
|
||||
break;
|
||||
case INVENTORY_MESSAGE:
|
||||
InventoryProtocol.handleInventoryMessage(connectionHandler, (InventoryMessage)message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously handles a network message
|
||||
* @param message The network message
|
||||
*/
|
||||
public void handleSynchronousMessage(NetworkMessage message){
|
||||
//print out message
|
||||
printMessage(message);
|
||||
//actually handle message
|
||||
switch(message.getType()){
|
||||
case ENTITY_MESSAGE: {
|
||||
EntityProtocol.handleSynchronousEntityMessage(connectionHandler, (EntityMessage)message);
|
||||
} break;
|
||||
case TERRAIN_MESSAGE: {
|
||||
TerrainProtocol.handleSynchronousServerMessage(connectionHandler, (TerrainMessage)message);
|
||||
} break;
|
||||
case PLAYER_MESSAGE: {
|
||||
PlayerProtocol.handleSynchronousPlayerMessage(connectionHandler, (PlayerMessage)message);
|
||||
} break;
|
||||
case AUTH_MESSAGE: {
|
||||
AuthProtocol.handleSynchronousAuthMessage(connectionHandler, (AuthMessage)message);
|
||||
} break;
|
||||
case SERVER_MESSAGE: {
|
||||
ServerProtocol.handleSynchronousServerMessage(connectionHandler, (ServerMessage)message);
|
||||
} break;
|
||||
case CHARACTER_MESSAGE: {
|
||||
CharacterProtocol.handleSynchronousCharacterMessage(connectionHandler, (CharacterMessage)message);
|
||||
} break;
|
||||
case LORE_MESSAGE: {
|
||||
LoreProtocol.handleSynchronousLoreMessage(connectionHandler, (LoreMessage)message);
|
||||
} break;
|
||||
case INVENTORY_MESSAGE: {
|
||||
InventoryProtocol.handleSynchronousInventoryMessage(connectionHandler, (InventoryMessage)message);
|
||||
} break;
|
||||
case SYNCHRONIZATION_MESSAGE:
|
||||
//silently ignore sync messages from client
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Handles a server-type network message
|
||||
* @param message The server message
|
||||
*/
|
||||
void handleServerMessage(ServerMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case PING:
|
||||
@ -83,6 +128,20 @@ public class ServerProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the network message from the context of the main server simulation thread
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The network message
|
||||
*/
|
||||
protected static void handleSynchronousServerMessage(ServerConnectionHandler connectionHandler, ServerMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case PING:
|
||||
case PONG:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out the network message type, this only prints ping and pong if echoPings is true
|
||||
*/
|
||||
|
||||
@ -6,20 +6,25 @@ import java.nio.IntBuffer;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.client.terrain.cache.ChunkData;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||
import electrosphere.net.server.Server;
|
||||
import electrosphere.net.server.ServerConnectionHandler;
|
||||
import electrosphere.net.server.player.Player;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.fluid.manager.ServerFluidChunk;
|
||||
import electrosphere.server.terrain.editing.TerrainEditing;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
import electrosphere.server.terrain.models.TerrainModification;
|
||||
|
||||
/**
|
||||
* Server handling for terrain network messages
|
||||
*/
|
||||
public class TerrainProtocol {
|
||||
|
||||
/**
|
||||
* Handles a terrain message
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The terrain message
|
||||
*/
|
||||
protected static void handleTerrainMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case REQUESTMETADATA:
|
||||
@ -53,6 +58,36 @@ public class TerrainProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the network message from the context of the main server simulation thread
|
||||
* @param connectionHandler The connection handler
|
||||
* @param message The network message
|
||||
*/
|
||||
protected static void handleSynchronousServerMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case REQUESTCHUNKDATA:
|
||||
case REQUESTEDITVOXEL:
|
||||
case REQUESTFLUIDDATA:
|
||||
case REQUESTMETADATA:
|
||||
case REQUESTUSETERRAINPALETTE:
|
||||
case RESPONSEMETADATA:
|
||||
case UPDATEFLUIDDATA:
|
||||
case SPAWNPOSITION:
|
||||
case UPDATEVOXEL:
|
||||
case SENDCHUNKDATA:
|
||||
case SENDFLUIDDATA:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a subchunk to the client
|
||||
* @param connectionHandler The connection handler
|
||||
* @param worldX the world x
|
||||
* @param worldY the world y
|
||||
* @param worldZ the world z
|
||||
*/
|
||||
static void sendWorldSubChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ){
|
||||
/*
|
||||
int locationX,
|
||||
@ -200,6 +235,13 @@ public class TerrainProtocol {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a fluid sub chunk to the client
|
||||
* @param connectionHandler The connection handler
|
||||
* @param worldX the world x
|
||||
* @param worldY the world y
|
||||
* @param worldZ the world z
|
||||
*/
|
||||
static void sendWorldFluidSubChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ){
|
||||
|
||||
// System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY());
|
||||
@ -213,6 +255,10 @@ public class TerrainProtocol {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends world metadata to the client
|
||||
* @param connectionHandler The connection handler
|
||||
*/
|
||||
static void sendWorldMetadata(ServerConnectionHandler connectionHandler){
|
||||
//world metadata
|
||||
connectionHandler.addMessagetoOutgoingQueue(
|
||||
@ -233,7 +279,8 @@ public class TerrainProtocol {
|
||||
* @param message The message containing the edit request
|
||||
*/
|
||||
static void attemptTerrainEdit(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
||||
Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
|
||||
// Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -7,13 +7,15 @@ public class BehaviorTreeIdEnums {
|
||||
|
||||
public static final int BTREE_CLIENTATTACKTREE_ID = 0;
|
||||
public static final int BTREE_SERVERATTACKTREE_ID = 1;
|
||||
public static final int BTREE_CLIENTEQUIPSTATE_ID = 2;
|
||||
public static final int BTREE_SERVEREQUIPSTATE_ID = 3;
|
||||
public static final int BTREE_GRAVITY_ID = 4;
|
||||
public static final int BTREE_SERVERGRAVITY_ID = 5;
|
||||
public static final int BTREE_IDLE_ID = 6;
|
||||
public static final int BTREE_SERVERIDLE_ID = 7;
|
||||
public static final int BTREE_CLIENTGROUNDMOVEMENTTREE_ID = 8;
|
||||
public static final int BTREE_SERVERGROUNDMOVEMENTTREE_ID = 9;
|
||||
public static final int BTREE_CLIENTBLOCKTREE_ID = 2;
|
||||
public static final int BTREE_SERVERBLOCKTREE_ID = 3;
|
||||
public static final int BTREE_CLIENTEQUIPSTATE_ID = 4;
|
||||
public static final int BTREE_SERVEREQUIPSTATE_ID = 5;
|
||||
public static final int BTREE_GRAVITY_ID = 6;
|
||||
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_CLIENTGROUNDMOVEMENTTREE_ID = 10;
|
||||
public static final int BTREE_SERVERGROUNDMOVEMENTTREE_ID = 11;
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
package electrosphere.net.synchronization;
|
||||
|
||||
|
||||
import electrosphere.entity.state.block.ClientBlockTree;
|
||||
|
||||
import electrosphere.entity.state.block.ServerBlockTree;
|
||||
|
||||
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree;
|
||||
|
||||
import electrosphere.entity.state.movement.groundmove.ServerGroundMovementTree;
|
||||
@ -110,13 +114,25 @@ public class ClientSynchronizationManager {
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case BehaviorTreeIdEnums.BTREE_SERVERBLOCKTREE_ID: {
|
||||
switch(message.getfieldId()){
|
||||
case 8:{
|
||||
ClientBlockTree tree = ClientBlockTree.getClientBlockTree(entity);
|
||||
tree.setState(ClientBlockTree.getBlockStateShortAsEnum((short)message.getbTreeValue()));
|
||||
} break;
|
||||
case 9:{
|
||||
ClientBlockTree tree = ClientBlockTree.getClientBlockTree(entity);
|
||||
tree.setCurrentBlockVariant(message.getstringValue());
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case BehaviorTreeIdEnums.BTREE_SERVEREQUIPSTATE_ID: {
|
||||
switch(message.getfieldId()){
|
||||
}
|
||||
} break;
|
||||
case BehaviorTreeIdEnums.BTREE_SERVERGRAVITY_ID: {
|
||||
switch(message.getfieldId()){
|
||||
case 7:{
|
||||
case 11:{
|
||||
ClientGravityTree tree = ClientGravityTree.getClientGravityTree(entity);
|
||||
tree.setState(ClientGravityTree.getGravityTreeStateShortAsEnum((short)message.getbTreeValue()));
|
||||
} break;
|
||||
@ -124,15 +140,15 @@ public class ClientSynchronizationManager {
|
||||
} break;
|
||||
case BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID: {
|
||||
switch(message.getfieldId()){
|
||||
case 9:{
|
||||
ClientIdleTree tree = ClientIdleTree.getIdleTree(entity);
|
||||
case 13:{
|
||||
ClientIdleTree tree = ClientIdleTree.getClientIdleTree(entity);
|
||||
tree.setState(ClientIdleTree.getIdleTreeStateShortAsEnum((short)message.getbTreeValue()));
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case BehaviorTreeIdEnums.BTREE_SERVERGROUNDMOVEMENTTREE_ID: {
|
||||
switch(message.getfieldId()){
|
||||
case 11:{
|
||||
case 15:{
|
||||
ClientGroundMovementTree tree = ClientGroundMovementTree.getClientGroundMovementTree(entity);
|
||||
tree.setFacing(ClientGroundMovementTree.getMovementRelativeFacingShortAsEnum((short)message.getbTreeValue()));
|
||||
} break;
|
||||
|
||||
@ -116,7 +116,12 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
//since you're directly accessing the quat from the body, need to adjust it to be in the correct orientation
|
||||
modelTransformMatrix.rotate(PhysicsUtils.odeQuatToJomlQuat(capsuleView.getQuaternion()).mul(new Quaterniond(0.707,0,0,0.707)));
|
||||
modelTransformMatrix.scale(capsuleView.getRadius(),capsuleView.getLength(),capsuleView.getRadius());
|
||||
//the ode4j capsule's end caps are always at least radius length, the length only controls the distance between the two caps.
|
||||
//unfortunately that won't be easy to replicate with rendering tech currently; instead, run logic below
|
||||
double radius = capsuleView.getRadius();
|
||||
double length = capsuleView.getLength();
|
||||
if(length < radius) length = radius;
|
||||
modelTransformMatrix.scale(radius,length,radius);
|
||||
hitboxModel.setModelMatrix(modelTransformMatrix);
|
||||
hitboxModel.draw(renderPipelineState,openGLState);
|
||||
}
|
||||
@ -220,7 +225,12 @@ public class DebugContentPipeline implements RenderPipeline {
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
//since you're directly accessing the quat from the body, need to adjust it to be in the correct orientation
|
||||
modelTransformMatrix.rotate(PhysicsUtils.odeQuatToJomlQuat(capsuleView.getQuaternion()).mul(new Quaterniond(0.707,0,0,0.707)));
|
||||
modelTransformMatrix.scale(capsuleView.getRadius(),capsuleView.getLength(),capsuleView.getRadius());
|
||||
//the ode4j capsule's end caps are always at least radius length, the length only controls the distance between the two caps.
|
||||
//unfortunately that won't be easy to replicate with rendering tech currently; instead, run logic below
|
||||
double radius = capsuleView.getRadius();
|
||||
double length = capsuleView.getLength();
|
||||
if(length < radius) length = radius;
|
||||
modelTransformMatrix.scale(radius,length,radius);
|
||||
hitboxModel.setModelMatrix(modelTransformMatrix);
|
||||
hitboxModel.draw(renderPipelineState,openGLState);
|
||||
}
|
||||
|
||||
41
src/main/java/electrosphere/server/MainServerFunctions.java
Normal file
41
src/main/java/electrosphere/server/MainServerFunctions.java
Normal file
@ -0,0 +1,41 @@
|
||||
package electrosphere.server;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
|
||||
/**
|
||||
* Functions that should be fired every server frame
|
||||
*/
|
||||
public class MainServerFunctions {
|
||||
|
||||
/**
|
||||
* Calls the main server routines that should fire each frame
|
||||
*/
|
||||
public static void simulate(){
|
||||
|
||||
//
|
||||
//Synchronous player message parsing\
|
||||
Globals.profiler.beginCpuSample("Server synchronous packet parsing");
|
||||
if(Globals.server != null){
|
||||
Globals.server.synchronousPacketHandling();
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
|
||||
//
|
||||
//Micro simulation (ie simulating each scene on the server)
|
||||
Globals.profiler.beginCpuSample("Server micro simulation");
|
||||
LoggerInterface.loggerEngine.DEBUG("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");
|
||||
if(Globals.macroSimulation != null && Globals.macroSimulation.isReady()){
|
||||
Globals.macroSimulation.simulate();
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
|
||||
}
|
||||
@ -30,7 +30,7 @@ public class PlayerCharacterCreation {
|
||||
Realm realm = Globals.realmManager.getRealms().iterator().next();
|
||||
Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,new Vector3d(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z),raceName,template);
|
||||
int playerCharacterId = newPlayerEntity.getId();
|
||||
connectionHandler.setPlayerCharacterId(playerCharacterId);
|
||||
connectionHandler.setPlayerEntityId(playerCharacterId);
|
||||
CreatureUtils.setControllerPlayerId(newPlayerEntity, connectionHandler.getPlayerId());
|
||||
//custom player btrees
|
||||
addPlayerServerBTrees(newPlayerEntity);
|
||||
|
||||
35
src/main/java/electrosphere/server/player/PlayerActions.java
Normal file
35
src/main/java/electrosphere/server/player/PlayerActions.java
Normal file
@ -0,0 +1,35 @@
|
||||
package electrosphere.server.player;
|
||||
|
||||
import electrosphere.client.item.ItemActions;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.block.ServerBlockTree;
|
||||
import electrosphere.net.parser.net.message.InventoryMessage;
|
||||
import electrosphere.net.server.ServerConnectionHandler;
|
||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||
|
||||
/**
|
||||
* Class for handling
|
||||
*/
|
||||
public class PlayerActions {
|
||||
|
||||
/**
|
||||
* Attempts to perform an action a player requested
|
||||
* @param connectionHandler The player's connection handler
|
||||
* @param message The network message that encapsulates the requested action
|
||||
*/
|
||||
public static void attemptPlayerAction(ServerConnectionHandler connectionHandler, InventoryMessage message){
|
||||
Entity playerEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
|
||||
|
||||
if(message.getitemActionCode() == ItemActions.ITEM_ACTION_CODE_SECONDARY){
|
||||
ServerBlockTree serverBlockTree = ServerBlockTree.getServerBlockTree(playerEntity);
|
||||
if(serverBlockTree != null){
|
||||
if(message.getitemActionCodeState() == ItemActions.ITEM_ACTION_CODE_STATE_ON){
|
||||
serverBlockTree.start();
|
||||
} else {
|
||||
serverBlockTree.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user