diff --git a/assets/Data/entity/objects/furniture.json b/assets/Data/entity/objects/furniture.json index 6b0f50f6..c39e5e8c 100644 --- a/assets/Data/entity/objects/furniture.json +++ b/assets/Data/entity/objects/furniture.json @@ -54,6 +54,38 @@ } }, "tokens": [ + "FURNITURE" + ] + }, + { + "id" : "Workbench", + "collidable": { + "type" : "CUBE", + "dimension1" : 0.03, + "dimension2" : 0.03, + "dimension3" : 0.2, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, + "offsetX" : 0.0, + "offsetY" : 0.05, + "offsetZ" : 0.0 + }, + "spawnItem" : { + "graphicsTemplate" : { + "model": { + "path" : "Models/objects/furniture/workbench1.glb" + } + } + }, + "graphicsTemplate": { + "model": { + "path" : "Models/objects/furniture/workbench1.glb" + } + }, + "tokens": [ + "FURNITURE" ] } diff --git a/assets/Data/game/recipes.json b/assets/Data/game/recipes.json index 8a2086b1..0ba9a125 100644 --- a/assets/Data/game/recipes.json +++ b/assets/Data/game/recipes.json @@ -31,6 +31,22 @@ "count": 1 } ] + }, + { + "id": 2, + "displayName": "Workbench", + "ingredients": [ + { + "itemType": "Log", + "count": 1 + } + ], + "products": [ + { + "itemType": "SPAWN_Workbench", + "count": 1 + } + ] } ], "files": [ diff --git a/assets/Models/objects/furniture/texturemap.json b/assets/Models/objects/furniture/texturemap.json index 25c3088f..e80804d5 100644 --- a/assets/Models/objects/furniture/texturemap.json +++ b/assets/Models/objects/furniture/texturemap.json @@ -6,6 +6,13 @@ "diffuse" : "/Textures/wooden.png", "isDefault" : true } + ], + "Models/objects/furniture/workbench1.glb": [ + { + "meshName" : "Cube", + "diffuse" : "/Models/objects/furniture/workbench1.png", + "isDefault" : true + } ] } } \ No newline at end of file diff --git a/assets/Models/objects/furniture/workbench1.glb b/assets/Models/objects/furniture/workbench1.glb new file mode 100644 index 00000000..4bca0258 Binary files /dev/null and b/assets/Models/objects/furniture/workbench1.glb differ diff --git a/assets/Models/objects/furniture/workbench1.png b/assets/Models/objects/furniture/workbench1.png new file mode 100644 index 00000000..b752d214 Binary files /dev/null and b/assets/Models/objects/furniture/workbench1.png differ diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 12be9808..56233806 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1028,6 +1028,15 @@ Fix shovel not having texture Re-enable foliage manager Fix chunk value lookup +(11/14/2024) +Workbench model +Item usage definitions +Way to define auto generated spawner items (ie item form of a furniture item) +Define interaction distance explicitly +Fix client side store-in-inventory transform failing to destroy world-side item +Fix gravity trees failing to handle missing collidables +Fix token NPE + # TODO diff --git a/net/inventory.json b/net/inventory.json index 5dbbf5e2..913bbf7d 100644 --- a/net/inventory.json +++ b/net/inventory.json @@ -36,6 +36,18 @@ { "name" : "itemActionCodeState", "type" : "FIXED_INT" + }, + { + "name" : "viewTargetX", + "type" : "FIXED_DOUBLE" + }, + { + "name" : "viewTargetY", + "type" : "FIXED_DOUBLE" + }, + { + "name" : "viewTargetZ", + "type" : "FIXED_DOUBLE" } ], "messageTypes" : [ @@ -125,7 +137,10 @@ "data" : [ "equipPointId", "itemActionCode", - "itemActionCodeState" + "itemActionCodeState", + "viewTargetX", + "viewTargetY", + "viewTargetZ" ] } ] diff --git a/src/main/java/electrosphere/client/item/ItemActions.java b/src/main/java/electrosphere/client/item/ItemActions.java index 750c4971..0b357586 100644 --- a/src/main/java/electrosphere/client/item/ItemActions.java +++ b/src/main/java/electrosphere/client/item/ItemActions.java @@ -1,6 +1,10 @@ package electrosphere.client.item; +import org.joml.Vector3d; + +import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.script.ClientScriptUtils; +import electrosphere.collision.CollisionEngine; import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.state.attack.ClientAttackTree; @@ -33,8 +37,18 @@ public class ItemActions { * Attempts to perform the primary item action */ public static void attemptPrimaryItemAction(){ + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Vector3d cursorPos = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); //tell the server we want the secondary hand item to START doing something - Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage("handRight", ITEM_ACTION_CODE_PRIMARY, ITEM_ACTION_CODE_STATE_ON)); + Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage( + "handRight", + ITEM_ACTION_CODE_PRIMARY, + ITEM_ACTION_CODE_STATE_ON, + cursorPos.x, + cursorPos.y, + cursorPos.z + )); //TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server) if(Globals.playerEntity != null){ ClientAttackTree attackTree = CreatureUtils.clientGetAttackTree(Globals.playerEntity); @@ -60,8 +74,18 @@ public class ItemActions { * Repeats the primary item action */ public static void repeatPrimaryItemAction(){ + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Vector3d cursorPos = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); //tell the server we want the secondary hand item to STOP doing something - Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage("handRight", ITEM_ACTION_CODE_PRIMARY, ITEM_ACTION_CODE_STATE_REPEAT)); + Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage( + "handRight", + ITEM_ACTION_CODE_PRIMARY, + ITEM_ACTION_CODE_STATE_REPEAT, + cursorPos.x, + cursorPos.y, + cursorPos.z + )); //TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server) } @@ -69,8 +93,18 @@ public class ItemActions { * Releases the primary item action */ public static void releasePrimaryItemAction(){ + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Vector3d cursorPos = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); //tell the server we want the secondary hand item to STOP doing something - Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage("handRight", ITEM_ACTION_CODE_PRIMARY, ITEM_ACTION_CODE_STATE_OFF)); + Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage( + "handRight", + ITEM_ACTION_CODE_PRIMARY, + ITEM_ACTION_CODE_STATE_OFF, + cursorPos.x, + cursorPos.y, + cursorPos.z + )); //TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server) if(Globals.playerEntity != null){ // Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera); @@ -86,8 +120,18 @@ public class ItemActions { * Attempts to perform the secondary item action */ public static void attemptSecondaryItemAction(){ + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Vector3d cursorPos = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); //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)); + Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage( + "handRight", + ITEM_ACTION_CODE_SECONDARY, + ITEM_ACTION_CODE_STATE_ON, + cursorPos.x, + cursorPos.y, + cursorPos.z + )); //TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server) if(Globals.playerEntity != null){ ClientToolbarState clientToolbarState = ClientToolbarState.getClientToolbarState(Globals.playerEntity); @@ -105,8 +149,18 @@ public class ItemActions { * Releases the secondary item action */ public static void releaseSecondaryItemAction(){ + Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); + Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Vector3d cursorPos = Globals.clientSceneWrapper.getCollisionEngine().rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); //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)); + Globals.clientConnection.queueOutgoingMessage(InventoryMessage.constructclientRequestPerformItemActionMessage( + "handRight", + ITEM_ACTION_CODE_SECONDARY, + ITEM_ACTION_CODE_STATE_OFF, + cursorPos.x, + cursorPos.y, + cursorPos.z + )); //TODO: do any immediate client side calculations here (ie start playing an animation until we get response from server) } diff --git a/src/main/java/electrosphere/client/script/ScriptClientVoxelUtils.java b/src/main/java/electrosphere/client/script/ScriptClientVoxelUtils.java index bafab8a8..0b10173e 100644 --- a/src/main/java/electrosphere/client/script/ScriptClientVoxelUtils.java +++ b/src/main/java/electrosphere/client/script/ScriptClientVoxelUtils.java @@ -27,7 +27,7 @@ public class ScriptClientVoxelUtils { ){ Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); - Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(Globals.clientSelectedVoxelType != null){ TerrainEditing.editTerrain(cursorPos, 1.1f, Globals.clientSelectedVoxelType.getId(), 0.1f); } diff --git a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityActorTab.java b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityActorTab.java index 4d836769..6b1f4e7f 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityActorTab.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityActorTab.java @@ -38,6 +38,7 @@ public class ImGuiEntityActorTab { //procedural model if(commonEntityData.getGraphicsTemplate().getProceduralModel() != null && ImGui.collapsingHeader("Procedural Model")){ + ImGui.text("Procedural Model path: " + commonEntityData.getGraphicsTemplate().getProceduralModel()); if(ImGui.button("Regenerate")){ if(commonEntityData.getGraphicsTemplate().getProceduralModel().getTreeModel() != null){ ProceduralTree.setProceduralActor( @@ -47,6 +48,8 @@ public class ImGuiEntityActorTab { ); } } + } else { + ImGui.text("Model path: " + actor.getModelPath()); } //mesh mask diff --git a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java index fc633317..f89b3e43 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java @@ -12,11 +12,13 @@ import electrosphere.client.entity.debug.DebugVisualizerUtils; import electrosphere.collision.PhysicsEntityUtils; import electrosphere.engine.Globals; import electrosphere.entity.Entity; +import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.state.AnimationPriorities; import electrosphere.entity.state.attach.AttachUtils; import electrosphere.entity.state.client.firstPerson.FirstPersonTree; import electrosphere.entity.state.equip.ClientEquipState; +import electrosphere.entity.state.foliage.AmbientFoliage; import electrosphere.entity.state.hitbox.HitboxCollectionState; import electrosphere.entity.state.server.ServerPlayerViewDirTree; import electrosphere.entity.types.creature.CreatureUtils; @@ -100,6 +102,15 @@ public class ImGuiEntityMacros { if(filterToFoliage && !FoliageUtils.isFoliage(entity)){ continue; } + if(filterBasic && + ( + AmbientFoliage.getAmbientFoliageTree(entity) != null || + entity.containsKey(EntityDataStrings.TERRAIN_IS_TERRAIN) || + entity.containsKey(EntityDataStrings.FLUID_IS_FLUID) + ) + ){ + continue; + } ImGui.beginGroup(); ImGui.pushID(entity.getId()); ImGui.text("Id: " + entity.getId() + " (" + getEntityName(entity) + ")"); diff --git a/src/main/java/electrosphere/client/ui/menu/ingame/MenuGeneratorsLevelEditor.java b/src/main/java/electrosphere/client/ui/menu/ingame/MenuGeneratorsLevelEditor.java index cc418d1b..b98c5cb2 100644 --- a/src/main/java/electrosphere/client/ui/menu/ingame/MenuGeneratorsLevelEditor.java +++ b/src/main/java/electrosphere/client/ui/menu/ingame/MenuGeneratorsLevelEditor.java @@ -175,7 +175,7 @@ public class MenuGeneratorsLevelEditor { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0).add(cursorVerticalOffset); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE).add(cursorVerticalOffset); CreatureUtils.serverSpawnBasicCreature(realm, cursorPos, data.getId(), null); })); } @@ -205,9 +205,9 @@ public class MenuGeneratorsLevelEditor { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(cursorPos == null){ - cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).mul(-5.0)); + cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE)); } cursorPos = cursorPos.add(cursorVerticalOffset); UnitUtils.spawnUnit(realm, cursorPos, unitDefinition.getId()); @@ -238,7 +238,7 @@ public class MenuGeneratorsLevelEditor { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0).add(cursorVerticalOffset); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE).add(cursorVerticalOffset); FoliageUtils.serverSpawnTreeFoliage(realm, cursorPos, data.getId(), new Random().nextLong()); })); } @@ -267,7 +267,7 @@ public class MenuGeneratorsLevelEditor { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0).add(cursorVerticalOffset); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE).add(cursorVerticalOffset); ItemUtils.serverSpawnBasicItem(realm, cursorPos, item.getId()); })); } @@ -297,7 +297,7 @@ public class MenuGeneratorsLevelEditor { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0).add(cursorVerticalOffset); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE).add(cursorVerticalOffset); CommonEntityUtils.serverSpawnBasicObject(realm, cursorPos, object.getId()); })); } diff --git a/src/main/java/electrosphere/client/ui/menu/script/ScriptLevelEditorUtils.java b/src/main/java/electrosphere/client/ui/menu/script/ScriptLevelEditorUtils.java index 5fcf0ed6..dc7309bb 100644 --- a/src/main/java/electrosphere/client/ui/menu/script/ScriptLevelEditorUtils.java +++ b/src/main/java/electrosphere/client/ui/menu/script/ScriptLevelEditorUtils.java @@ -40,7 +40,7 @@ public class ScriptLevelEditorUtils { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(cursorPos != null){ cursorPos = cursorPos.add(cursorVerticalOffset); CreatureUtils.serverSpawnBasicCreature(realm, cursorPos, Globals.selectedSpawntype.getId(), null); @@ -51,7 +51,7 @@ public class ScriptLevelEditorUtils { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(cursorPos != null){ cursorPos = cursorPos.add(cursorVerticalOffset); ItemUtils.serverSpawnBasicItem(realm, cursorPos, Globals.selectedSpawntype.getId()); @@ -62,7 +62,7 @@ public class ScriptLevelEditorUtils { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(cursorPos != null){ cursorPos = cursorPos.add(cursorVerticalOffset); FoliageUtils.serverSpawnTreeFoliage(realm, cursorPos, Globals.selectedSpawntype.getId(), new Random().nextLong()); @@ -73,7 +73,7 @@ public class ScriptLevelEditorUtils { Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Realm realm = Globals.realmManager.getRealms().iterator().next(); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = clientCollisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(cursorPos != null){ cursorPos = cursorPos.add(cursorVerticalOffset); CommonEntityUtils.serverSpawnBasicObject(realm, cursorPos, Globals.selectedSpawntype.getId()); @@ -90,7 +90,7 @@ public class ScriptLevelEditorUtils { Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(Globals.playerCamera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); CollisionEngine clientCollisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); //using client collision engine so ray doesn't collide with player entity - Entity target = clientCollisionEngine.rayCast(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Entity target = clientCollisionEngine.rayCast(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); //show detail view here if(target != null){ ImGuiEntityMacros.showEntity(target); diff --git a/src/main/java/electrosphere/collision/CollisionEngine.java b/src/main/java/electrosphere/collision/CollisionEngine.java index b7adbe05..e1e05b0c 100644 --- a/src/main/java/electrosphere/collision/CollisionEngine.java +++ b/src/main/java/electrosphere/collision/CollisionEngine.java @@ -89,6 +89,11 @@ public class CollisionEngine { * Threshold after which the engine warns about collidable count */ public static final int COLLIDABLE_COUNT_WARNING_THRESHOLD = 1000; + + /** + * Default distance to interact with collidables at (ie picking where to place things) + */ + public static final double DEFAULT_INTERACT_DISTANCE = 5.0; //world data that the collision engine leverages for position correction and the like CollisionWorldData collisionWorldData; diff --git a/src/main/java/electrosphere/controls/CameraHandler.java b/src/main/java/electrosphere/controls/CameraHandler.java index 03621ed5..c98e5007 100644 --- a/src/main/java/electrosphere/controls/CameraHandler.java +++ b/src/main/java/electrosphere/controls/CameraHandler.java @@ -179,11 +179,11 @@ public class CameraHandler { ){ Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); - Vector3d cursorPos = collisionEngine.rayCastPosition(centerPos, new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = collisionEngine.rayCastPosition(centerPos, new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(cursorPos != null){ EntityUtils.getPosition(Globals.playerCursor).set(cursorPos); } else { - EntityUtils.getPosition(Globals.playerCursor).set(new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-5.0))); + EntityUtils.getPosition(Globals.playerCursor).set(new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE))); } } } diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java index 89ae0eea..c0435987 100644 --- a/src/main/java/electrosphere/controls/ControlHandler.java +++ b/src/main/java/electrosphere/controls/ControlHandler.java @@ -1123,7 +1123,7 @@ public class ControlHandler { ){ Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); - Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(Globals.clientSelectedVoxelType != null){ TerrainEditing.editTerrain(cursorPos, 1.1f, Globals.clientSelectedVoxelType.getId(), 0.1f); } @@ -1138,7 +1138,7 @@ public class ControlHandler { ){ Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); - Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); if(Globals.clientSelectedVoxelType != null){ TerrainEditing.editTerrain(cursorPos, 1.1f, Globals.clientSelectedVoxelType.getId(), 0.1f); } @@ -1156,7 +1156,7 @@ public class ControlHandler { ){ Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); - Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); TerrainEditing.editTerrain(cursorPos, 1.1f, 1, -0.01f); } }}); @@ -1169,7 +1169,7 @@ public class ControlHandler { ){ Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); - Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), 5.0); + Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); TerrainEditing.editTerrain(cursorPos, 1.1f, 1, -0.01f); } }}); diff --git a/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java b/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java index 5edfc2e8..8b923874 100644 --- a/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java +++ b/src/main/java/electrosphere/entity/state/equip/ServerToolbarState.java @@ -271,8 +271,11 @@ public class ServerToolbarState implements BehaviorTree { // //Visual transforms if(targetHasWhitelist){ + ServerEntityUtils.destroyEntity(this.realWorldItem); + this.realWorldItem = null; } else { ServerEntityUtils.destroyEntity(this.realWorldItem); + this.realWorldItem = null; } // diff --git a/src/main/java/electrosphere/entity/state/gravity/ClientGravityTree.java b/src/main/java/electrosphere/entity/state/gravity/ClientGravityTree.java index 41444aac..c08f234d 100644 --- a/src/main/java/electrosphere/entity/state/gravity/ClientGravityTree.java +++ b/src/main/java/electrosphere/entity/state/gravity/ClientGravityTree.java @@ -83,7 +83,13 @@ public class ClientGravityTree implements BehaviorTree { return this.state == GravityTreeState.ACTIVE; } + @Override public void simulate(float deltaTime){ + + //make sure physics is available + if(this.collidable == null){ + return; + } //state machine switch(state){ diff --git a/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java b/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java index a0985218..b30ae232 100644 --- a/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java +++ b/src/main/java/electrosphere/entity/state/gravity/ServerGravityTree.java @@ -89,6 +89,11 @@ public class ServerGravityTree implements BehaviorTree { * @param deltaTime The time to simulate it for */ public void simulate(float deltaTime){ + + //make sure physics is available + if(collidable == null){ + return; + } //state machine switch(state){ diff --git a/src/main/java/electrosphere/entity/state/inventory/InventoryUtils.java b/src/main/java/electrosphere/entity/state/inventory/InventoryUtils.java index eb0e9fc4..c0a6c62a 100644 --- a/src/main/java/electrosphere/entity/state/inventory/InventoryUtils.java +++ b/src/main/java/electrosphere/entity/state/inventory/InventoryUtils.java @@ -3,6 +3,7 @@ package electrosphere.entity.state.inventory; import org.joml.Vector3d; import electrosphere.engine.Globals; +import electrosphere.entity.ClientEntityUtils; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; @@ -316,7 +317,7 @@ public class InventoryUtils { //convert to in-inventory Entity inventoryItem = ItemUtils.clientRecreateContainerItem(spawnedItem, parentContainer); //destroy the item that was left over - ItemUtils.clientDestroyInWorldItem(spawnedItem); + ClientEntityUtils.destroyEntity(spawnedItem); //store item in inventory inventory.addItem(inventoryItem); //set item containing parent diff --git a/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java b/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java index 57c44345..c14fbccd 100644 --- a/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java +++ b/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java @@ -114,31 +114,33 @@ public class CommonEntityUtils { // Tokens that should be processed before other work is done // // - for(String token : rawType.getTokens()){ - switch(token){ - case "GENERATE_COLLISION_OBJECT": { - Globals.assetManager.addCollisionMeshToQueue(new PhysicsMeshQueueItem(Globals.clientSceneWrapper.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath())); - Globals.clientSceneWrapper.getScene().registerBehaviorTree(new BehaviorTree() {public void simulate(float deltaTime) { - DBody collisionObject = Globals.assetManager.fetchCollisionObject(Globals.clientSceneWrapper.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath()); - if(collisionObject != null){ - Globals.clientSceneWrapper.getScene().deregisterBehaviorTree(this); - CollisionObjUtils.clientAttachCollisionObjectToEntity(entity, collisionObject, 0, Collidable.TYPE_OBJECT); - } - }}); - } break; - case "GENERATE_COLLISION_TERRAIN": { - Globals.assetManager.addCollisionMeshToQueue(new PhysicsMeshQueueItem(Globals.clientSceneWrapper.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath())); - Globals.clientSceneWrapper.getScene().registerBehaviorTree(new BehaviorTree() {public void simulate(float deltaTime) { - DBody collisionObject = Globals.assetManager.fetchCollisionObject(Globals.clientSceneWrapper.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath()); - if(collisionObject != null){ - Globals.clientSceneWrapper.getScene().deregisterBehaviorTree(this); - CollisionObjUtils.clientAttachCollisionObjectToEntity(entity, collisionObject, 0, Collidable.TYPE_TERRAIN); - } - }}); - } break; - case "SEEDED": { - generateDrawable = false; - } break; + if(rawType.getTokens() != null){ + for(String token : rawType.getTokens()){ + switch(token){ + case "GENERATE_COLLISION_OBJECT": { + Globals.assetManager.addCollisionMeshToQueue(new PhysicsMeshQueueItem(Globals.clientSceneWrapper.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath())); + Globals.clientSceneWrapper.getScene().registerBehaviorTree(new BehaviorTree() {public void simulate(float deltaTime) { + DBody collisionObject = Globals.assetManager.fetchCollisionObject(Globals.clientSceneWrapper.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath()); + if(collisionObject != null){ + Globals.clientSceneWrapper.getScene().deregisterBehaviorTree(this); + CollisionObjUtils.clientAttachCollisionObjectToEntity(entity, collisionObject, 0, Collidable.TYPE_OBJECT); + } + }}); + } break; + case "GENERATE_COLLISION_TERRAIN": { + Globals.assetManager.addCollisionMeshToQueue(new PhysicsMeshQueueItem(Globals.clientSceneWrapper.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath())); + Globals.clientSceneWrapper.getScene().registerBehaviorTree(new BehaviorTree() {public void simulate(float deltaTime) { + DBody collisionObject = Globals.assetManager.fetchCollisionObject(Globals.clientSceneWrapper.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath()); + if(collisionObject != null){ + Globals.clientSceneWrapper.getScene().deregisterBehaviorTree(this); + CollisionObjUtils.clientAttachCollisionObjectToEntity(entity, collisionObject, 0, Collidable.TYPE_TERRAIN); + } + }}); + } break; + case "SEEDED": { + generateDrawable = false; + } break; + } } } @@ -411,31 +413,33 @@ public class CommonEntityUtils { // Tokens that should be processed before other work is done // // - for(String token : rawType.getTokens()){ - switch(token){ - case "GENERATE_COLLISION_OBJECT": { - Globals.assetManager.addCollisionMeshToQueue(new PhysicsMeshQueueItem(realm.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath())); - ServerBehaviorTreeUtils.attachBTreeToEntity(entity, new BehaviorTree() {public void simulate(float deltaTime) { - DBody collisionObject = Globals.assetManager.fetchCollisionObject(realm.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath()); - if(collisionObject != null){ - ServerBehaviorTreeUtils.detatchBTreeFromEntity(entity, this); - CollisionObjUtils.serverAttachCollisionObjectToEntity(entity, collisionObject, 0, Collidable.TYPE_OBJECT); - } - }}); - } break; - case "GENERATE_COLLISION_TERRAIN": { - Globals.assetManager.addCollisionMeshToQueue(new PhysicsMeshQueueItem(realm.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath())); - ServerBehaviorTreeUtils.attachBTreeToEntity(entity, new BehaviorTree() {public void simulate(float deltaTime) { - DBody collisionObject = Globals.assetManager.fetchCollisionObject(realm.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath()); - if(collisionObject != null){ - ServerBehaviorTreeUtils.detatchBTreeFromEntity(entity, this); - CollisionObjUtils.serverAttachCollisionObjectToEntity(entity, collisionObject, 0, Collidable.TYPE_TERRAIN); - } - }}); - } break; - case "SEEDED": { - generateDrawable = false; - } break; + if(rawType.getTokens() != null){ + for(String token : rawType.getTokens()){ + switch(token){ + case "GENERATE_COLLISION_OBJECT": { + Globals.assetManager.addCollisionMeshToQueue(new PhysicsMeshQueueItem(realm.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath())); + ServerBehaviorTreeUtils.attachBTreeToEntity(entity, new BehaviorTree() {public void simulate(float deltaTime) { + DBody collisionObject = Globals.assetManager.fetchCollisionObject(realm.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath()); + if(collisionObject != null){ + ServerBehaviorTreeUtils.detatchBTreeFromEntity(entity, this); + CollisionObjUtils.serverAttachCollisionObjectToEntity(entity, collisionObject, 0, Collidable.TYPE_OBJECT); + } + }}); + } break; + case "GENERATE_COLLISION_TERRAIN": { + Globals.assetManager.addCollisionMeshToQueue(new PhysicsMeshQueueItem(realm.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath())); + ServerBehaviorTreeUtils.attachBTreeToEntity(entity, new BehaviorTree() {public void simulate(float deltaTime) { + DBody collisionObject = Globals.assetManager.fetchCollisionObject(realm.getCollisionEngine(),rawType.getGraphicsTemplate().getModel().getPath()); + if(collisionObject != null){ + ServerBehaviorTreeUtils.detatchBTreeFromEntity(entity, this); + CollisionObjUtils.serverAttachCollisionObjectToEntity(entity, collisionObject, 0, Collidable.TYPE_TERRAIN); + } + }}); + } break; + case "SEEDED": { + generateDrawable = false; + } break; + } } } diff --git a/src/main/java/electrosphere/entity/types/item/ItemUtils.java b/src/main/java/electrosphere/entity/types/item/ItemUtils.java index d89bfed8..dc5a1fc3 100644 --- a/src/main/java/electrosphere/entity/types/item/ItemUtils.java +++ b/src/main/java/electrosphere/entity/types/item/ItemUtils.java @@ -143,20 +143,22 @@ public class ItemUtils { rVal.putData(EntityDataStrings.ITEM_WEAPON_DATA_RAW,weaponData); } //tokens - for(String token : item.getTokens()){ - switch(token){ - case "GRAVITY": - Collidable collidable = (Collidable)rVal.getData(EntityDataStrings.PHYSICS_COLLIDABLE); - DBody collisionObject = PhysicsEntityUtils.getDBody(rVal); - ServerGravityTree.attachTree(rVal, collidable, collisionObject, 30); - rVal.putData(EntityDataStrings.GRAVITY_ENTITY, true); + if(item.getTokens() != null){ + for(String token : item.getTokens()){ + switch(token){ + case "GRAVITY": + Collidable collidable = (Collidable)rVal.getData(EntityDataStrings.PHYSICS_COLLIDABLE); + DBody collisionObject = PhysicsEntityUtils.getDBody(rVal); + ServerGravityTree.attachTree(rVal, collidable, collisionObject, 30); + rVal.putData(EntityDataStrings.GRAVITY_ENTITY, true); + break; + case "TARGETABLE": + ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.TARGETABLE); + break; + case "OUTLINE": + rVal.putData(EntityDataStrings.DRAW_OUTLINE, true); break; - case "TARGETABLE": - ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.TARGETABLE); - break; - case "OUTLINE": - rVal.putData(EntityDataStrings.DRAW_OUTLINE, true); - break; + } } } if(item.getIdleAnim() != null){ diff --git a/src/main/java/electrosphere/game/data/Config.java b/src/main/java/electrosphere/game/data/Config.java index 222d69c4..7e634703 100644 --- a/src/main/java/electrosphere/game/data/Config.java +++ b/src/main/java/electrosphere/game/data/Config.java @@ -88,6 +88,9 @@ public class Config { config.recipeMap = RecipeDataMap.loadRecipeFiles("Data/game/recipes.json"); config.biomeMap = BiomeTypeMap.loadBiomeFile("Data/game/biomes.json"); + //create furniture items + ItemDataMap.loadSpawnItems(config.itemMap, config.objectTypeLoader); + //validate ConfigValidator.valdiate(config); diff --git a/src/main/java/electrosphere/game/data/common/CommonEntityType.java b/src/main/java/electrosphere/game/data/common/CommonEntityType.java index 2b275e7c..a13f448e 100644 --- a/src/main/java/electrosphere/game/data/common/CommonEntityType.java +++ b/src/main/java/electrosphere/game/data/common/CommonEntityType.java @@ -5,6 +5,7 @@ import java.util.List; import electrosphere.game.data.collidable.CollidableTemplate; import electrosphere.game.data.collidable.HitboxData; import electrosphere.game.data.common.camera.CameraData; +import electrosphere.game.data.common.item.SpawnItemDescription; import electrosphere.game.data.common.life.HealthSystem; import electrosphere.game.data.common.light.PointLightDescription; import electrosphere.game.data.creature.type.LookAtSystem; @@ -138,6 +139,11 @@ public class CommonEntityType { */ CameraData cameraData; + /** + * Data about a spawn item type should be generated for this common entity type + */ + SpawnItemDescription spawnItem; + /** * Gets the id for this creature type * @return The id @@ -146,6 +152,14 @@ public class CommonEntityType { return id; } + /** + * Sets the id of this entity type + * @param id The new id + */ + public void setId(String id){ + this.id = id; + } + /** * Gets the list of hitboxes for this creature * @return The list of hitbox data @@ -162,6 +176,14 @@ public class CommonEntityType { return tokens; } + /** + * Sets the tokens for this entity type + * @param tokens The list of tokens + */ + public void setTokens(List tokens){ + this.tokens = tokens; + } + /** * Gets the list of data of movement types available to this creature * @return The list of movement type data @@ -282,6 +304,14 @@ public class CommonEntityType { return graphicsTemplate; } + /** + * Sets the graphics template for this object + * @param graphicsTemplate The graphics template + */ + public void setGraphicsTemplate(GraphicsTemplate graphicsTemplate){ + this.graphicsTemplate = graphicsTemplate; + } + /** * Gets the growth model * @return The growth model @@ -329,6 +359,14 @@ public class CommonEntityType { public List getAiTrees() { return aiTrees; } + + /** + * Gets data about a spawn item type should be generated for this common entity type + * @return Data about a spawn item type should be generated for this common entity type + */ + public SpawnItemDescription getSpawnItem(){ + return this.spawnItem; + } } diff --git a/src/main/java/electrosphere/game/data/common/item/SpawnItemDescription.java b/src/main/java/electrosphere/game/data/common/item/SpawnItemDescription.java new file mode 100644 index 00000000..2b35a9d3 --- /dev/null +++ b/src/main/java/electrosphere/game/data/common/item/SpawnItemDescription.java @@ -0,0 +1,38 @@ +package electrosphere.game.data.common.item; + +import electrosphere.game.data.graphics.GraphicsTemplate; + +/** + * Describes an automatically generated item definition for an item that can spawn this object + */ +public class SpawnItemDescription { + + /** + * The icon for the item + */ + String itemIcon; + + /** + * The graphics template for the generated item + */ + GraphicsTemplate graphicsTemplate; + + /** + * Gets the item icon for this spawn item + * @return The item icon + */ + public String getItemIcon() { + return itemIcon; + } + + /** + * Gets the graphics template for this spawn item + * @return The graphics template + */ + public GraphicsTemplate getGraphicsTemplate() { + return graphicsTemplate; + } + + + +} diff --git a/src/main/java/electrosphere/game/data/item/Item.java b/src/main/java/electrosphere/game/data/item/Item.java index 8aea8aac..f3afd337 100644 --- a/src/main/java/electrosphere/game/data/item/Item.java +++ b/src/main/java/electrosphere/game/data/item/Item.java @@ -1,19 +1,46 @@ package electrosphere.game.data.item; +import java.util.Arrays; + import electrosphere.game.data.common.CommonEntityType; +import electrosphere.game.data.common.item.SpawnItemDescription; /** * Data on a given item */ public class Item extends CommonEntityType { - //the idle animation for the item + /** + * The default item icon path + */ + static final String DEFAULT_ITEM_ICON_PATH = "Textures/icons/itemIconItemGeneric.png"; + + /** + * The array of default tokens for all items + */ + static final String[] DEFAULT_TOKENS = new String[]{ + "GRAVITY", + "TARGETABLE", + }; + + /** + * The idle animation for the item + */ String idleAnim; - //the path for the icon texture for this item + + /** + * The path for the icon texture for this item + */ String iconPath; - //weapon data for this item if it is an item + + /** + * Weapon data for this item if it is an item + */ WeaponData weaponData; - //The data defining how this item is equipped + + /** + * The data defining how this item is equipped + */ EquipData equipData; /** @@ -31,11 +58,53 @@ public class Item extends CommonEntityType { */ String clientSideSecondary; + /** + * The usage logic for a secondary usage of this item + */ + ItemUsage secondaryUsage; + /** * The block data for this item */ ItemBlockData itemBlockData; + /** + * Creates item data from a spawn item description + * @param description The spawn item description + * @return The item data + */ + public static Item createSpawnItem(CommonEntityType objectData){ + SpawnItemDescription description = objectData.getSpawnItem(); + + + Item rVal = new Item(); + rVal.setId("SPAWN_" + objectData.getId()); + + + if(description.getItemIcon() != null){ + rVal.iconPath = description.getItemIcon(); + } else { + rVal.iconPath = Item.DEFAULT_ITEM_ICON_PATH; + } + if(description.getGraphicsTemplate() != null){ + rVal.setGraphicsTemplate(description.getGraphicsTemplate()); + } else { + throw new Error("Need to implement handling for when no graphics template is providedd!"); + } + + + //set usage + ItemUsage usage = new ItemUsage(); + usage.setSpawnEntityId(objectData.getId()); + rVal.setSecondaryUsage(usage); + + + //attach common tokens + rVal.setTokens(Arrays.asList(DEFAULT_TOKENS)); + + return rVal; + } + /** * the idle animation for the item * @return @@ -100,4 +169,20 @@ public class Item extends CommonEntityType { return this.itemBlockData; } + /** + * Gets the secondary usage logic of this item + * @return The secondary usage logic + */ + public ItemUsage getSecondaryUsage(){ + return secondaryUsage; + } + + /** + * Sets the secondary usage logic of this item + * @param secondaryUsage The secondary usage logic + */ + public void setSecondaryUsage(ItemUsage secondaryUsage){ + this.secondaryUsage = secondaryUsage; + } + } diff --git a/src/main/java/electrosphere/game/data/item/ItemDataMap.java b/src/main/java/electrosphere/game/data/item/ItemDataMap.java index f37d738f..cbb1e37a 100644 --- a/src/main/java/electrosphere/game/data/item/ItemDataMap.java +++ b/src/main/java/electrosphere/game/data/item/ItemDataMap.java @@ -9,6 +9,8 @@ import java.util.Set; import electrosphere.entity.Entity; import electrosphere.entity.types.item.ItemUtils; +import electrosphere.game.data.common.CommonEntityMap; +import electrosphere.game.data.common.CommonEntityType; import electrosphere.util.FileUtils; /** @@ -110,4 +112,19 @@ public class ItemDataMap { return rVal; } + /** + * Loads all furnitures as items + * @param itemDataMap The item data map + * @param objectMap The object map that contains furniture + */ + public static void loadSpawnItems(ItemDataMap itemDataMap, CommonEntityMap objectMap){ + for(CommonEntityType objectData : objectMap.getTypes()){ + if(objectData.getSpawnItem() != null){ + Item spawnItem = Item.createSpawnItem(objectData); + //create spawn items + itemDataMap.putType(spawnItem.getId(), spawnItem); + } + } + } + } diff --git a/src/main/java/electrosphere/game/data/item/ItemUsage.java b/src/main/java/electrosphere/game/data/item/ItemUsage.java new file mode 100644 index 00000000..c80f9e1b --- /dev/null +++ b/src/main/java/electrosphere/game/data/item/ItemUsage.java @@ -0,0 +1,31 @@ +package electrosphere.game.data.item; + +/** + * Defines what a given use action does with an item + */ +public class ItemUsage { + + /** + * If defined, this item will spawn the provided entity id on use + */ + String spawnEntityId; + + /** + * Gets the spawn entity id of the item usage + * @return The spawn entity id + */ + public String getSpawnEntityId(){ + return spawnEntityId; + } + + /** + * Sets the spawn entity id of the item usage + * @param spawnEntityId The spawn entity id + */ + public void setSpawnEntityId(String spawnEntityId) { + this.spawnEntityId = spawnEntityId; + } + + + +} diff --git a/src/main/java/electrosphere/net/parser/net/message/InventoryMessage.java b/src/main/java/electrosphere/net/parser/net/message/InventoryMessage.java index 18ab2cdb..af64e0ce 100644 --- a/src/main/java/electrosphere/net/parser/net/message/InventoryMessage.java +++ b/src/main/java/electrosphere/net/parser/net/message/InventoryMessage.java @@ -36,6 +36,9 @@ public class InventoryMessage extends NetworkMessage { int toolbarId; int itemActionCode; int itemActionCodeState; + double viewTargetX; + double viewTargetY; + double viewTargetZ; /** * Constructor @@ -162,6 +165,48 @@ public class InventoryMessage extends NetworkMessage { this.itemActionCodeState = itemActionCodeState; } + /** + * Gets viewTargetX + */ + public double getviewTargetX() { + return viewTargetX; + } + + /** + * Sets viewTargetX + */ + public void setviewTargetX(double viewTargetX) { + this.viewTargetX = viewTargetX; + } + + /** + * Gets viewTargetY + */ + public double getviewTargetY() { + return viewTargetY; + } + + /** + * Sets viewTargetY + */ + public void setviewTargetY(double viewTargetY) { + this.viewTargetY = viewTargetY; + } + + /** + * Gets viewTargetZ + */ + public double getviewTargetZ() { + return viewTargetZ; + } + + /** + * Sets viewTargetZ + */ + public void setviewTargetZ(double viewTargetZ) { + this.viewTargetZ = viewTargetZ; + } + /** * Removes the packet header from the buffer * @param byteBuffer The buffer @@ -639,6 +684,15 @@ public class InventoryMessage extends NetworkMessage { if(currentStreamLength < 14 + equipPointIdSize){ return false; } + if(currentStreamLength < 22 + equipPointIdSize){ + return false; + } + if(currentStreamLength < 30 + equipPointIdSize){ + return false; + } + if(currentStreamLength < 38 + equipPointIdSize){ + return false; + } return true; } @@ -651,17 +705,23 @@ public class InventoryMessage extends NetworkMessage { rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer)); rVal.setitemActionCode(ByteStreamUtils.popIntFromByteQueue(byteBuffer)); rVal.setitemActionCodeState(ByteStreamUtils.popIntFromByteQueue(byteBuffer)); + rVal.setviewTargetX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer)); + rVal.setviewTargetY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer)); + rVal.setviewTargetZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer)); return rVal; } /** * Constructs a message of type clientRequestPerformItemAction */ - public static InventoryMessage constructclientRequestPerformItemActionMessage(String equipPointId,int itemActionCode,int itemActionCodeState){ + public static InventoryMessage constructclientRequestPerformItemActionMessage(String equipPointId,int itemActionCode,int itemActionCodeState,double viewTargetX,double viewTargetY,double viewTargetZ){ InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTPERFORMITEMACTION); rVal.setequipPointId(equipPointId); rVal.setitemActionCode(itemActionCode); rVal.setitemActionCodeState(itemActionCodeState); + rVal.setviewTargetX(viewTargetX); + rVal.setviewTargetY(viewTargetY); + rVal.setviewTargetZ(viewTargetZ); rVal.serialize(); return rVal; } @@ -854,7 +914,7 @@ public class InventoryMessage extends NetworkMessage { } break; case CLIENTREQUESTPERFORMITEMACTION: - rawBytes = new byte[2+4+equipPointId.length()+4+4]; + rawBytes = new byte[2+4+equipPointId.length()+4+4+8+8+8]; //message header rawBytes[0] = TypeBytes.MESSAGE_TYPE_INVENTORY; //entity messaage header @@ -875,6 +935,18 @@ public class InventoryMessage extends NetworkMessage { for(int i = 0; i < 4; i++){ rawBytes[10+equipPointId.length()+i] = intValues[i]; } + intValues = ByteStreamUtils.serializeDoubleToBytes(viewTargetX); + for(int i = 0; i < 8; i++){ + rawBytes[14+equipPointId.length()+i] = intValues[i]; + } + intValues = ByteStreamUtils.serializeDoubleToBytes(viewTargetY); + for(int i = 0; i < 8; i++){ + rawBytes[22+equipPointId.length()+i] = intValues[i]; + } + intValues = ByteStreamUtils.serializeDoubleToBytes(viewTargetZ); + for(int i = 0; i < 8; i++){ + rawBytes[30+equipPointId.length()+i] = intValues[i]; + } break; } serialized = true; diff --git a/src/main/java/electrosphere/server/player/PlayerActions.java b/src/main/java/electrosphere/server/player/PlayerActions.java index 59f2cbd2..d82635ab 100644 --- a/src/main/java/electrosphere/server/player/PlayerActions.java +++ b/src/main/java/electrosphere/server/player/PlayerActions.java @@ -1,10 +1,18 @@ package electrosphere.server.player; +import org.joml.Vector3d; + import electrosphere.client.item.ItemActions; +import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.state.block.ServerBlockTree; +import electrosphere.entity.state.equip.ServerToolbarState; +import electrosphere.entity.types.common.CommonEntityUtils; +import electrosphere.game.data.item.Item; +import electrosphere.game.data.item.ItemUsage; import electrosphere.net.parser.net.message.InventoryMessage; import electrosphere.net.server.ServerConnectionHandler; +import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.utils.EntityLookupUtils; /** @@ -21,15 +29,47 @@ public class PlayerActions { 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(); + ServerToolbarState serverToolbarState = ServerToolbarState.getServerToolbarState(playerEntity); + if(serverToolbarState != null && serverToolbarState.getRealWorldItem() != null){ + Item item = Globals.gameConfigCurrent.getItemMap().getItem(serverToolbarState.getRealWorldItem()); + if(item.getBlockSystem() != null){ + PlayerActions.block(playerEntity, message); + } else if(item.getSecondaryUsage() != null){ + PlayerActions.secondaryUsage(playerEntity, item, message); } } } } + + /** + * Attempts to block + */ + private static void block(Entity playerEntity, InventoryMessage message){ + ServerBlockTree serverBlockTree = ServerBlockTree.getServerBlockTree(playerEntity); + if(serverBlockTree != null){ + if(message.getitemActionCodeState() == ItemActions.ITEM_ACTION_CODE_STATE_ON){ + serverBlockTree.start(); + } else { + serverBlockTree.stop(); + } + } + } + + /** + * Performs various secondary usages + * @param playerEntity The player's entity + * @param item The item data + * @param message The message + */ + private static void secondaryUsage(Entity playerEntity, Item item, InventoryMessage message){ + ItemUsage secondaryUsage = item.getSecondaryUsage(); + Realm playerRealm = Globals.realmManager.getEntityRealm(playerEntity); + if(secondaryUsage.getSpawnEntityId() != null){ + Vector3d spawnPos = new Vector3d(message.getviewTargetX(),message.getviewTargetY(),message.getviewTargetZ()); + CommonEntityUtils.serverSpawnBasicObject(playerRealm, spawnPos, secondaryUsage.getSpawnEntityId()); + } + } + + }