diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index f2e93879..3bf0cf6a 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1620,6 +1620,7 @@ Using up charges destroys the item (including toolbar instances) Crafting can consume charges Products from crafting can add charges to existing items Cache busting when physics sync pulls player entity TELEPORT distances +Lotta inventory work to bugfix charges, crafting, in-inventory items, etc diff --git a/src/main/java/electrosphere/client/terrain/foliage/FoliageCellManager.java b/src/main/java/electrosphere/client/terrain/foliage/FoliageCellManager.java index bd9f154e..8349edf6 100644 --- a/src/main/java/electrosphere/client/terrain/foliage/FoliageCellManager.java +++ b/src/main/java/electrosphere/client/terrain/foliage/FoliageCellManager.java @@ -777,6 +777,28 @@ public class FoliageCellManager { foliageCell.setHasRequested(false); } + /** + * Marks a foliage cell as updateable + * @param worldX The world x position + * @param worldY The world y position + * @param worldZ The world z position + */ + public void markUpdateable(int worldX, int worldY, int worldZ){ + for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){ + for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){ + for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){ + int absVoxelX = Globals.clientWorldData.convertRelativeVoxelToAbsoluteVoxelSpace(x,worldX); + int absVoxelY = Globals.clientWorldData.convertRelativeVoxelToAbsoluteVoxelSpace(y,worldY); + int absVoxelZ = Globals.clientWorldData.convertRelativeVoxelToAbsoluteVoxelSpace(z,worldZ); + FoliageCell foliageCell = this.getFoliageCell(absVoxelX, absVoxelY, absVoxelZ); + foliageCell.ejectChunkData(); + foliageCell.setHasGenerated(false); + foliageCell.setHasRequested(false); + } + } + } + } + /** * Requests all chunks for a given foliage cell * @param cell The cell diff --git a/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java b/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java index 5657cebd..35f87d2a 100644 --- a/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java +++ b/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java @@ -182,6 +182,11 @@ public class ClientTerrainManager { data.setVoxelType(values); data.setVoxelWeight(weights); } + if(message.getchunkResolution() == ChunkData.NO_STRIDE && terrainCache.containsChunkDataAtWorldPoint(message.getworldX(), message.getworldY(), message.getworldZ(), ChunkData.NO_STRIDE)){ + //this is a full-res chunk, and we already had this chunk in cache + //need to flag foliage cell to update these positions given that we have changed terrain values + Globals.foliageCellManager.markUpdateable(message.getworldX(), message.getworldY(), message.getworldZ()); + } terrainCache.addChunkDataToCache( message.getworldX(), message.getworldY(), message.getworldZ(), data diff --git a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiDrawCell.java b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiDrawCell.java index 6c33fc6f..12ad8ed2 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiDrawCell.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiDrawCell.java @@ -75,7 +75,7 @@ public class ImGuiDrawCell { } if(ImGui.button("Request terrain at camera position")){ Vector3i cameraWorldPos = Globals.clientWorldData.convertRealToWorldSpace(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); - Globals.clientTerrainManager.requestChunk(cameraWorldPos.x, cameraWorldPos.y, cameraWorldPos.z, 1); + Globals.clientTerrainManager.requestChunk(cameraWorldPos.x, cameraWorldPos.y, cameraWorldPos.z, 0); } } }); diff --git a/src/main/java/electrosphere/entity/state/equip/ClientToolbarState.java b/src/main/java/electrosphere/entity/state/equip/ClientToolbarState.java index 2f167492..3f0d83f2 100644 --- a/src/main/java/electrosphere/entity/state/equip/ClientToolbarState.java +++ b/src/main/java/electrosphere/entity/state/equip/ClientToolbarState.java @@ -95,7 +95,7 @@ public class ClientToolbarState implements BehaviorTree { boolean targetHasWhitelist = ItemUtils.hasEquipList(toEquip); String equipItemClass = ItemUtils.getEquipClass(toEquip); EquipPoint targetPoint = equipInventoryState.getEquipPointFromSlot(toolbarData.getPrimarySlot()); - if(targetPoint.getEquipClassWhitelist() != null && !targetPoint.getEquipClassWhitelist().contains(equipItemClass)){ + if(equipItemClass != null && targetPoint.getEquipClassWhitelist() != null && !targetPoint.getEquipClassWhitelist().contains(equipItemClass)){ targetPoint = equipInventoryState.getEquipPointFromSlot(toolbarData.getCombinedSlot()); } equippedEntity = toEquip; diff --git a/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java b/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java index cb6b338e..fddec8f3 100644 --- a/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java +++ b/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java @@ -140,7 +140,7 @@ public class ServerToolbarState implements BehaviorTree { ItemUtils.setRealWorldEntity(inInventoryEntity, realWorldItem); EquipPoint targetPoint = equipInventoryState.getEquipPointFromSlot(toolbarData.getPrimarySlot()); - if(targetPoint.getEquipClassWhitelist() != null && !targetPoint.getEquipClassWhitelist().contains(equipItemClass)){ + if(equipItemClass != null && targetPoint.getEquipClassWhitelist() != null && !targetPoint.getEquipClassWhitelist().contains(equipItemClass)){ targetPoint = equipInventoryState.getEquipPointFromSlot(toolbarData.getCombinedSlot()); } diff --git a/src/main/java/electrosphere/entity/state/inventory/InventoryUtils.java b/src/main/java/electrosphere/entity/state/inventory/InventoryUtils.java index 69331954..eaa120c4 100644 --- a/src/main/java/electrosphere/entity/state/inventory/InventoryUtils.java +++ b/src/main/java/electrosphere/entity/state/inventory/InventoryUtils.java @@ -264,8 +264,6 @@ public class InventoryUtils { Entity inventoryItem = ItemUtils.serverRecreateContainerItem(item, creature); //store item in inventory inventory.addItem(inventoryItem); - //set item containing parent - ItemUtils.setContainingParent(inventoryItem, creature); //if we are the server, immediately send required packets ServerDataCell dataCell = DataCellSearchUtils.getEntityDataCell(item); // ServerDataCell dataCell = Globals.dataCellLocationResolver.getDataCellAtPoint(EntityUtils.getPosition(item),item); @@ -458,15 +456,7 @@ public class InventoryUtils { } } } - // - //tell player that the item is no longer in their inventory - if(CreatureUtils.hasControllerPlayerId(creature)){ - //get player - int playerId = CreatureUtils.getControllerPlayerId(creature); - Player controllerPlayer = Globals.playerManager.getPlayerFromId(playerId); - //tell the player they don't have the item anymore - controllerPlayer.addMessage(InventoryMessage.constructremoveItemFromInventoryMessage(item.getId())); - } + InventoryUtils.serverRemoveItemFromInventories(creature, item); //get parent realm Realm realm = Globals.realmManager.getEntityRealm(creature); //find "in front of creature" @@ -611,6 +601,15 @@ public class InventoryUtils { Globals.cursorState.hintClearBlockCursor(); ServerToolbarState.getServerToolbarState(creature).update(); } + // + //tell player that the item is no longer in their inventory + if(CreatureUtils.hasControllerPlayerId(creature)){ + //get player + int playerId = CreatureUtils.getControllerPlayerId(creature); + Player controllerPlayer = Globals.playerManager.getPlayerFromId(playerId); + //tell the player they don't have the item anymore + controllerPlayer.addMessage(InventoryMessage.constructremoveItemFromInventoryMessage(item.getId())); + } } /** @@ -654,6 +653,23 @@ public class InventoryUtils { //remove item from inventory inventory.tryRemoveItem(item); } + if(InventoryUtils.hasToolbarInventory(creature)){ + RelationalInventoryState inventory = InventoryUtils.getToolbarInventory(creature); + inventory.tryRemoveItem(item); + if(ServerToolbarState.hasServerToolbarState(creature)){ + ServerToolbarState serverToolbarState = ServerToolbarState.getServerToolbarState(creature); + serverToolbarState.update(); + } + } + // + //tell player that the item is no longer in their inventory + if(CreatureUtils.hasControllerPlayerId(creature)){ + //get player + int playerId = CreatureUtils.getControllerPlayerId(creature); + Player controllerPlayer = Globals.playerManager.getPlayerFromId(playerId); + //tell the player they don't have the item anymore + controllerPlayer.addMessage(InventoryMessage.constructremoveItemFromInventoryMessage(item.getId())); + } ServerEntityUtils.destroyEntity(item); } diff --git a/src/main/java/electrosphere/entity/state/item/ServerChargeState.java b/src/main/java/electrosphere/entity/state/item/ServerChargeState.java index 2e38cba2..21e84bd4 100644 --- a/src/main/java/electrosphere/entity/state/item/ServerChargeState.java +++ b/src/main/java/electrosphere/entity/state/item/ServerChargeState.java @@ -4,16 +4,13 @@ package electrosphere.entity.state.item; import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.state.equip.ServerToolbarState; import electrosphere.entity.state.inventory.InventoryUtils; -import electrosphere.entity.state.inventory.RelationalInventoryState; import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.item.ItemUtils; import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; -import electrosphere.entity.ServerEntityUtils; import electrosphere.net.synchronization.enums.FieldIdEnums; import electrosphere.server.datacell.utils.DataCellSearchUtils; -import electrosphere.net.parser.net.message.InventoryMessage; import electrosphere.net.parser.net.message.SynchronizationMessage; import electrosphere.net.server.player.Player; import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums; @@ -70,21 +67,7 @@ public class ServerChargeState implements BehaviorTree { if(inventoryItem != null){ ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(inventoryItem); if(serverChargeState != null){ - if(serverChargeState.getCharges() - charges > 0){ - serverChargeState.setCharges(serverChargeState.getCharges() - charges); - } else { - if(CreatureUtils.hasControllerPlayerId(parent)){ - //get the player - int controllerPlayerID = CreatureUtils.getControllerPlayerId(parent); - Player controllerPlayer = Globals.playerManager.getPlayerFromId(controllerPlayerID); - //send message - controllerPlayer.addMessage(InventoryMessage.constructremoveItemFromInventoryMessage(inventoryItem.getId())); - } - RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(parent); - toolbarInventory.tryRemoveItem(inventoryItem); - serverToolbarState.update(); - ServerEntityUtils.destroyEntity(inventoryItem); - } + serverChargeState.attemptAddCharges(-charges); } } } diff --git a/src/main/java/electrosphere/entity/types/item/ItemUtils.java b/src/main/java/electrosphere/entity/types/item/ItemUtils.java index 2d663f1e..f67ce620 100644 --- a/src/main/java/electrosphere/entity/types/item/ItemUtils.java +++ b/src/main/java/electrosphere/entity/types/item/ItemUtils.java @@ -41,8 +41,6 @@ import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.server.player.Player; import electrosphere.renderer.actor.Actor; import electrosphere.server.datacell.Realm; -import electrosphere.server.datacell.utils.EntityLookupUtils; -import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.server.datacell.utils.ServerEntityTagUtils; import electrosphere.server.entity.poseactor.PoseActor; @@ -162,13 +160,10 @@ public class ItemUtils { // // if(item.getWeaponData() != null){ - rVal.putData(EntityDataStrings.ITEM_IS_WEAPON, true); WeaponData weaponData = item.getWeaponData(); if(weaponData.getHitboxes() != null){ HitboxCollectionState.attachHitboxState(realm.getHitboxManager(), true, rVal, weaponData.getHitboxes()); } - rVal.putData(EntityDataStrings.ITEM_WEAPON_CLASS,weaponData.getWeaponClass()); - rVal.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData); } //tokens if(item.getTokens() != null){ @@ -192,10 +187,48 @@ public class ItemUtils { if(item.getIdleAnim() != null){ rVal.putData(EntityDataStrings.ANIM_IDLE,item.getIdleAnim()); } + + + //make all non-positional, non-physics data transform here + ItemUtils.serverApplyItemDataTransforms(item,rVal); + + } + + /** + * [SERVER ONLY] Applies transforms that we would expect to be applied to an entity that is an item inside an inventory + * @param item The item data + * @param itemEnt The item entity + */ + private static void serverApplyItemDataTransforms(Item item, Entity itemEnt){ + if(item == null){ + throw new Error("Item data is null"); + } + if(itemEnt == null){ + throw new Error("Item entity is null"); + } + + // + // + //Item specific transforms + // + // + if(item.getWeaponData() != null){ + WeaponData weaponData = item.getWeaponData(); + itemEnt.putData(EntityDataStrings.ITEM_IS_WEAPON, true); + itemEnt.putData(EntityDataStrings.ITEM_WEAPON_CLASS,weaponData.getWeaponClass()); + itemEnt.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData); + } + //tokens + if(item.getTokens() != null){ + for(String token : item.getTokens()){ + switch(token){ + } + } + } if(item.getIconPath() != null && !item.getIconPath().equals("")){ - rVal.putData(EntityDataStrings.ITEM_ICON,item.getIconPath()); + itemEnt.putData(EntityDataStrings.ITEM_ICON,item.getIconPath()); } else { - rVal.putData(EntityDataStrings.ITEM_ICON,AssetDataStrings.UI_TEXTURE_ITEM_ICON_GENERIC); + itemEnt.putData(EntityDataStrings.ITEM_ICON,AssetDataStrings.UI_TEXTURE_ITEM_ICON_GENERIC); } // // @@ -205,28 +238,27 @@ public class ItemUtils { if(item.getEquipData() != null){ EquipData equipData = item.getEquipData(); if(equipData.getEquipWhitelist() != null){ - rVal.putData(EntityDataStrings.ITEM_EQUIP_WHITELIST, equipData.getEquipWhitelist()); + itemEnt.putData(EntityDataStrings.ITEM_EQUIP_WHITELIST, equipData.getEquipWhitelist()); } if(equipData.getEquipClass() != null){ - rVal.putData(EntityDataStrings.ITEM_EQUIP_CLASS,equipData.getEquipClass()); + itemEnt.putData(EntityDataStrings.ITEM_EQUIP_CLASS,equipData.getEquipClass()); } } - rVal.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, false); + itemEnt.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, false); // // Fab data // if(item.getFabData() != null){ - rVal.putData(EntityDataStrings.ITEM_FAB_DATA, item.getFabData()); + itemEnt.putData(EntityDataStrings.ITEM_FAB_DATA, item.getFabData()); } // //stacking behavior // if(item.getMaxStack() != null){ - ServerChargeState.attachTree(rVal, item.getMaxStack()); + ServerChargeState.attachTree(itemEnt, item.getMaxStack()); } - } /** @@ -491,6 +523,29 @@ public class ItemUtils { } } + /** + * [SERVER ONLY] Applies transforms that we would expect to be applied to an entity that is an item inside an inventory + * @param itemData The item data + * @param item The item entity + * @param containingParent The containing parent entity + */ + private static void serverApplyInInventoryItemTransforms(Item itemData, Entity itemEnt, Entity containingParent){ + if(itemData == null){ + throw new Error("Item data is null"); + } + if(itemEnt == null){ + throw new Error("Item entity is null"); + } + if(containingParent == null){ + throw new Error("Containing parent is null"); + } + itemEnt.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, true); + ItemUtils.setContainingParent(itemEnt, containingParent); + CommonEntityUtils.setEntityType(itemEnt, EntityType.ITEM); + CommonEntityUtils.setEntitySubtype(itemEnt, itemData.getId()); + CommonEntityUtils.setCommonData(itemEnt, itemData); + } + /** * Emits an entity which represents the item inside a container @@ -500,30 +555,21 @@ public class ItemUtils { public static Entity serverRecreateContainerItem(Entity item, Entity containingParent){ if(ItemUtils.isItem(item)){ Item itemData = Globals.gameConfigCurrent.getItemMap().getItem(ItemUtils.getType(item)); - Entity rVal = EntityCreationUtils.createRealmlessServerEntity(); - if(ItemUtils.getEquipWhitelist(item) != null){ - rVal.putData(EntityDataStrings.ITEM_EQUIP_WHITELIST, getEquipWhitelist(item)); + Realm realm = Globals.realmManager.getEntityRealm(containingParent); + Entity rVal = EntityCreationUtils.createServerInventoryEntity(realm); + + //apply normal item transforms + ItemUtils.serverApplyItemDataTransforms(itemData, rVal); + + //apply in-inventory transforms + ItemUtils.serverApplyInInventoryItemTransforms(itemData, rVal, containingParent); + + //error checking + if(Globals.realmManager.getEntityRealm(rVal) == null){ + LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Created item without it being assigned to a realm!")); } - - rVal.putData(EntityDataStrings.ITEM_ICON,ItemUtils.getItemIcon(item)); - rVal.putData(EntityDataStrings.ITEM_EQUIP_CLASS, item.getData(EntityDataStrings.ITEM_EQUIP_CLASS)); - CommonEntityUtils.setEntityType(rVal, EntityType.ITEM); - rVal.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, true); - ItemUtils.setContainingParent(rVal, containingParent); - CommonEntityUtils.setEntitySubtype(rVal, CommonEntityUtils.getEntitySubtype(item)); - - //attach to server tracking - Realm realm = Globals.realmManager.getEntityRealm(item); - EntityLookupUtils.registerServerEntity(rVal); - ServerBehaviorTreeUtils.registerEntity(rVal); - Globals.realmManager.mapEntityToRealm(rVal, realm); - Globals.entityDataCellMapper.registerEntity(rVal, realm.getInventoryCell()); - - // - //stacking behavior - // - if(itemData.getMaxStack() != null){ - ServerChargeState.attachTree(rVal, itemData.getMaxStack()); + if(Globals.entityDataCellMapper.getEntityDataCell(rVal) == null){ + throw new Error("Failed to get data cell or the entity"); } return rVal; @@ -548,31 +594,28 @@ public class ItemUtils { throw new Error("Trying to store an item in an entity with no inventories!"); } Realm realm = Globals.realmManager.getEntityRealm(parent); - Vector3d parentPos = EntityUtils.getPosition(parent); //must correct the position such that it spawns inside the realm Entity rVal = EntityCreationUtils.createServerInventoryEntity(realm); + //apply normal item transforms + ItemUtils.serverApplyItemDataTransforms(itemData, rVal); + //apply item transforms to an entity - ItemUtils.serverApplyItemEntityTransforms(realm, parentPos, rVal, itemData); + ItemUtils.serverApplyInInventoryItemTransforms(itemData, rVal, parent); //store the item in its actual inventory naturalInventory.addItem(rVal); - - //associate with parent and set other data - ItemUtils.setContainingParent(rVal, parent); - - //destroy physics - if(realm.getCollisionEngine() != null){ - realm.getCollisionEngine().destroyPhysics(rVal); - } //error checking if(Globals.realmManager.getEntityRealm(rVal) == null){ LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Created item without it being assigned to a realm!")); } + if(Globals.entityDataCellMapper.getEntityDataCell(rVal) == null){ + throw new Error("Failed to get data cell or the entity"); + } //send entity to client if(CreatureUtils.hasControllerPlayerId(parent)){ diff --git a/src/main/java/electrosphere/server/datacell/utils/EntityLookupUtils.java b/src/main/java/electrosphere/server/datacell/utils/EntityLookupUtils.java index 05262435..8ffe23ee 100644 --- a/src/main/java/electrosphere/server/datacell/utils/EntityLookupUtils.java +++ b/src/main/java/electrosphere/server/datacell/utils/EntityLookupUtils.java @@ -12,7 +12,9 @@ import electrosphere.entity.Entity; */ public class EntityLookupUtils { - //map of all entities by their ID + /** + * map of all entities by their ID + */ static Map idToEntityMap = new HashMap(); /**