growing component scaffolding
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-13 12:31:29 -04:00
parent 7f33ba6348
commit b43d795a23
15 changed files with 453 additions and 1 deletions

View File

@ -7,6 +7,7 @@
"Data/entity/objects/debug_objects.json",
"Data/entity/objects/game_objects.json",
"Data/entity/objects/containers.json",
"Data/entity/objects/furniture.json"
"Data/entity/objects/furniture.json",
"Data/entity/objects/crops.json"
]
}

View File

@ -0,0 +1,38 @@
{
"objects" : [
{
"id" : "wheat",
"hitboxData" : [
{
"type": "static_capsule",
"radius": 2,
"length": 5
}
],
"tokens": [
],
"graphicsTemplate": {
"model": {
"path" : "Models/foliage/flowers/Flower_3_Group.gltf"
}
},
"growthData" : {
"growthMax" : 1000,
"scaleMax" : 3,
"earlyGrowthLoot" : {
"tickets" : [
]
},
"maxGrowthLoot" : {
"tickets" : [
]
}
}
}
],
"files" : []
}

View File

@ -1735,6 +1735,7 @@ Remove old data classes
Update default block cursor size
Creature template -> object template
Fix foliage saving seed to template
Scaffolding growing component

View File

@ -21,6 +21,7 @@ import electrosphere.data.creature.equip.ToolbarData;
import electrosphere.data.creature.movement.MovementSystem;
import electrosphere.data.creature.rotator.RotatorSystem;
import electrosphere.data.foliage.AmbientAudio;
import electrosphere.data.foliage.GrowthData;
import electrosphere.data.foliage.GrowthModel;
import electrosphere.data.furniture.FurnitureData;
import electrosphere.data.graphics.GraphicsTemplate;
@ -162,6 +163,11 @@ public class CommonEntityType {
*/
FurnitureData furnitureData;
/**
* The growth data
*/
GrowthData growthData;
/**
* Gets the id for this creature type
* @return The id
@ -418,5 +424,13 @@ public class CommonEntityType {
return furnitureData;
}
/**
* Gets the growth data for the entity
* @return The growth data
*/
public GrowthData getGrowthData(){
return growthData;
}
}

View File

@ -0,0 +1,62 @@
package electrosphere.data.foliage;
import electrosphere.data.common.life.loot.LootPool;
/**
* Data that controls the growth characteristics of an entity that grows into something
*/
public class GrowthData {
/**
* The maximum value to grow to
*/
Integer growthMax;
/**
* The scale to be at when the entity finishes growing
*/
Double scaleMax;
/**
* The loot pool for when the entity completes growing
*/
LootPool maxGrowthLoot;
/**
* The loot pool for when the entity has not completed growing
*/
LootPool earlyGrowthLoot;
/**
* Gets the maximum value to grow to
* @return The maximum value to grow to
*/
public Integer getGrowthMax() {
return growthMax;
}
/**
* Gets the loot pool to drop on finishing growing
* @return The loot pool
*/
public LootPool getMaxGrowthLoot() {
return maxGrowthLoot;
}
/**
* Gets the loot pool to drop when death/harvest before max growth
* @return The loot pool
*/
public LootPool getEarlyGrowthLoot() {
return earlyGrowthLoot;
}
/**
* Gets the scale for when the entity finishes growing
* @return The scale
*/
public Double getScaleMax() {
return scaleMax;
}
}

View File

@ -81,5 +81,13 @@ public class ClientEntityUtils {
}
}
/**
* Sets the scale of the entity
* @param entity The entity
* @param scale The scale
*/
public static void setScale(Entity entity, Vector3d scale){
EntityUtils.getScale(entity).set(scale);
}
}

View File

@ -362,6 +362,12 @@ public class EntityDataStrings {
public static final String TREE_SERVERDOOR = "treeServerDoor";
public static final String TREE_CLIENTDOOR = "treeClientDoor";
/**
* Growth
*/
public static final String TREE_SERVERGROWTH = "treeServerGrowth";
public static final String TREE_CLIENTGROWTH = "treeClientGrowth";
/*
Entity categories
*/

View File

@ -194,4 +194,13 @@ public class ServerEntityUtils {
return realm.getDataCellManager().guaranteePositionIsInBounds(position);
}
/**
* Sets the scale of the entity
* @param entity The entity
* @param scale The scale to set to
*/
public static void setScale(Entity entity, Vector3d scale){
EntityUtils.getScale(entity).set(scale);
}
}

View File

@ -0,0 +1,128 @@
package electrosphere.entity.state.growth;
import org.joml.Vector3d;
import electrosphere.data.foliage.GrowthData;
import electrosphere.engine.Globals;
import electrosphere.entity.EntityDataStrings;
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
/**
* Tree for doing the inbetween work to grow an entity into a new entity
*/
@SynchronizedBehaviorTree(name = "clientGrowth", isServer = false, correspondingTree="serverGrowth")
public class ClientGrowthComponent implements BehaviorTree {
/**
* The current growth amount
*/
@SyncedField
private int status;
/**
* The parent entity
*/
Entity parent;
/**
* The data
*/
GrowthData data;
/**
* Creates an idle tree
* @param e the entity to attach the tree to
*/
private ClientGrowthComponent(Entity e, Object ... params){
parent = e;
this.data = (GrowthData)params[0];
}
@Override
public void simulate(float deltaTime){
float percentage = this.status / (float)data.getGrowthMax();
Vector3d targetScale = new Vector3d(data.getScaleMax() * percentage);
ClientEntityUtils.setScale(parent, targetScale);
}
/**
* <p> (initially) Automatically generated </p>
* <p>
* Attaches this tree to the entity.
* </p>
* @param entity The entity to attach to
* @param tree The behavior tree to attach
* @param params Optional parameters that will be provided to the constructor
*/
public static ClientGrowthComponent attachTree(Entity parent, Object ... params){
ClientGrowthComponent rVal = new ClientGrowthComponent(parent,params);
//!!WARNING!! from here below should not be touched
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
parent.putData(EntityDataStrings.TREE_CLIENTGROWTH, rVal);
Globals.clientSceneWrapper.getScene().registerBehaviorTree(rVal);
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_CLIENTGROWTH_ID);
return rVal;
}
/**
* <p> Automatically generated </p>
* <p>
* Detatches this tree from the entity.
* </p>
* @param entity The entity to detach to
* @param tree The behavior tree to detach
*/
public static void detachTree(Entity entity, BehaviorTree tree){
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_CLIENTGROWTH_ID);
}
/**
* <p>
* Gets the ClientGrowthComponent of the entity
* </p>
* @param entity the entity
* @return The ClientGrowthComponent
*/
public static ClientGrowthComponent getClientGrowthComponent(Entity entity){
return (ClientGrowthComponent)entity.getData(EntityDataStrings.TREE_CLIENTGROWTH);
}
/**
* <p>
* Checks if the entity has a ClientGrowthComponent component
* </p>
* @param entity the entity
* @return true if the entity contains the component, false otherwise
*/
public static boolean hasClientGrowthComponent(Entity entity){
return entity.containsKey(EntityDataStrings.TREE_CLIENTGROWTH);
}
/**
* <p> Automatically generated </p>
* <p>
* Sets status and handles the synchronization logic for it.
* </p>
* @param status The value to set status to.
*/
public void setStatus(int status){
this.status = status;
}
/**
* <p> Automatically generated </p>
* <p>
* Gets status.
* </p>
*/
public int getStatus(){
return status;
}
}

View File

@ -0,0 +1,139 @@
package electrosphere.entity.state.growth;
import org.joml.Vector3d;
import electrosphere.data.foliage.GrowthData;
import electrosphere.engine.Globals;
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.SynchronizationMessage;
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
/**
* Tree for playing an idle animation when an entity isn't doing anything
*/
@SynchronizedBehaviorTree(name = "serverGrowth", isServer = true, correspondingTree = "clientGrowth")
public class ServerGrowthComponent implements BehaviorTree {
/**
* The current growth amount
*/
@SyncedField
private int status;
/**
* The parent entity
*/
Entity parent;
/**
* The data
*/
GrowthData data;
/**
* Creates a server idle tree
* @param e The entity to attach it to
*/
public ServerGrowthComponent(Entity e, Object ... params){
parent = e;
this.data = (GrowthData)params[0];
}
@Override
public void simulate(float deltaTime){
if(status < data.getGrowthMax()){
this.setStatus(status + 1);
}
float percentage = this.status / (float)data.getGrowthMax();
Vector3d targetScale = new Vector3d(data.getScaleMax() * percentage);
ServerEntityUtils.setScale(parent, targetScale);
}
/**
* <p> (initially) Automatically generated </p>
* <p>
* Attaches this tree to the entity.
* </p>
* @param entity The entity to attach to
* @param tree The behavior tree to attach
* @param params Optional parameters that will be provided to the constructor
*/
public static ServerGrowthComponent attachTree(Entity parent, Object ... params){
ServerGrowthComponent rVal = new ServerGrowthComponent(parent,params);
//!!WARNING!! from here below should not be touched
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
ServerBehaviorTreeUtils.attachBTreeToEntity(parent, rVal);
parent.putData(EntityDataStrings.TREE_SERVERGROWTH, rVal);
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_SERVERGROWTH_ID);
return rVal;
}
/**
* <p> Automatically generated </p>
* <p>
* Detatches this tree from the entity.
* </p>
* @param entity The entity to detach to
* @param tree The behavior tree to detach
*/
public static void detachTree(Entity entity, BehaviorTree tree){
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_SERVERGROWTH_ID);
}
/**
* <p>
* Gets the ServerGrowthComponent of the entity
* </p>
* @param entity the entity
* @return The ServerGrowthComponent
*/
public static ServerGrowthComponent getServerGrowthComponent(Entity entity){
return (ServerGrowthComponent)entity.getData(EntityDataStrings.TREE_SERVERGROWTH);
}
/**
* <p>
* Checks if the entity has a ServerGrowthComponent component
* </p>
* @param entity the entity
* @return true if the entity contains the component, false otherwise
*/
public static boolean hasServerGrowthComponent(Entity entity){
return entity.containsKey(EntityDataStrings.TREE_SERVERGROWTH);
}
/**
* <p> Automatically generated </p>
* <p>
* Sets status and handles the synchronization logic for it.
* </p>
* @param status The value to set status to.
*/
public void setStatus(int status){
this.status = status;
if(DataCellSearchUtils.getEntityDataCell(parent) != null){
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientIntStateMessage(parent.getId(), BehaviorTreeIdEnums.BTREE_SERVERGROWTH_ID, FieldIdEnums.TREE_SERVERGROWTH_SYNCEDFIELD_STATUS_ID, status));
}
}
/**
* <p> Automatically generated </p>
* <p>
* Gets status.
* </p>
*/
public int getStatus(){
return status;
}
}

View File

@ -52,6 +52,8 @@ import electrosphere.entity.state.furniture.ClientDoorState;
import electrosphere.entity.state.furniture.ServerDoorState;
import electrosphere.entity.state.gravity.ClientGravityTree;
import electrosphere.entity.state.gravity.ServerGravityTree;
import electrosphere.entity.state.growth.ClientGrowthComponent;
import electrosphere.entity.state.growth.ServerGrowthComponent;
import electrosphere.entity.state.hitbox.HitboxCollectionState;
import electrosphere.entity.state.idle.ClientIdleTree;
import electrosphere.entity.state.idle.ServerIdleTree;
@ -346,6 +348,9 @@ public class CommonEntityUtils {
if(rawType.getBlockSystem() != null){
ClientBlockTree.attachTree(entity, rawType.getBlockSystem());
}
if(rawType.getGrowthData() != null){
ClientGrowthComponent.attachTree(entity, rawType.getGrowthData());
}
if(rawType.getTokens() != null){
for(String token : rawType.getTokens()){
switch(token){
@ -753,6 +758,10 @@ public class CommonEntityUtils {
}
}
if(rawType.getGrowthData() != null){
ServerGrowthComponent.attachTree(entity, rawType.getGrowthData());
}
///
///
/// AI (This SHOULD only be applied on the server with the way AI architected currently)

View File

@ -1,6 +1,7 @@
package electrosphere.net.synchronization.client;
import electrosphere.entity.state.growth.ClientGrowthComponent;
import electrosphere.entity.state.furniture.ClientDoorState;
import electrosphere.entity.state.item.ClientChargeState;
import electrosphere.entity.state.movement.editor.ClientEditorMovementTree;
@ -307,6 +308,16 @@ public class ClientSynchronizationManager {
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGROWTH_ID: {
switch(message.getfieldId()){
case FieldIdEnums.TREE_SERVERGROWTH_SYNCEDFIELD_STATUS_ID:{
ClientGrowthComponent tree = ClientGrowthComponent.getClientGrowthComponent(entity);
if(tree != null){
tree.setStatus(message.getintValue());
}
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID: {
switch(message.getfieldId()){
case FieldIdEnums.TREE_SERVERIDLE_SYNCEDFIELD_STATE_ID:{

View File

@ -17,6 +17,8 @@ public class BehaviorTreeIdEnums {
public static final int BTREE_SERVERDOOR_ID = 29;
public static final int BTREE_CLIENTGRAVITY_ID = 12;
public static final int BTREE_SERVERGRAVITY_ID = 7;
public static final int BTREE_CLIENTGROWTH_ID = 30;
public static final int BTREE_SERVERGROWTH_ID = 31;
public static final int BTREE_IDLE_ID = 8;
public static final int BTREE_SERVERIDLE_ID = 9;
public static final int BTREE_CLIENTCHARGESTATE_ID = 26;

View File

@ -21,6 +21,8 @@ public class FieldIdEnums {
public static final int TREE_SERVERDOOR_SYNCEDFIELD_STATE_ID = 37;
public static final int TREE_CLIENTGRAVITY_SYNCEDFIELD_STATE_ID = 16;
public static final int TREE_SERVERGRAVITY_SYNCEDFIELD_STATE_ID = 11;
public static final int TREE_CLIENTGROWTH_SYNCEDFIELD_STATUS_ID = 38;
public static final int TREE_SERVERGROWTH_SYNCEDFIELD_STATUS_ID = 39;
public static final int TREE_IDLE_SYNCEDFIELD_STATE_ID = 12;
public static final int TREE_SERVERIDLE_SYNCEDFIELD_STATE_ID = 13;
public static final int TREE_CLIENTCHARGESTATE_SYNCEDFIELD_CHARGES_ID = 34;

View File

@ -1,6 +1,8 @@
package electrosphere.net.synchronization.transport;
import electrosphere.entity.state.growth.ServerGrowthComponent;
import electrosphere.entity.state.growth.ClientGrowthComponent;
import electrosphere.entity.state.furniture.ServerDoorState;
import electrosphere.entity.state.furniture.ClientDoorState;
import electrosphere.entity.state.item.ServerChargeState;
@ -99,6 +101,10 @@ public class StateCollection {
ServerGravityTree tree = ServerGravityTree.getServerGravityTree(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVERGRAVITY_ID,FieldIdEnums.TREE_SERVERGRAVITY_SYNCEDFIELD_STATE_ID,ClientGravityTree.getGravityTreeStateEnumAsShort(tree.getState())));
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGROWTH_ID: {
ServerGrowthComponent tree = ServerGrowthComponent.getServerGrowthComponent(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVERGROWTH_ID,FieldIdEnums.TREE_SERVERGROWTH_SYNCEDFIELD_STATUS_ID,tree.getStatus()));
} break;
case BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID: {
ServerIdleTree tree = ServerIdleTree.getServerIdleTree(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID,FieldIdEnums.TREE_SERVERIDLE_SYNCEDFIELD_STATE_ID,ClientIdleTree.getIdleTreeStateEnumAsShort(tree.getState())));
@ -203,6 +209,14 @@ public class StateCollection {
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGROWTH_ID: {
ClientGrowthComponent tree = ClientGrowthComponent.getClientGrowthComponent(entity);
switch(syncedValue.getFieldId()){
case(FieldIdEnums.TREE_SERVERGROWTH_SYNCEDFIELD_STATUS_ID): {
tree.setStatus(((Double)syncedValue.getValue()).intValue());
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID: {
ClientIdleTree tree = ClientIdleTree.getClientIdleTree(entity);
switch(syncedValue.getFieldId()){
@ -346,6 +360,14 @@ public class StateCollection {
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERGROWTH_ID: {
ServerGrowthComponent tree = ServerGrowthComponent.getServerGrowthComponent(entity);
switch(syncedValue.getFieldId()){
case(FieldIdEnums.TREE_SERVERGROWTH_SYNCEDFIELD_STATUS_ID): {
tree.setStatus(((Double)syncedValue.getValue()).intValue());
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERIDLE_ID: {
ServerIdleTree tree = ServerIdleTree.getServerIdleTree(entity);
switch(syncedValue.getFieldId()){