PoseActor caching fix, interact on server

This commit is contained in:
austin 2025-04-03 17:11:20 -04:00
parent 90a88bbd8b
commit 8c530823e7
12 changed files with 169 additions and 7 deletions

View File

@ -5,6 +5,27 @@
"tokens" : [ "tokens" : [
"FLAMMABLE" "FLAMMABLE"
], ],
"hitboxes" : [
{
"type": "hurt",
"offset": [0, 0.6, 0],
"radius": 0.35
}
],
"healthSystem" : {
"maxHealth" : 5,
"onDamageIFrames" : 0,
"lootPool" : {
"tickets" : [
{
"itemId" : "Stick",
"rarity" : 0.8,
"minQuantity" : 1,
"maxQuantity" : 1
}
]
}
},
"buttonInteraction" : { "buttonInteraction" : {
"onInteract" : "harvest", "onInteract" : "harvest",
"interactionShape" : { "interactionShape" : {

View File

@ -1426,6 +1426,9 @@ Add bushes to forest biome
Make foliage data files recursive Make foliage data files recursive
Fix bug with toolbar not unequipping items when moving to empty slot Fix bug with toolbar not unequipping items when moving to empty slot
Break out interaction ray casting into dedicated collision engine object Break out interaction ray casting into dedicated collision engine object
Bush hitbox
Harvesting interaction happens on server
Fix PoseActor position/rotation caching bug

View File

@ -41,6 +41,7 @@ import electrosphere.entity.types.common.CommonEntityFlags;
import electrosphere.entity.types.common.CommonEntityUtils; import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.common.interact.InteractionData; import electrosphere.game.data.common.interact.InteractionData;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.renderer.ui.elements.Window; import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.events.MouseEvent; import electrosphere.renderer.ui.events.MouseEvent;
import electrosphere.renderer.ui.events.ScrollEvent; import electrosphere.renderer.ui.events.ScrollEvent;
@ -623,7 +624,8 @@ public class ControlCategoryMainGame {
WindowUtils.openInteractionMenu(interactionData.getWindowTarget()); WindowUtils.openInteractionMenu(interactionData.getWindowTarget());
} break; } break;
case InteractionData.ON_INTERACT_HARVEST: { case InteractionData.ON_INTERACT_HARVEST: {
System.out.println("Harvest me! :D"); int serverEntityId = Globals.clientSceneWrapper.mapClientToServerId(target.getId());
Globals.clientConnection.queueOutgoingMessage(EntityMessage.constructinteractMessage(serverEntityId, InteractionData.ON_INTERACT_HARVEST));
} break; } break;
default: { default: {
throw new Error("Unhandled interaction signal " + interactionData.getOnInteract()); throw new Error("Unhandled interaction signal " + interactionData.getOnInteract());

View File

@ -27,6 +27,7 @@ import electrosphere.game.data.collidable.HitboxData;
import electrosphere.game.data.utils.DataFormatUtil; import electrosphere.game.data.utils.DataFormatUtil;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.poseactor.PoseActor;
import electrosphere.util.math.SpatialMathUtils; import electrosphere.util.math.SpatialMathUtils;
/** /**
@ -298,7 +299,8 @@ public class HitboxCollectionState {
// //
for(String boneName : this.boneHitboxMap.keySet()){ for(String boneName : this.boneHitboxMap.keySet()){
if(EntityUtils.getPoseActor(parent).containsBone(boneName)){ if(EntityUtils.getPoseActor(parent).containsBone(boneName)){
Vector3d bonePosition = EntityUtils.getPoseActor(parent).getBonePosition(boneName); PoseActor poseActor = EntityUtils.getPoseActor(parent);
Vector3d bonePosition = poseActor.getBonePosition(boneName);
// //
for(HitboxState state : this.boneHitboxMap.get(boneName)){ for(HitboxState state : this.boneHitboxMap.get(boneName)){
if(state == null){ if(state == null){

View File

@ -21,6 +21,7 @@ public class EntityMessage extends NetworkMessage {
ATTACHENTITYTOENTITY, ATTACHENTITYTOENTITY,
UPDATEENTITYVIEWDIR, UPDATEENTITYVIEWDIR,
SYNCPHYSICS, SYNCPHYSICS,
INTERACT,
} }
/** /**
@ -61,6 +62,7 @@ public class EntityMessage extends NetworkMessage {
int targetID; int targetID;
int bTreeID; int bTreeID;
int propertyValueInt; int propertyValueInt;
String interactionSignal;
/** /**
* Constructor * Constructor
@ -558,6 +560,20 @@ public class EntityMessage extends NetworkMessage {
this.propertyValueInt = propertyValueInt; this.propertyValueInt = propertyValueInt;
} }
/**
* Gets interactionSignal
*/
public String getinteractionSignal() {
return interactionSignal;
}
/**
* Sets interactionSignal
*/
public void setinteractionSignal(String interactionSignal) {
this.interactionSignal = interactionSignal;
}
/** /**
* Removes the packet header from the buffer * Removes the packet header from the buffer
* @param byteBuffer The buffer * @param byteBuffer The buffer
@ -626,6 +642,8 @@ public class EntityMessage extends NetworkMessage {
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_INTERACT:
return EntityMessage.canParseinteractMessage(byteBuffer);
} }
return false; return false;
} }
@ -1048,6 +1066,54 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
/**
* Checks if a message of type interact can be parsed from the byte stream
*/
public static boolean canParseinteractMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){
return false;
}
int interactionSignalSize = 0;
if(currentStreamLength < 10){
return false;
} else {
temporaryByteQueue.add(byteBuffer.peek(6 + 0));
temporaryByteQueue.add(byteBuffer.peek(6 + 1));
temporaryByteQueue.add(byteBuffer.peek(6 + 2));
temporaryByteQueue.add(byteBuffer.peek(6 + 3));
interactionSignalSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
}
if(currentStreamLength < 10 + interactionSignalSize){
return false;
}
return true;
}
/**
* Parses a message of type interact
*/
public static EntityMessage parseinteractMessage(CircularByteBuffer byteBuffer, MessagePool pool){
EntityMessage rVal = (EntityMessage)pool.get(MessageType.ENTITY_MESSAGE);
rVal.messageType = EntityMessageType.INTERACT;
EntityMessage.stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setinteractionSignal(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal;
}
/**
* Constructs a message of type interact
*/
public static EntityMessage constructinteractMessage(int entityID,String interactionSignal){
EntityMessage rVal = new EntityMessage(EntityMessageType.INTERACT);
rVal.setentityID(entityID);
rVal.setinteractionSignal(interactionSignal);
rVal.serialize();
return rVal;
}
@Override @Override
void serialize(){ void serialize(){
byte[] intValues = new byte[8]; byte[] intValues = new byte[8];
@ -1411,6 +1477,25 @@ public class EntityMessage extends NetworkMessage {
rawBytes[158+i] = intValues[i]; rawBytes[158+i] = intValues[i];
} }
break; break;
case INTERACT:
rawBytes = new byte[2+4+4+interactionSignal.length()];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
//entity messaage header
rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_INTERACT;
intValues = ByteStreamUtils.serializeIntToBytes(entityID);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(interactionSignal.length());
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
stringBytes = interactionSignal.getBytes();
for(int i = 0; i < interactionSignal.length(); i++){
rawBytes[10+i] = stringBytes[i];
}
break;
} }
serialized = true; serialized = true;
} }

View File

@ -120,6 +120,11 @@ public abstract class NetworkMessage {
rVal = EntityMessage.parsesyncPhysicsMessage(byteBuffer,pool); rVal = EntityMessage.parsesyncPhysicsMessage(byteBuffer,pool);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_INTERACT:
if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseinteractMessage(byteBuffer,pool);
}
break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_LORE: case TypeBytes.MESSAGE_TYPE_LORE:

View File

@ -30,6 +30,7 @@ public class TypeBytes {
public static final byte ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY = 7; public static final byte ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY = 7;
public static final byte ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR = 8; public static final byte ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR = 8;
public static final byte ENTITY_MESSAGE_TYPE_SYNCPHYSICS = 9; public static final byte ENTITY_MESSAGE_TYPE_SYNCPHYSICS = 9;
public static final byte ENTITY_MESSAGE_TYPE_INTERACT = 10;
/* /*
Entity packet sizes Entity packet sizes
*/ */

View File

@ -10,6 +10,7 @@ import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.template.ServerProtocolTemplate; import electrosphere.net.template.ServerProtocolTemplate;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.player.PlayerActions;
/** /**
* The server protocol for handling entity messages * The server protocol for handling entity messages
@ -55,6 +56,10 @@ public class EntityProtocol implements ServerProtocolTemplate<EntityMessage> {
ServerPlayerViewDirTree.getTree(targetEntity).setPlayerViewDir(message.getpropertyType(), message.getyaw(),message.getpitch(),message.gettime()); ServerPlayerViewDirTree.getTree(targetEntity).setPlayerViewDir(message.getpropertyType(), message.getyaw(),message.getpitch(),message.gettime());
} }
} break; } break;
case INTERACT: {
targetEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
PlayerActions.attemptInteraction(connectionHandler, targetEntity, message.getinteractionSignal());
} break;
//ignore stack //ignore stack
case KILL: case KILL:
case DESTROY: case DESTROY:

View File

@ -10,6 +10,7 @@ import electrosphere.entity.state.block.ServerBlockTree;
import electrosphere.entity.state.equip.ServerToolbarState; import electrosphere.entity.state.equip.ServerToolbarState;
import electrosphere.entity.types.common.CommonEntityUtils; import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.common.interact.InteractionData;
import electrosphere.game.data.creature.type.CreatureData; import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.block.BlockVariant; import electrosphere.game.data.creature.type.block.BlockVariant;
import electrosphere.game.data.item.Item; import electrosphere.game.data.item.Item;
@ -21,6 +22,7 @@ import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.server.block.editing.ServerBlockEditing; import electrosphere.server.block.editing.ServerBlockEditing;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.utils.ServerScriptUtils;
/** /**
* Class for handling * Class for handling
@ -109,4 +111,23 @@ public class PlayerActions {
} }
} }
/**
* Attempts to perform an action a player requested
* @param connectionHandler The player's connection handler
* @param target The target if the interaction
* @param signal The type of interaction
*/
public static void attemptInteraction(ServerConnectionHandler connectionHandler, Entity target, String signal){
Entity playerEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
switch(signal){
case InteractionData.ON_INTERACT_HARVEST: {
ServerScriptUtils.fireSignalOnEntity(playerEntity, "entityInteractHarvest", target);
} break;
default: {
throw new Error("Unsupported signal received! " + signal);
}
}
}
} }

View File

@ -96,6 +96,11 @@ public class PoseActor {
for(ActorAnimationMask mask : toRemoveMasks){ for(ActorAnimationMask mask : toRemoveMasks){
animationQueue.remove(mask); animationQueue.remove(mask);
} }
PoseModel model = Globals.assetManager.fetchPoseModel(modelPath);
if(model != null){
this.applyAnimationMasks(model);
this.calculateNodeTransforms(model);
}
} }
/** /**

View File

@ -140,6 +140,10 @@
{ {
"name" : "propertyValueInt", "name" : "propertyValueInt",
"type" : "FIXED_INT" "type" : "FIXED_INT"
},
{
"name" : "interactionSignal",
"type" : "VAR_STRING"
} }
], ],
"messageTypes" : [ "messageTypes" : [
@ -270,6 +274,14 @@
"angForceY", "angForceY",
"angForceZ" "angForceZ"
] ]
},
{
"messageName" : "interact",
"description" : "Interacts with a given entity",
"data" : [
"entityID",
"interactionSignal"
]
} }