fab items
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-04-29 21:39:48 -04:00
parent ec7c1371c2
commit c083aaf05f
14 changed files with 203 additions and 7 deletions

View File

@ -7,6 +7,7 @@
"Data/entity/items/debug_tools.json", "Data/entity/items/debug_tools.json",
"Data/entity/items/hand_tools.json", "Data/entity/items/hand_tools.json",
"Data/entity/items/clothing.json", "Data/entity/items/clothing.json",
"Data/entity/items/materials.json" "Data/entity/items/materials.json",
"Data/entity/items/fabs.json"
] ]
} }

View File

@ -0,0 +1,7 @@
{
"items" : [
],
"files" : [
"Data/entity/items/fabs/floors.json"
]
}

View File

@ -0,0 +1,40 @@
{
"items" : [
{
"id" : "woodfloor",
"tokens" : [
"GRAVITY",
"TARGETABLE"
],
"fabData" : {
"fabPath" : "Data/fab/wood_refined_floor.block"
},
"clientSideSecondary" : "PLACE_FAB",
"itemAudio": {
"uiGrabAudio" : "Audio/ui/items/specific/Pick Up Wood A.wav",
"uiReleaseAudio" : "Audio/ui/items/specific/Drop Wood A.wav"
},
"graphicsTemplate": {
"model": {
"path" : "Models/items/minicrate.glb"
}
},
"collidable": {
"type" : "CUBE",
"dimension1" : 0.1,
"dimension2" : 0.1,
"dimension3" : 0.35,
"rotX": 0,
"rotY": 0,
"rotZ": 0,
"rotW": 1,
"offsetX" : 0,
"offsetY" : 0.05,
"offsetZ" : 0
},
"iconPath" : "Textures/icons/itemIconItemGeneric.png"
}
],
"files" : [
]
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 KiB

View File

@ -1602,6 +1602,7 @@ Flower foliage item
Texture loading from model files (ie can load texture path from model file) Texture loading from model files (ie can load texture path from model file)
Clean up material class a bit Clean up material class a bit
Cleaning up dead code Cleaning up dead code
Fab items

View File

@ -48,6 +48,11 @@ public class AssetDataStrings {
public static final String UI_FRAME_TEXTURE_DEFAULT_2 = "Textures/ui/uiFrame2.png"; public static final String UI_FRAME_TEXTURE_DEFAULT_2 = "Textures/ui/uiFrame2.png";
public static final String UI_FRAME_TEXTURE_DEFAULT_3 = "Textures/ui/panel-001.png"; public static final String UI_FRAME_TEXTURE_DEFAULT_3 = "Textures/ui/panel-001.png";
/**
* UI icon textures
*/
public static final String UI_TEXTURE_ITEM_ICON_GENERIC = "Textures/icons/itemIconItemGeneric.png";
/** /**
* UI generic audio * UI generic audio
*/ */

View File

@ -212,6 +212,11 @@ public class EntityDataStrings {
public static final String TREE_SERVERCHARGESTATE = "treeServerChargeState"; public static final String TREE_SERVERCHARGESTATE = "treeServerChargeState";
public static final String TREE_CLIENTCHARGESTATE = "treeClientChargeState"; public static final String TREE_CLIENTCHARGESTATE = "treeClientChargeState";
/**
* Data for placing fabs with an item
*/
public static final String ITEM_FAB_DATA = "itemFabData";
/* /*
Attack behavior tree Attack behavior tree

View File

@ -9,6 +9,7 @@ import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.entity.state.inventory.RelationalInventoryState; import electrosphere.entity.state.inventory.RelationalInventoryState;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils; import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.data.block.BlockFab;
import electrosphere.game.data.common.treedata.TreeDataAnimation; import electrosphere.game.data.common.treedata.TreeDataAnimation;
import electrosphere.game.data.creature.type.equip.EquipPoint; import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.game.data.creature.type.equip.ToolbarData; import electrosphere.game.data.creature.type.equip.ToolbarData;
@ -31,6 +32,7 @@ import electrosphere.entity.EntityUtils;
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums; import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorMeshMask; import electrosphere.renderer.actor.ActorMeshMask;
import electrosphere.util.FileUtils;
import electrosphere.net.parser.net.message.InventoryMessage; import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.synchronization.annotation.SyncedField; import electrosphere.net.synchronization.annotation.SyncedField;
@ -191,6 +193,10 @@ public class ClientToolbarState implements BehaviorTree {
} else if(itemData.getTokens().contains(CursorState.CURSOR_BLOCK_TOKEN)) { } else if(itemData.getTokens().contains(CursorState.CURSOR_BLOCK_TOKEN)) {
Globals.cursorState.setClampToExistingBlock(true); Globals.cursorState.setClampToExistingBlock(true);
CursorState.makeBlockVisible(AssetDataStrings.TEXTURE_RED_TRANSPARENT); CursorState.makeBlockVisible(AssetDataStrings.TEXTURE_RED_TRANSPARENT);
} else if(itemData.getFabData() != null){
Globals.cursorState.setSelectedFab(BlockFab.read(FileUtils.getAssetFile(itemData.getFabData().getFabPath())));
Globals.cursorState.setSelectedFabPath(FileUtils.getAssetFileString(itemData.getFabData().getFabPath()));
CursorState.makeFabVisible();
} }
} }
} }

View File

@ -7,9 +7,9 @@ import org.joml.Vector3d;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
import electrosphere.collision.PhysicsEntityUtils; import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.ClientEntityUtils; import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils; import electrosphere.entity.EntityCreationUtils;
@ -47,9 +47,11 @@ import electrosphere.server.entity.poseactor.PoseActor;
*/ */
public class ItemUtils { public class ItemUtils {
//generic item icon filepath /**
static final String genericItemIconPath = "Textures/icons/itemIconItemGeneric.png"; * Spawns an item on the client
* @param name The name of the item type
* @return The item entity
*/
public static Entity clientSpawnBasicItem(String name){ public static Entity clientSpawnBasicItem(String name){
Item item = Globals.gameConfigCurrent.getItemMap().getItem(name); Item item = Globals.gameConfigCurrent.getItemMap().getItem(name);
Entity rVal = EntityCreationUtils.createClientSpatialEntity(); Entity rVal = EntityCreationUtils.createClientSpatialEntity();
@ -81,7 +83,7 @@ public class ItemUtils {
if(item.getIconPath() != null && !item.getIconPath().equals("")){ if(item.getIconPath() != null && !item.getIconPath().equals("")){
rVal.putData(EntityDataStrings.ITEM_ICON,item.getIconPath()); rVal.putData(EntityDataStrings.ITEM_ICON,item.getIconPath());
} else { } else {
rVal.putData(EntityDataStrings.ITEM_ICON,genericItemIconPath); rVal.putData(EntityDataStrings.ITEM_ICON,AssetDataStrings.UI_TEXTURE_ITEM_ICON_GENERIC);
} }
if(item.getItemAudio() != null){ if(item.getItemAudio() != null){
ItemAudio audio = item.getItemAudio(); ItemAudio audio = item.getItemAudio();
@ -109,6 +111,14 @@ public class ItemUtils {
} }
rVal.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, false); rVal.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, false);
//
// Fab data
//
if(item.getFabData() != null){
rVal.putData(EntityDataStrings.ITEM_FAB_DATA, item.getFabData());
}
Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.ITEM); Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.ITEM);
return rVal; return rVal;
} }
@ -174,7 +184,7 @@ public class ItemUtils {
if(item.getIconPath() != null && !item.getIconPath().equals("")){ if(item.getIconPath() != null && !item.getIconPath().equals("")){
rVal.putData(EntityDataStrings.ITEM_ICON,item.getIconPath()); rVal.putData(EntityDataStrings.ITEM_ICON,item.getIconPath());
} else { } else {
rVal.putData(EntityDataStrings.ITEM_ICON,genericItemIconPath); rVal.putData(EntityDataStrings.ITEM_ICON,AssetDataStrings.UI_TEXTURE_ITEM_ICON_GENERIC);
} }
// //
// //
@ -191,6 +201,14 @@ public class ItemUtils {
} }
} }
rVal.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, false); rVal.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, false);
//
// Fab data
//
if(item.getFabData() != null){
rVal.putData(EntityDataStrings.ITEM_FAB_DATA, item.getFabData());
}
} }
/** /**

View File

@ -82,6 +82,11 @@ public class Item extends CommonEntityType {
*/ */
ItemUsage secondaryUsage; ItemUsage secondaryUsage;
/**
* Item fab data
*/
ItemFabData fabData;
/** /**
* Creates item data from a spawn item description * Creates item data from a spawn item description
* @param description The spawn item description * @param description The spawn item description
@ -261,4 +266,12 @@ public class Item extends CommonEntityType {
this.primaryUsage = primaryUsage; this.primaryUsage = primaryUsage;
} }
/**
* Gets the fab data for this item
* @return The fab data
*/
public ItemFabData getFabData(){
return fabData;
}
} }

View File

@ -0,0 +1,29 @@
package electrosphere.game.data.item;
/**
* Data for placing fabs
*/
public class ItemFabData {
/**
* The path for the fab to place when this item is consumed
*/
String fabPath;
/**
* Gets the path for the corresponding fab file
* @return The path for the corresponding fab file
*/
public String getFabPath() {
return fabPath;
}
/**
* Sets the path for the corresponding fab file
* @param fabPath The path for the corresponding fab file
*/
public void setFabPath(String fabPath) {
this.fabPath = fabPath;
}
}

View File

@ -8,6 +8,7 @@ import electrosphere.util.FileUtils;
import org.lwjgl.PointerBuffer; import org.lwjgl.PointerBuffer;
import org.lwjgl.assimp.AIMaterial; import org.lwjgl.assimp.AIMaterial;
import org.lwjgl.assimp.AIMaterialProperty;
import org.lwjgl.assimp.AIScene; import org.lwjgl.assimp.AIScene;
import org.lwjgl.assimp.AIString; import org.lwjgl.assimp.AIString;
import org.lwjgl.assimp.AITexture; import org.lwjgl.assimp.AITexture;
@ -94,6 +95,7 @@ public class Material {
texPaths[i] = tex.mFilename().dataString(); texPaths[i] = tex.mFilename().dataString();
} }
//discover diffuse //discover diffuse
boolean foundDiffuse = false;
int textureCount = Assimp.aiGetMaterialTextureCount(input, Assimp.aiTextureType_DIFFUSE); int textureCount = Assimp.aiGetMaterialTextureCount(input, Assimp.aiTextureType_DIFFUSE);
if(textureCount > 0){ if(textureCount > 0){
//for the time being, only load the first diffuse //for the time being, only load the first diffuse
@ -118,6 +120,7 @@ public class Material {
rVal.usesFetch = true; rVal.usesFetch = true;
rVal.diffuse = resolved; rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse); Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
foundDiffuse = true;
} }
} else { } else {
String resolved = Material.resolveTexturePath(path, texturePath); String resolved = Material.resolveTexturePath(path, texturePath);
@ -125,6 +128,45 @@ public class Material {
rVal.usesFetch = true; rVal.usesFetch = true;
rVal.diffuse = resolved; rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse); Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
foundDiffuse = true;
}
}
}
if(!foundDiffuse){
textureCount = Assimp.aiGetMaterialTextureCount(input, Assimp.aiTextureType_BASE_COLOR);
if(textureCount > 0){
//for the time being, only load the first diffuse
int textureIndex = 0;
int retCode = Assimp.aiGetMaterialTexture(input, Assimp.aiTextureType_BASE_COLOR, textureIndex, aiPathString, (IntBuffer)null, null, null, null, null, null);
if(retCode != Assimp.aiReturn_SUCCESS){
throw new Error("Failed to read diffuse! " + textureCount + " " + Assimp.aiGetErrorString());
}
String texturePath = aiPathString.dataString();
if(texturePath == null || texturePath.length() <= 0){
throw new Error("Texture path is empty " + texturePath);
}
if(texturePath.length() == 2 && texturePath.startsWith("*")){
//older versions of Assimp require you to read the INDEX of the texture from the material, then look up that texture in the scene itself
//format looks like "*<index>" ie "*0"
int indexInLoadedTexturePaths = Integer.parseInt(texturePath.substring(1));
if(indexInLoadedTexturePaths >= texPaths.length){
throw new Error("Index discovered is outside the array's length " + indexInLoadedTexturePaths + " " + texPaths.length);
}
String resolved = Material.resolveTexturePath(path, texPaths[indexInLoadedTexturePaths]);
if(resolved != null && resolved.length() > 0){
rVal.usesFetch = true;
rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
foundDiffuse = true;
}
} else {
String resolved = Material.resolveTexturePath(path, texturePath);
if(resolved != null && resolved.length() > 0){
rVal.usesFetch = true;
rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
foundDiffuse = true;
}
} }
} }
} }
@ -135,6 +177,25 @@ public class Material {
return rVal; return rVal;
} }
/**
* Describes the properties of a material
* @param material The material
*/
public static void listMaterialProps(AIMaterial material){
LoggerInterface.loggerRenderer.WARNING("Describing material");
for(int i = 0; i < material.mNumProperties(); i++){
AIMaterialProperty prop = AIMaterialProperty.create(material.mProperties().get(i));
String key = prop.mKey().dataString();
int propType = prop.mSemantic();
if(propType == Assimp.aiTextureType_NONE){
//non-texture prop
LoggerInterface.loggerRenderer.WARNING("Prop \"" + key + "\" is not a texture");
} else {
LoggerInterface.loggerRenderer.WARNING("Prop \"" + key + "\" is a texture");
}
}
}
/** /**
* Resolves the filepath of the texture * Resolves the filepath of the texture
* @param path The path of the ai scene itself * @param path The path of the ai scene itself

View File

@ -209,6 +209,16 @@ public class FileUtils {
return targetFile; return targetFile;
} }
/**
* Gets an assets file
* @param pathName The relative path in the assets folder
* @return The file
*/
public static String getAssetFileString(String pathName){
String sanitizedFilePath = sanitizeFilePath(pathName);
return "./assets" + sanitizedFilePath;
}
/** /**
* Gets an assets file as a byte buffer * Gets an assets file as a byte buffer
* @param pathName The relative path in the assets folder * @param pathName The relative path in the assets folder