unified item transfer flow

This commit is contained in:
austin 2025-05-13 16:45:21 -04:00
parent 676494ff20
commit 198ce812bd
11 changed files with 245 additions and 19 deletions

View File

@ -1754,6 +1754,8 @@ Inventory window max width
Natural inventory panel wraps on width limit Natural inventory panel wraps on width limit
Fix target inventory window clearing Fix target inventory window clearing
Non-ideal implementation of multiple inventory windows drawing at once Non-ideal implementation of multiple inventory windows drawing at once
Inventory packet for unified item transform requests from client
Server inventory utility for unified item transform requests

View File

@ -14,6 +14,9 @@ import electrosphere.entity.state.inventory.RelationalInventoryState;
import electrosphere.entity.state.inventory.UnrelationalInventoryState; import electrosphere.entity.state.inventory.UnrelationalInventoryState;
import electrosphere.entity.types.item.ItemUtils; import electrosphere.entity.types.item.ItemUtils;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.server.protocol.InventoryProtocol;
import electrosphere.renderer.ui.elements.Div; import electrosphere.renderer.ui.elements.Div;
import electrosphere.renderer.ui.elements.Label; import electrosphere.renderer.ui.elements.Label;
import electrosphere.renderer.ui.elementtypes.ClickableElement.ClickEventCallback; import electrosphere.renderer.ui.elementtypes.ClickableElement.ClickEventCallback;
@ -130,19 +133,26 @@ public class NaturalInventoryPanel {
panel = ItemIconPanel.createPanel(currentItem, i, inventory); panel = ItemIconPanel.createPanel(currentItem, i, inventory);
} else { } else {
panel = ItemIconPanel.createEmptyItemPanel(() -> { panel = ItemIconPanel.createEmptyItemPanel(() -> {
if(Globals.dragSourceInventory instanceof RelationalInventoryState){ NetworkMessage requestPickupMessage = InventoryMessage.constructclientRequestStoreItemMessage(
if(Globals.dragSourceInventory == InventoryUtils.getToolbarInventory(entity)){ Globals.clientSceneWrapper.mapClientToServerId(entity.getId()),
InventoryUtils.clientAddToNatural(Globals.draggedItem); InventoryProtocol.INVENTORY_TYPE_NATURAL,
} else if(Globals.dragSourceInventory == InventoryUtils.getEquipInventory(entity)){ 0 + "",
RelationalInventoryState equipInventory = InventoryUtils.getEquipInventory(entity); Globals.clientSceneWrapper.mapClientToServerId(Globals.draggedItem.getId())
ClientEquipState equipState = ClientEquipState.getEquipState(entity); );
equipState.commandAttemptUnequip(equipInventory.getItemSlot(Globals.draggedItem)); Globals.clientConnection.queueOutgoingMessage(requestPickupMessage);
} // if(Globals.dragSourceInventory instanceof RelationalInventoryState){
} else if(Globals.dragSourceInventory instanceof UnrelationalInventoryState){ // if(Globals.dragSourceInventory == InventoryUtils.getToolbarInventory(entity)){
if(ItemUtils.getContainingParent(Globals.draggedItem) != Globals.playerEntity){ // InventoryUtils.clientAddToNatural(Globals.draggedItem);
throw new UnsupportedOperationException("Unimplemented!"); // } else if(Globals.dragSourceInventory == InventoryUtils.getEquipInventory(entity)){
} // RelationalInventoryState equipInventory = InventoryUtils.getEquipInventory(entity);
} // ClientEquipState equipState = ClientEquipState.getEquipState(entity);
// equipState.commandAttemptUnequip(equipInventory.getItemSlot(Globals.draggedItem));
// }
// } else if(Globals.dragSourceInventory instanceof UnrelationalInventoryState){
// if(ItemUtils.getContainingParent(Globals.draggedItem) != Globals.playerEntity){
// throw new UnsupportedOperationException("Unimplemented!");
// }
// }
}); });
} }
panelContainer.addChild(panel); panelContainer.addChild(panel);

View File

@ -191,6 +191,7 @@ public class ClientInventoryState implements BehaviorTree {
ClientChargeState clientChargeState = ClientChargeState.getClientChargeState(clientInventoryItem); ClientChargeState clientChargeState = ClientChargeState.getClientChargeState(clientInventoryItem);
clientChargeState.setCharges(message.getcharges()); clientChargeState.setCharges(message.getcharges());
} break; } break;
case CLIENTREQUESTSTOREITEM:
case CLIENTREQUESTCRAFT: case CLIENTREQUESTCRAFT:
case CLIENTUPDATETOOLBAR: case CLIENTUPDATETOOLBAR:
case CLIENTREQUESTADDNATURAL: case CLIENTREQUESTADDNATURAL:

View File

@ -7,6 +7,7 @@ import java.util.stream.Collectors;
import org.joml.Vector3d; import org.joml.Vector3d;
import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType; import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
import electrosphere.data.creature.equip.EquipPoint;
import electrosphere.data.item.Item; import electrosphere.data.item.Item;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
@ -284,6 +285,43 @@ public class InventoryUtils {
return inventoryItem; return inventoryItem;
} }
/**
* Tries to add an item to a given inventory on a given container
* @param container The container to store the item in
* @param item The item to store
* @param containerType The type of container to store into
* @param slotId (Optional) The slot within the container to store into
* @return The in-inventory item
*/
public static void serverAttemptStoreItemTransform(Entity container, Entity itemEnt, int containerType, String slotId){
if(itemEnt == null){
throw new Error("Null item provided! " + itemEnt);
}
if(!ItemUtils.isItem(itemEnt)){
throw new Error("Item is not an item!");
}
if(containerType != InventoryProtocol.INVENTORY_TYPE_EQUIP && containerType != InventoryProtocol.INVENTORY_TYPE_NATURAL && containerType != InventoryProtocol.INVENTORY_TYPE_TOOLBAR){
throw new Error("Invalid container type! " + containerType);
}
//check if should remove from existing container
if(ItemUtils.getContainingParent(itemEnt) != null && ItemUtils.getContainingParent(itemEnt) != container){
Entity existingContainer = ItemUtils.getContainingParent(itemEnt);
InventoryUtils.serverRemoveItemFromInventories(existingContainer,itemEnt);
}
if(containerType == InventoryProtocol.INVENTORY_TYPE_EQUIP){
ServerEquipState equipState = ServerEquipState.getEquipState(container);
EquipPoint point = equipState.getEquipPoint(slotId);
equipState.commandAttemptEquip(itemEnt, point);
} else if(containerType == InventoryProtocol.INVENTORY_TYPE_NATURAL){
InventoryUtils.serverAddToNatural(container, itemEnt);
} else if(containerType == InventoryProtocol.INVENTORY_TYPE_TOOLBAR){
ServerToolbarState serverToolbarState = ServerToolbarState.getServerToolbarState(container);
serverToolbarState.attemptEquip(itemEnt, Integer.parseInt(slotId));
}
}
/** /**
* Perform the entity transforms to actually store an item in an inventory, if server this has the side effect of also sending packets on success * Perform the entity transforms to actually store an item in an inventory, if server this has the side effect of also sending packets on success
* @param creature The creature to store the item in * @param creature The creature to store the item in

View File

@ -8,6 +8,8 @@ import electrosphere.entity.Entity;
import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.equip.ServerEquipState; import electrosphere.entity.state.equip.ServerEquipState;
import electrosphere.entity.state.equip.ServerToolbarState; import electrosphere.entity.state.equip.ServerToolbarState;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.InventoryMessage; import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
@ -89,6 +91,30 @@ public class ServerInventoryState implements BehaviorTree {
ServerToolbarState serverToolbarState = ServerToolbarState.getServerToolbarState(parent); ServerToolbarState serverToolbarState = ServerToolbarState.getServerToolbarState(parent);
serverToolbarState.attemptChangeSelection(message.gettoolbarId()); serverToolbarState.attemptChangeSelection(message.gettoolbarId());
} break; } break;
case CLIENTREQUESTSTOREITEM: {
Entity itemEnt = EntityLookupUtils.getEntityById(message.getitemEntId());
Entity currentParent = ItemUtils.getContainingParent(itemEnt);
Entity container = EntityLookupUtils.getEntityById(message.gettargetEntId());
//error checking
if(itemEnt == null){
throw new Error("Failed to locate server entity " + message.getitemEntId());
}
if(container == null){
throw new Error("Failed to locate server entity " + message.gettargetEntId());
}
//picking up from in the world
if(currentParent == null){
if(container != this.parent){
LoggerInterface.loggerEngine.WARNING("A client is trying to pick up an item for another entity!");
} else {
InventoryUtils.serverAttemptStoreItemTransform(parent, itemEnt, message.getcontainerType(), message.getequipPointId());
}
}
//transfering from one container to another
if(currentParent != null){
InventoryUtils.serverAttemptStoreItemTransform(container, itemEnt, message.getcontainerType(), message.getequipPointId());
}
} break;
case CLIENTREQUESTCRAFT: case CLIENTREQUESTCRAFT:
case CLIENTREQUESTPERFORMITEMACTION: case CLIENTREQUESTPERFORMITEMACTION:
case SERVERCOMMANDUNEQUIPITEM: case SERVERCOMMANDUNEQUIPITEM:

View File

@ -74,6 +74,7 @@ public class InventoryProtocol implements ClientProtocolTemplate<InventoryMessag
} }
} }
} break; } break;
case CLIENTREQUESTSTOREITEM:
case CLIENTREQUESTCRAFT: case CLIENTREQUESTCRAFT:
case CLIENTUPDATETOOLBAR: case CLIENTUPDATETOOLBAR:
case CLIENTREQUESTADDNATURAL: case CLIENTREQUESTADDNATURAL:

View File

@ -18,6 +18,7 @@ public class InventoryMessage extends NetworkMessage {
SERVERCOMMANDEQUIPITEM, SERVERCOMMANDEQUIPITEM,
SERVERCOMMANDUNEQUIPITEM, SERVERCOMMANDUNEQUIPITEM,
CLIENTREQUESTUNEQUIPITEM, CLIENTREQUESTUNEQUIPITEM,
CLIENTREQUESTSTOREITEM,
CLIENTREQUESTADDTOOLBAR, CLIENTREQUESTADDTOOLBAR,
CLIENTREQUESTADDNATURAL, CLIENTREQUESTADDNATURAL,
CLIENTUPDATETOOLBAR, CLIENTUPDATETOOLBAR,
@ -33,6 +34,8 @@ public class InventoryMessage extends NetworkMessage {
String itemTemplate; String itemTemplate;
String equipPointId; String equipPointId;
int entityId; int entityId;
int itemEntId;
int targetEntId;
int equipperId; int equipperId;
int containerType; int containerType;
int toolbarId; int toolbarId;
@ -107,6 +110,34 @@ public class InventoryMessage extends NetworkMessage {
this.entityId = entityId; this.entityId = entityId;
} }
/**
* Gets itemEntId
*/
public int getitemEntId() {
return itemEntId;
}
/**
* Sets itemEntId
*/
public void setitemEntId(int itemEntId) {
this.itemEntId = itemEntId;
}
/**
* Gets targetEntId
*/
public int gettargetEntId() {
return targetEntId;
}
/**
* Sets targetEntId
*/
public void settargetEntId(int targetEntId) {
this.targetEntId = targetEntId;
}
/** /**
* Gets equipperId * Gets equipperId
*/ */
@ -295,6 +326,8 @@ public class InventoryMessage extends NetworkMessage {
return InventoryMessage.canParseserverCommandUnequipItemMessage(byteBuffer); return InventoryMessage.canParseserverCommandUnequipItemMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM:
return InventoryMessage.canParseclientRequestUnequipItemMessage(byteBuffer); return InventoryMessage.canParseclientRequestUnequipItemMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTSTOREITEM:
return InventoryMessage.canParseclientRequestStoreItemMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDTOOLBAR: case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDTOOLBAR:
if(byteBuffer.getRemaining() >= TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDTOOLBAR_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDTOOLBAR_SIZE){
return true; return true;
@ -670,6 +703,64 @@ public class InventoryMessage extends NetworkMessage {
return rVal; return rVal;
} }
/**
* Checks if a message of type clientRequestStoreItem can be parsed from the byte stream
*/
public static boolean canParseclientRequestStoreItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList<Byte>();
if(currentStreamLength < 6){
return false;
}
if(currentStreamLength < 10){
return false;
}
int equipPointIdSize = 0;
if(currentStreamLength < 14){
return false;
} else {
temporaryByteQueue.add(byteBuffer.peek(10 + 0));
temporaryByteQueue.add(byteBuffer.peek(10 + 1));
temporaryByteQueue.add(byteBuffer.peek(10 + 2));
temporaryByteQueue.add(byteBuffer.peek(10 + 3));
equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
}
if(currentStreamLength < 14 + equipPointIdSize){
return false;
}
if(currentStreamLength < 18 + equipPointIdSize){
return false;
}
return true;
}
/**
* Parses a message of type clientRequestStoreItem
*/
public static InventoryMessage parseclientRequestStoreItemMessage(CircularByteBuffer byteBuffer, MessagePool pool){
InventoryMessage rVal = (InventoryMessage)pool.get(MessageType.INVENTORY_MESSAGE);
rVal.messageType = InventoryMessageType.CLIENTREQUESTSTOREITEM;
InventoryMessage.stripPacketHeader(byteBuffer);
rVal.settargetEntId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setcontainerType(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.setitemEntId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal;
}
/**
* Constructs a message of type clientRequestStoreItem
*/
public static InventoryMessage constructclientRequestStoreItemMessage(int targetEntId,int containerType,String equipPointId,int itemEntId){
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTSTOREITEM);
rVal.settargetEntId(targetEntId);
rVal.setcontainerType(containerType);
rVal.setequipPointId(equipPointId);
rVal.setitemEntId(itemEntId);
rVal.serialize();
return rVal;
}
/** /**
* Parses a message of type clientRequestAddToolbar * Parses a message of type clientRequestAddToolbar
*/ */
@ -1001,6 +1092,33 @@ public class InventoryMessage extends NetworkMessage {
rawBytes[6+i] = stringBytes[i]; rawBytes[6+i] = stringBytes[i];
} }
break; break;
case CLIENTREQUESTSTOREITEM:
rawBytes = new byte[2+4+4+4+equipPointId.length()+4];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_INVENTORY;
//entity messaage header
rawBytes[1] = TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTSTOREITEM;
intValues = ByteStreamUtils.serializeIntToBytes(targetEntId);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(containerType);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(equipPointId.length());
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
}
stringBytes = equipPointId.getBytes();
for(int i = 0; i < equipPointId.length(); i++){
rawBytes[14+i] = stringBytes[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(itemEntId);
for(int i = 0; i < 4; i++){
rawBytes[14+equipPointId.length()+i] = intValues[i];
}
break;
case CLIENTREQUESTADDTOOLBAR: case CLIENTREQUESTADDTOOLBAR:
rawBytes = new byte[2+4+4]; rawBytes = new byte[2+4+4];
//message header //message header

View File

@ -385,6 +385,11 @@ public abstract class NetworkMessage {
rVal = InventoryMessage.parseclientRequestUnequipItemMessage(byteBuffer,pool); rVal = InventoryMessage.parseclientRequestUnequipItemMessage(byteBuffer,pool);
} }
break; break;
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTSTOREITEM:
if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseclientRequestStoreItemMessage(byteBuffer,pool);
}
break;
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDTOOLBAR: case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDTOOLBAR:
if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseclientRequestAddToolbarMessage(byteBuffer,pool); rVal = InventoryMessage.parseclientRequestAddToolbarMessage(byteBuffer,pool);

View File

@ -159,12 +159,13 @@ public class TypeBytes {
public static final byte INVENTORY_MESSAGE_TYPE_SERVERCOMMANDEQUIPITEM = 4; 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_SERVERCOMMANDUNEQUIPITEM = 5;
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM = 6; public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM = 6;
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDTOOLBAR = 7; public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTSTOREITEM = 7;
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDNATURAL = 8; public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDTOOLBAR = 8;
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTUPDATETOOLBAR = 9; public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTADDNATURAL = 9;
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION = 10; public static final byte INVENTORY_MESSAGE_TYPE_CLIENTUPDATETOOLBAR = 10;
public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTCRAFT = 11; public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTPERFORMITEMACTION = 11;
public static final byte INVENTORY_MESSAGE_TYPE_SERVERUPDATEITEMCHARGES = 12; public static final byte INVENTORY_MESSAGE_TYPE_CLIENTREQUESTCRAFT = 12;
public static final byte INVENTORY_MESSAGE_TYPE_SERVERUPDATEITEMCHARGES = 13;
/* /*
Inventory packet sizes Inventory packet sizes
*/ */

View File

@ -101,6 +101,12 @@ public class InventoryProtocol implements ServerProtocolTemplate<InventoryMessag
// InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message); // InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
} }
} break; } break;
case CLIENTREQUESTSTOREITEM: {
target = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
if(target != null && InventoryUtils.hasNaturalInventory(target)){
InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
}
} break;
case SERVERCOMMANDUNEQUIPITEM: case SERVERCOMMANDUNEQUIPITEM:
case SERVERCOMMANDMOVEITEMCONTAINER: case SERVERCOMMANDMOVEITEMCONTAINER:
case SERVERCOMMANDEQUIPITEM: case SERVERCOMMANDEQUIPITEM:

View File

@ -17,6 +17,14 @@
"name" : "entityId", "name" : "entityId",
"type" : "FIXED_INT" "type" : "FIXED_INT"
}, },
{
"name" : "itemEntId",
"type" : "FIXED_INT"
},
{
"name" : "targetEntId",
"type" : "FIXED_INT"
},
{ {
"name" : "equipperId", "name" : "equipperId",
"type" : "FIXED_INT" "type" : "FIXED_INT"
@ -121,6 +129,16 @@
"equipPointId" "equipPointId"
] ]
}, },
{
"messageName" : "clientRequestStoreItem",
"description" : "Requests that a given item be placed in a given container type on a given container",
"data" : [
"targetEntId",
"containerType",
"equipPointId",
"itemEntId"
]
},
{ {
"messageName" : "clientRequestAddToolbar", "messageName" : "clientRequestAddToolbar",
"description" : "Requests that the server add the item to the client entity's toolbar", "description" : "Requests that the server add the item to the client entity's toolbar",