optimization work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-03-29 20:23:17 -04:00
parent 5588827644
commit c630a184aa
19 changed files with 184 additions and 137 deletions

View File

@ -1383,6 +1383,7 @@ Network message object pooling
Threadsafe EntityDataCellMapper
Code cleanup
Small ServerAttackTree fix (for when not holding an item)
Work on optimization

View File

@ -32,9 +32,14 @@ public class ChunkData {
*/
public static final int CHUNK_DATA_SIZE = ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE;
//What type of terrain is in this voxel, eg stone vs dirt vs grass, etc
/**
* What type of terrain is in this voxel, eg stone vs dirt vs grass, etc
*/
int[][][] voxelType;
//How much of that terrain type is in this voxel
/**
* How much of that terrain type is in this voxel
*/
float[][][] voxelWeight;
//the list of positions modified since the last call to resetModifiedPositions

View File

@ -112,7 +112,6 @@ public class ClientTerrainManager {
public void handleMessages(){
Globals.profiler.beginCpuSample("ClientTerrainManager.handleMessages");
lock.acquireUninterruptibly();
List<TerrainMessage> bouncedMessages = new LinkedList<TerrainMessage>();
for(TerrainMessage message : messageQueue){
switch(message.getMessageSubtype()){
case SENDCHUNKDATA: {
@ -216,11 +215,9 @@ public class ClientTerrainManager {
LoggerInterface.loggerEngine.WARNING("ClientTerrainManager: unhandled network message of type" + message.getMessageSubtype());
break;
}
Globals.clientConnection.release(message);
}
messageQueue.clear();
for(TerrainMessage message : bouncedMessages){
messageQueue.add(message);
}
//evaluate if any terrain chunks have failed to request
for(Long key : this.requestedMap.keySet()){
int duration = this.requestedMap.get(key);

View File

@ -4,8 +4,8 @@ import electrosphere.entity.Entity;
import electrosphere.entity.state.collidable.Impulse;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@ -22,7 +22,7 @@ public class Collidable {
boolean parentTracksCollidable = true;
//The impulses to be applied to this collidable
List<Impulse> impulses = new CopyOnWriteArrayList<Impulse>();
List<Impulse> impulses = new LinkedList<Impulse>();
/**
* The params for the surface of this collidable when a collision occurs

View File

@ -47,10 +47,10 @@ public class EntityUtils {
if(dataCell != null){
dataCell.getScene().deregisterEntity(e);
}
Globals.entityDataCellMapper.ejectEntity(e);
}
Globals.realmManager.removeEntity(e);
}
Globals.entityDataCellMapper.ejectEntity(e);
EntityLookupUtils.removeEntity(e);
}

View File

@ -6,15 +6,17 @@ import electrosphere.entity.EntityTags;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.attach.AttachUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.util.annotation.Exclude;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReentrantLock;
/**
* A game scene
@ -35,33 +37,39 @@ public class Scene {
* The list of behavior trees
*/
List<BehaviorTree> behaviorTreeList;
@Exclude
/**
* Lock for threadsafeing the scene
*/
ReentrantLock lock = new ReentrantLock();
/**
* Constructor
*/
public Scene(){
entityIdMap = new ConcurrentHashMap<Integer,Entity>();
tagEntityMap = new ConcurrentHashMap<String,Set<Entity>>();
behaviorTreeList = new CopyOnWriteArrayList<BehaviorTree>();
tagEntityMap.put(EntityTags.BONE_ATTACHED, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.COLLIDABLE, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.SPRINTABLE, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.MOVEABLE, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.ATTACKER, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.TARGETABLE, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.LIFE_STATE, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.CREATURE, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.UI, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.DRAWABLE, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.DRAW_INSTANCED, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.DRAW_VOLUMETIC_SOLIDS_PASS, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.DRAW_VOLUMETIC_DEPTH_PASS, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.DRAW_CAST_SHADOW, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.LIGHT, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.ITEM, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.GRAVITY, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.PARTICLE, new CopyOnWriteArraySet<Entity>());
tagEntityMap.put(EntityTags.TRANSFORM_ATTACHED, new CopyOnWriteArraySet<Entity>());
entityIdMap = new HashMap<Integer,Entity>();
tagEntityMap = new HashMap<String,Set<Entity>>();
behaviorTreeList = new LinkedList<BehaviorTree>();
tagEntityMap.put(EntityTags.BONE_ATTACHED, new HashSet<Entity>());
tagEntityMap.put(EntityTags.COLLIDABLE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.SPRINTABLE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.MOVEABLE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.ATTACKER, new HashSet<Entity>());
tagEntityMap.put(EntityTags.TARGETABLE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.LIFE_STATE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.CREATURE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.UI, new HashSet<Entity>());
tagEntityMap.put(EntityTags.DRAWABLE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.DRAW_INSTANCED, new HashSet<Entity>());
tagEntityMap.put(EntityTags.DRAW_VOLUMETIC_SOLIDS_PASS, new HashSet<Entity>());
tagEntityMap.put(EntityTags.DRAW_VOLUMETIC_DEPTH_PASS, new HashSet<Entity>());
tagEntityMap.put(EntityTags.DRAW_CAST_SHADOW, new HashSet<Entity>());
tagEntityMap.put(EntityTags.LIGHT, new HashSet<Entity>());
tagEntityMap.put(EntityTags.ITEM, new HashSet<Entity>());
tagEntityMap.put(EntityTags.GRAVITY, new HashSet<Entity>());
tagEntityMap.put(EntityTags.PARTICLE, new HashSet<Entity>());
tagEntityMap.put(EntityTags.TRANSFORM_ATTACHED, new HashSet<Entity>());
}
/**
@ -69,7 +77,9 @@ public class Scene {
* @param e The entity to register
*/
public void registerEntity(Entity e){
lock.lock();
entityIdMap.put(e.getId(), e);
lock.unlock();
}
/**
@ -78,13 +88,15 @@ public class Scene {
* @param tag The tag
*/
public void registerEntityToTag(Entity e, String tag){
lock.lock();
if(tagEntityMap.containsKey(tag)){
tagEntityMap.get(tag).add(e);
} else {
Set<Entity> newEntityList = new CopyOnWriteArraySet<Entity>();
Set<Entity> newEntityList = new HashSet<Entity>();
newEntityList.add(e);
tagEntityMap.put(tag,newEntityList);
}
lock.unlock();
}
/**
@ -93,7 +105,13 @@ public class Scene {
* @return A list of all entities with the tag, or null if no entities have been added to the tag yet
*/
public Set<Entity> getEntitiesWithTag(String tag){
return tagEntityMap.get(tag);
lock.lock();
Set<Entity> rVal = null;
if(tagEntityMap.containsKey(tag)){
rVal = new HashSet<Entity>(tagEntityMap.get(tag));
}
lock.unlock();
return rVal;
}
/**
@ -102,7 +120,9 @@ public class Scene {
* @param tag The tag
*/
public void removeEntityFromTag(Entity e, String tag){
lock.lock();
tagEntityMap.get(tag).remove(e);
lock.unlock();
}
/**
@ -110,10 +130,12 @@ public class Scene {
* @param e
*/
public void deregisterEntity(Entity e){
lock.lock();
for(String key : tagEntityMap.keySet()){
tagEntityMap.get(key).remove(e);
}
entityIdMap.remove(e.getId());
lock.unlock();
}
/**
@ -121,6 +143,7 @@ public class Scene {
* @param target The top level entity to deregister
*/
public void recursiveDeregister(Entity target){
lock.lock();
if(AttachUtils.hasChildren(target)){
List<Entity> childrenList = AttachUtils.getChildrenList(target);
for(Entity currentChild : childrenList){
@ -128,6 +151,7 @@ public class Scene {
}
}
this.deregisterEntity(target);
lock.unlock();
}
/**
@ -136,7 +160,10 @@ public class Scene {
* @return The entity with that ID
*/
public Entity getEntityFromId(int id){
return (Entity)entityIdMap.get(id);
lock.lock();
Entity rVal = (Entity)entityIdMap.get(id);
lock.unlock();
return rVal;
}
/**
@ -145,7 +172,10 @@ public class Scene {
* @return true if the scene contains the entity, false otherwise
*/
public boolean containsEntity(Entity e){
return entityIdMap.containsKey(e.getId());
lock.lock();
boolean rVal = entityIdMap.containsKey(e.getId());
lock.unlock();
return rVal;
}
/**
@ -153,7 +183,9 @@ public class Scene {
* @param tree The behavior tree to register
*/
public void registerBehaviorTree(BehaviorTree tree){
lock.lock();
behaviorTreeList.add(tree);
lock.unlock();
}
/**
@ -161,9 +193,11 @@ public class Scene {
* @param task The task
*/
public void registerBehaviorTree(Runnable task){
lock.lock();
this.registerBehaviorTree(new BehaviorTree(){public void simulate(float deltaTime) {
task.run();
}});
lock.unlock();
}
/**
@ -171,20 +205,25 @@ public class Scene {
* @param tree The behavior tree to deregister
*/
public void deregisterBehaviorTree(BehaviorTree tree){
lock.lock();
while(behaviorTreeList.contains(tree)){
behaviorTreeList.remove(tree);
}
lock.unlock();
}
/**
* Simulates all behavior trees stored in the entity manager
*/
public void simulateBehaviorTrees(float deltaTime){
lock.lock();
Globals.profiler.beginAggregateCpuSample("Scene.simulateBehaviorTrees");
for(BehaviorTree tree : behaviorTreeList){
List<BehaviorTree> trees = new LinkedList<BehaviorTree>(behaviorTreeList);
for(BehaviorTree tree : trees){
tree.simulate(deltaTime);
}
Globals.profiler.endCpuSample();
lock.unlock();
}
/**
@ -192,7 +231,10 @@ public class Scene {
* @return The collection of all entities in the scene
*/
public Collection<Entity> getEntityList(){
return this.entityIdMap.values();
lock.lock();
Collection<Entity> rVal = new LinkedList<Entity>(this.entityIdMap.values());
lock.unlock();
return rVal;
}
/**
@ -200,7 +242,10 @@ public class Scene {
* @return The list of behavior trees attached to the scene
*/
public Collection<BehaviorTree> getBehaviorTrees(){
return Collections.unmodifiableList(this.behaviorTreeList);
lock.lock();
Collection<BehaviorTree> rVal = new LinkedList<BehaviorTree>(this.behaviorTreeList);
lock.unlock();
return rVal;
}
/**

View File

@ -41,7 +41,6 @@ import electrosphere.server.datacell.Realm;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Quaterniond;
import org.joml.Vector3d;
@ -63,7 +62,7 @@ public class ServerAttackTree implements BehaviorTree {
Entity parent;
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
List<EntityMessage> networkMessageQueue = new LinkedList<EntityMessage>();
long lastUpdateTime = 0;
@ -370,10 +369,12 @@ public class ServerAttackTree implements BehaviorTree {
this.stateTransitionUtil.simulate(AttackTreeState.ATTACK);
//activate hitboxes
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
for(Entity currentAttached : attachedEntities){
if(HitboxCollectionState.hasHitboxState(currentAttached)){
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
currentState.setActive(true);
if(attachedEntities != null){
for(Entity currentAttached : attachedEntities){
if(HitboxCollectionState.hasHitboxState(currentAttached)){
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
currentState.setActive(true);
}
}
}
if(firesProjectile && projectileToFire != null){

View File

@ -23,7 +23,8 @@ import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
import electrosphere.server.poseactor.PoseActor;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.LinkedList;
import java.util.List;
@SynchronizedBehaviorTree(name = "serverIdle", isServer = true, correspondingTree = "idle")
@ -40,7 +41,7 @@ public class ServerIdleTree implements BehaviorTree {
//The idle data
IdleData idleData;
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
List<EntityMessage> networkMessageQueue = new LinkedList<EntityMessage>();
/**
* Creates a server idle tree

View File

@ -1,6 +1,7 @@
package electrosphere.entity.state.inventory;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.LinkedList;
import java.util.List;
import electrosphere.entity.Entity;
import electrosphere.entity.btree.BehaviorTree;
@ -19,7 +20,7 @@ public class ServerInventoryState implements BehaviorTree {
/**
* The queue of messages to handle
*/
CopyOnWriteArrayList<InventoryMessage> networkMessageQueue = new CopyOnWriteArrayList<InventoryMessage>();
List<InventoryMessage> networkMessageQueue = new LinkedList<InventoryMessage>();
/**
* The parent of the state

View File

@ -31,7 +31,8 @@ import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.server.utils.ServerScriptUtils;
import electrosphere.util.math.SpatialMathUtils;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.LinkedList;
import java.util.List;
import org.joml.Quaterniond;
import org.joml.Vector3d;
@ -63,7 +64,7 @@ public class ServerEditorMovementTree implements BehaviorTree {
Entity parent;
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
List<EntityMessage> networkMessageQueue = new LinkedList<EntityMessage>();
long lastUpdateTime = 0;

View File

@ -35,7 +35,8 @@ import electrosphere.server.poseactor.PoseActor;
import electrosphere.server.utils.ServerScriptUtils;
import electrosphere.util.math.SpatialMathUtils;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.LinkedList;
import java.util.List;
import org.joml.Quaterniond;
import org.joml.Vector3d;
@ -71,7 +72,7 @@ public class ServerGroundMovementTree implements BehaviorTree {
Collidable collidable;
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
List<EntityMessage> networkMessageQueue = new LinkedList<EntityMessage>();
long lastUpdateTime = 0;

View File

@ -1,7 +1,7 @@
package electrosphere.net.parser.net.raw;
import electrosphere.net.parser.net.message.MessagePool;
import electrosphere.net.parser.net.message.NetworkMessage;
package electrosphere.net.parser.net.raw;
import electrosphere.net.parser.net.message.MessagePool;
import electrosphere.net.parser.net.message.NetworkMessage;
import io.github.studiorailgun.CircularByteBuffer;
import java.io.IOException;
import java.io.InputStream;
@ -68,6 +68,12 @@ public class NetworkParser {
* The number of bytes read
*/
long totalBytesRead = 0;
/**
* If set to true, the parser will automatically release messages on send.
* Otherwise, will not release when the message is sent.
*/
boolean releaseOnSend = true;
/**
@ -110,7 +116,9 @@ public class NetworkParser {
for(NetworkMessage message : outgoingMessageQueue){
outgoingMessageQueue.remove(message);
outgoingStream.write(message.getRawBytes());
this.pool.release(message);
if(this.releaseOnSend){
this.pool.release(message);
}
}
}
@ -177,5 +185,14 @@ public class NetworkParser {
public MessagePool getMessagePool(){
return this.pool;
}
/**
* If set to true, the parser will automatically release messages on send.
* Otherwise, will not release when the message is sent.
* @param releaseOnSend true to release messages on send, false otherwise
*/
public void setReleaseOnSend(boolean releaseOnSend){
this.releaseOnSend = releaseOnSend;
}
}

View File

@ -129,6 +129,7 @@ public class ServerConnectionHandler implements Runnable {
if(this.local){
//run if serverconnectionHandler is created by passing in input/output streams
networkParser = new NetworkParser(inputStream,outputStream);
networkParser.setReleaseOnSend(false);
messageProtocol = new MessageProtocol(this);
} else {
//run if ServerConnectionHandler is created by passing in a socket

View File

@ -7,7 +7,6 @@ import electrosphere.logger.LoggerInterface;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import electrosphere.entity.Entity;
import electrosphere.entity.state.movement.jump.ServerJumpTree;
@ -33,7 +32,7 @@ public class ServerSynchronizationManager {
//The list of messages to loop through
List<SynchronizationMessage> messages = new CopyOnWriteArrayList<SynchronizationMessage>();
List<SynchronizationMessage> messages = new LinkedList<SynchronizationMessage>();
/**
* Pushes a message into the queue to be processed

View File

@ -1,9 +1,9 @@
package electrosphere.server.datacell;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReentrantLock;
import org.joml.Vector3d;
@ -26,11 +26,19 @@ import electrosphere.server.fluid.simulator.FluidAcceleratedSimulator;
*/
public class RealmManager {
//All realms in this manager
Set<Realm> realms = new CopyOnWriteArraySet<Realm>();
//Map of entities to the realm the entity is in
/**
* All realms in this manager
*/
Set<Realm> realms = new HashSet<Realm>();
/**
* Map of entities to the realm the entity is in
*/
Map<Entity,Realm> entityToRealmMap = new HashMap<Entity,Realm>();
//Map of player to the realm the player is in
/**
* Map of player to the realm the player is in
*/
Map<Player,Realm> playerToRealmMap = new HashMap<Player,Realm>();
/**
@ -165,7 +173,10 @@ public class RealmManager {
* @return The set containing all realms in the manager
*/
public Set<Realm> getRealms(){
return realms;
lock.lock();
Set<Realm> rVal = new HashSet<Realm>(realms);
lock.unlock();
return rVal;
}
@ -174,6 +185,7 @@ public class RealmManager {
*/
public void simulate(){
Globals.profiler.beginCpuSample("RealmManager.simulate");
Set<Realm> realms = this.getRealms();
for(Realm realm : realms){
realm.simulate();
}
@ -209,6 +221,7 @@ public class RealmManager {
* @param saveName The name of the save
*/
public void save(String saveName){
Set<Realm> realms = this.getRealms();
for(Realm realm : realms){
realm.save(saveName);
}

View File

@ -52,8 +52,10 @@ public class GriddedDataCellLoaderService {
//let the service know we've finished this job
lock.lock();
queuedWorkLock.remove(key);
jobOperationMap.remove(key);
lock.unlock();
};
jobOperationMap.put(key,operation);
if(job != null){
if(!job.cancel(false)){
try {
@ -69,80 +71,24 @@ public class GriddedDataCellLoaderService {
if(job.isCancelled()){
Runnable oldOp = jobOperationMap.remove(key);
//queue job to run the old operation first, then the new one
opCallback = () -> {
Runnable currentOp = () -> {
oldOp.run();
//load here
operation.run();
};
opCallback = () -> {
currentOp.run();
//let the service know we've finished this job
lock.lock();
queuedWorkLock.remove(key);
jobOperationMap.remove(key);
lock.unlock();
};
jobOperationMap.put(key,currentOp);
}
}
//queue job to do the operation
Future<?> newJob = ioThreadService.submit(opCallback);
queuedWorkLock.put(key, newJob);
jobOperationMap.put(key,operation);
lock.unlock();
}
/**
* Loads a cell
* @param key The key for the cell
*/
protected static void loadCell(long key, Runnable loadLogic){
lock.lock();
//if there is a job queued and we couldn't cancel it, wait
Future<?> job = queuedWorkLock.get(key);
if(job != null && !job.cancel(false)){
try {
Globals.profiler.beginCpuSample("Waiting for cell io job to finish");
job.wait();
Globals.profiler.endCpuSample();
} catch (InterruptedException e) {
LoggerInterface.loggerEngine.ERROR("Failed to wait for previous job for cell!", e);
}
}
//queue job to load the cell
Future<?> newJob = ioThreadService.submit(() -> {
//load here
loadLogic.run();
//let the service know we've finished this job
lock.lock();
queuedWorkLock.remove(key);
lock.unlock();
});
queuedWorkLock.put(key, newJob);
lock.unlock();
}
/**
* Unloads a cell
* @param key The key for the cell
*/
protected static void unloadCell(long key, Runnable unloadLogic){
lock.lock();
//if there is a job queued and we couldn't cancel it, wait
Future<?> job = queuedWorkLock.get(key);
if(job != null && !job.cancel(false)){
try {
Globals.profiler.beginCpuSample("Waiting for cell io job to finish");
job.wait();
Globals.profiler.endCpuSample();
} catch (InterruptedException e) {
LoggerInterface.loggerEngine.ERROR("Failed to wait for previous job for cell!", e);
}
}
//queue job to load the cell
ioThreadService.submit(() -> {
//unload here
unloadLogic.run();
//let the service know we've finished this job
lock.lock();
queuedWorkLock.remove(key);
lock.unlock();
});
lock.unlock();
}

View File

@ -296,10 +296,12 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
*/
private void createTerrainPhysicsEntities(Vector3i worldPos){
Long key = this.getServerDataCellKey(worldPos);
loadedCellsLock.lock();
if(posPhysicsMap.containsKey(key)){
PhysicsDataCell cell = posPhysicsMap.get(key);
cell.retireCell();
}
loadedCellsLock.unlock();
//get data to generate with
Vector3d realPos = new Vector3d(
worldPos.x * ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET,
@ -325,7 +327,9 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
cell.setTerrainChunk(terrainChunk);
cell.setBlockChunk(blockChunkData);
cell.generatePhysics();
loadedCellsLock.lock();
posPhysicsMap.put(key, cell);
loadedCellsLock.unlock();
}
/**
@ -742,8 +746,10 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
serverContentManager.generateContentForDataCell(parent, worldPos, rVal, cellKey);
});
//generates physics for the cell in a dedicated thread then finally registers
loadedCellsLock.lock();
PhysicsDataCell cell = posPhysicsMap.get(key);
GriddedDataCellManager.runPhysicsGenerationThread(worldPos,key,cell,this.posPhysicsMap,this.groundDataCells,this.parent);
loadedCellsLock.unlock();
Globals.profiler.endCpuSample();

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import electrosphere.entity.Entity;
import electrosphere.entity.btree.BehaviorTree;
@ -17,14 +18,24 @@ import electrosphere.server.datacell.ServerDataCell;
*/
public class ServerBehaviorTreeUtils {
/**
* The map of entity to set of behavior trees attached to it
*/
static Map<Entity,Set<BehaviorTree>> entityBTreeMap = new HashMap<Entity,Set<BehaviorTree>>();
/**
* Lock for thread-safeing the util
*/
static ReentrantLock lock = new ReentrantLock();
/**
* Tracks behavior trees attached to this entity
* @param entity
*/
public static void registerEntity(Entity entity){
lock.lock();
entityBTreeMap.put(entity, new HashSet<BehaviorTree>());
lock.unlock();
}
/**
@ -32,6 +43,7 @@ public class ServerBehaviorTreeUtils {
* @param entity
*/
public static void deregisterEntity(Entity entity){
lock.lock();
Set<BehaviorTree> trees = entityBTreeMap.remove(entity);
ServerDataCell currentCell = DataCellSearchUtils.getEntityDataCell(entity);
if(trees != null){
@ -39,6 +51,7 @@ public class ServerBehaviorTreeUtils {
currentCell.getScene().deregisterBehaviorTree(tree);
}
}
lock.unlock();
}
/**
@ -47,10 +60,12 @@ public class ServerBehaviorTreeUtils {
* @param behaviorTree The behavior tree
*/
public static void attachBTreeToEntity(Entity entity, BehaviorTree behaviorTree){
lock.lock();
entityBTreeMap.get(entity).add(behaviorTree);
//register to cell
ServerDataCell currentCell = DataCellSearchUtils.getEntityDataCell(entity);
currentCell.getScene().registerBehaviorTree(behaviorTree);
lock.unlock();
}
/**
@ -59,10 +74,12 @@ public class ServerBehaviorTreeUtils {
* @param behaviorTree The behavior tree
*/
public static void detatchBTreeFromEntity(Entity entity, BehaviorTree behaviorTree){
lock.lock();
entityBTreeMap.get(entity).remove(behaviorTree);
//deregister from cell
ServerDataCell currentCell = DataCellSearchUtils.getEntityDataCell(entity);
currentCell.getScene().deregisterBehaviorTree(behaviorTree);
lock.unlock();
}
@ -72,6 +89,7 @@ public class ServerBehaviorTreeUtils {
* @param oldCell The cell the entity used to inhabit
*/
public static void updateCell(Entity entity, ServerDataCell oldCell){
lock.lock();
Set<BehaviorTree> trees = entityBTreeMap.get(entity);
ServerDataCell newCell = DataCellSearchUtils.getEntityDataCell(entity);
if(trees != null){
@ -82,6 +100,7 @@ public class ServerBehaviorTreeUtils {
newCell.getScene().registerBehaviorTree(tree);
}
}
lock.unlock();
}
}

View File

@ -1,9 +1,5 @@
package electrosphere.server.saves;
import java.util.List;
import electrosphere.entity.scene.Scene;
/**
* Top level save object that stores information about the save
*/
@ -24,9 +20,6 @@ public class Save {
//The name of the save
String name;
//The scenes
List<Scene> scenes;
/**
* Constructor
*/