From 8c530823e7b95a5dde22237a6c24eb8a3724ba0d Mon Sep 17 00:00:00 2001 From: austin Date: Thu, 3 Apr 2025 17:11:20 -0400 Subject: [PATCH] PoseActor caching fix, interact on server --- assets/Data/entity/foliage/bushes.json | 21 +++++ docs/src/progress/renderertodo.md | 3 + .../categories/ControlCategoryMainGame.java | 4 +- .../state/hitbox/HitboxCollectionState.java | 4 +- .../net/parser/net/message/EntityMessage.java | 85 +++++++++++++++++++ .../parser/net/message/NetworkMessage.java | 5 ++ .../net/parser/net/message/TypeBytes.java | 1 + .../net/parser/net/raw/NetworkParser.java | 10 +-- .../net/server/protocol/EntityProtocol.java | 5 ++ .../server/player/PlayerActions.java | 21 +++++ .../server/poseactor/PoseActor.java | 5 ++ src/net/entity.json | 12 +++ 12 files changed, 169 insertions(+), 7 deletions(-) diff --git a/assets/Data/entity/foliage/bushes.json b/assets/Data/entity/foliage/bushes.json index 1143ec26..5cb07a3f 100644 --- a/assets/Data/entity/foliage/bushes.json +++ b/assets/Data/entity/foliage/bushes.json @@ -5,6 +5,27 @@ "tokens" : [ "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" : { "onInteract" : "harvest", "interactionShape" : { diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 8f129319..e9623dd7 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1426,6 +1426,9 @@ Add bushes to forest biome Make foliage data files recursive Fix bug with toolbar not unequipping items when moving to empty slot Break out interaction ray casting into dedicated collision engine object +Bush hitbox +Harvesting interaction happens on server +Fix PoseActor position/rotation caching bug diff --git a/src/main/java/electrosphere/controls/categories/ControlCategoryMainGame.java b/src/main/java/electrosphere/controls/categories/ControlCategoryMainGame.java index 2b212869..a783f28b 100644 --- a/src/main/java/electrosphere/controls/categories/ControlCategoryMainGame.java +++ b/src/main/java/electrosphere/controls/categories/ControlCategoryMainGame.java @@ -41,6 +41,7 @@ import electrosphere.entity.types.common.CommonEntityFlags; import electrosphere.entity.types.common.CommonEntityUtils; import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.game.data.common.interact.InteractionData; +import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.renderer.ui.elements.Window; import electrosphere.renderer.ui.events.MouseEvent; import electrosphere.renderer.ui.events.ScrollEvent; @@ -623,7 +624,8 @@ public class ControlCategoryMainGame { WindowUtils.openInteractionMenu(interactionData.getWindowTarget()); } break; 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; default: { throw new Error("Unhandled interaction signal " + interactionData.getOnInteract()); diff --git a/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java b/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java index e2e9db42..0eb730ba 100644 --- a/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java +++ b/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java @@ -27,6 +27,7 @@ import electrosphere.game.data.collidable.HitboxData; import electrosphere.game.data.utils.DataFormatUtil; import electrosphere.logger.LoggerInterface; import electrosphere.server.datacell.Realm; +import electrosphere.server.poseactor.PoseActor; import electrosphere.util.math.SpatialMathUtils; /** @@ -298,7 +299,8 @@ public class HitboxCollectionState { // for(String boneName : this.boneHitboxMap.keySet()){ 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)){ if(state == null){ diff --git a/src/main/java/electrosphere/net/parser/net/message/EntityMessage.java b/src/main/java/electrosphere/net/parser/net/message/EntityMessage.java index cf791d35..b4ad0108 100644 --- a/src/main/java/electrosphere/net/parser/net/message/EntityMessage.java +++ b/src/main/java/electrosphere/net/parser/net/message/EntityMessage.java @@ -21,6 +21,7 @@ public class EntityMessage extends NetworkMessage { ATTACHENTITYTOENTITY, UPDATEENTITYVIEWDIR, SYNCPHYSICS, + INTERACT, } /** @@ -61,6 +62,7 @@ public class EntityMessage extends NetworkMessage { int targetID; int bTreeID; int propertyValueInt; + String interactionSignal; /** * Constructor @@ -558,6 +560,20 @@ public class EntityMessage extends NetworkMessage { 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 * @param byteBuffer The buffer @@ -626,6 +642,8 @@ public class EntityMessage extends NetworkMessage { } else { return false; } + case TypeBytes.ENTITY_MESSAGE_TYPE_INTERACT: + return EntityMessage.canParseinteractMessage(byteBuffer); } return false; } @@ -1048,6 +1066,54 @@ public class EntityMessage extends NetworkMessage { 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 temporaryByteQueue = new LinkedList(); + 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 void serialize(){ byte[] intValues = new byte[8]; @@ -1411,6 +1477,25 @@ public class EntityMessage extends NetworkMessage { rawBytes[158+i] = intValues[i]; } 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; } diff --git a/src/main/java/electrosphere/net/parser/net/message/NetworkMessage.java b/src/main/java/electrosphere/net/parser/net/message/NetworkMessage.java index c1fb54bd..5b9889b0 100644 --- a/src/main/java/electrosphere/net/parser/net/message/NetworkMessage.java +++ b/src/main/java/electrosphere/net/parser/net/message/NetworkMessage.java @@ -120,6 +120,11 @@ public abstract class NetworkMessage { rVal = EntityMessage.parsesyncPhysicsMessage(byteBuffer,pool); } break; + case TypeBytes.ENTITY_MESSAGE_TYPE_INTERACT: + if(EntityMessage.canParseMessage(byteBuffer,secondByte)){ + rVal = EntityMessage.parseinteractMessage(byteBuffer,pool); + } + break; } break; case TypeBytes.MESSAGE_TYPE_LORE: diff --git a/src/main/java/electrosphere/net/parser/net/message/TypeBytes.java b/src/main/java/electrosphere/net/parser/net/message/TypeBytes.java index e58b6824..8181c7e1 100644 --- a/src/main/java/electrosphere/net/parser/net/message/TypeBytes.java +++ b/src/main/java/electrosphere/net/parser/net/message/TypeBytes.java @@ -30,6 +30,7 @@ public class TypeBytes { 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_SYNCPHYSICS = 9; + public static final byte ENTITY_MESSAGE_TYPE_INTERACT = 10; /* Entity packet sizes */ diff --git a/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java b/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java index a327d155..5b3d637c 100644 --- a/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java +++ b/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java @@ -1,7 +1,7 @@ -package electrosphere.net.parser.net.raw; - -import electrosphere.net.parser.net.message.MessagePool; -import electrosphere.net.parser.net.message.NetworkMessage; +package electrosphere.net.parser.net.raw; + +import electrosphere.net.parser.net.message.MessagePool; +import electrosphere.net.parser.net.message.NetworkMessage; import io.github.studiorailgun.CircularByteBuffer; import java.io.IOException; import java.io.InputStream; @@ -194,5 +194,5 @@ public class NetworkParser { public void setReleaseOnSend(boolean releaseOnSend){ this.releaseOnSend = releaseOnSend; } - + } diff --git a/src/main/java/electrosphere/net/server/protocol/EntityProtocol.java b/src/main/java/electrosphere/net/server/protocol/EntityProtocol.java index 03be1aa7..938eaa2c 100644 --- a/src/main/java/electrosphere/net/server/protocol/EntityProtocol.java +++ b/src/main/java/electrosphere/net/server/protocol/EntityProtocol.java @@ -10,6 +10,7 @@ import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.template.ServerProtocolTemplate; import electrosphere.server.datacell.utils.EntityLookupUtils; +import electrosphere.server.player.PlayerActions; /** * The server protocol for handling entity messages @@ -55,6 +56,10 @@ public class EntityProtocol implements ServerProtocolTemplate { ServerPlayerViewDirTree.getTree(targetEntity).setPlayerViewDir(message.getpropertyType(), message.getyaw(),message.getpitch(),message.gettime()); } } break; + case INTERACT: { + targetEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId()); + PlayerActions.attemptInteraction(connectionHandler, targetEntity, message.getinteractionSignal()); + } break; //ignore stack case KILL: case DESTROY: diff --git a/src/main/java/electrosphere/server/player/PlayerActions.java b/src/main/java/electrosphere/server/player/PlayerActions.java index b62bcf15..af18fce6 100644 --- a/src/main/java/electrosphere/server/player/PlayerActions.java +++ b/src/main/java/electrosphere/server/player/PlayerActions.java @@ -10,6 +10,7 @@ import electrosphere.entity.state.block.ServerBlockTree; import electrosphere.entity.state.equip.ServerToolbarState; import electrosphere.entity.types.common.CommonEntityUtils; 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.block.BlockVariant; import electrosphere.game.data.item.Item; @@ -21,6 +22,7 @@ import electrosphere.net.server.ServerConnectionHandler; import electrosphere.server.block.editing.ServerBlockEditing; import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.utils.EntityLookupUtils; +import electrosphere.server.utils.ServerScriptUtils; /** * Class for handling @@ -108,5 +110,24 @@ public class PlayerActions { LoggerInterface.loggerEngine.DEBUG("Place block type " + secondaryUsage.getBlockId() + " at " + placementPos + " -> " + worldPos + " " + blockPos); } } + + + /** + * 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); + } + } + } } diff --git a/src/main/java/electrosphere/server/poseactor/PoseActor.java b/src/main/java/electrosphere/server/poseactor/PoseActor.java index 01ecf48c..97b8dd7d 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseActor.java +++ b/src/main/java/electrosphere/server/poseactor/PoseActor.java @@ -96,6 +96,11 @@ public class PoseActor { for(ActorAnimationMask mask : toRemoveMasks){ animationQueue.remove(mask); } + PoseModel model = Globals.assetManager.fetchPoseModel(modelPath); + if(model != null){ + this.applyAnimationMasks(model); + this.calculateNodeTransforms(model); + } } /** diff --git a/src/net/entity.json b/src/net/entity.json index 3eb75712..c0fc7e93 100644 --- a/src/net/entity.json +++ b/src/net/entity.json @@ -140,6 +140,10 @@ { "name" : "propertyValueInt", "type" : "FIXED_INT" + }, + { + "name" : "interactionSignal", + "type" : "VAR_STRING" } ], "messageTypes" : [ @@ -270,6 +274,14 @@ "angForceY", "angForceZ" ] + }, + { + "messageName" : "interact", + "description" : "Interacts with a given entity", + "data" : [ + "entityID", + "interactionSignal" + ] }