grid manager entity and player tracking overhaul
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
e12dd55703
commit
795fbb6a1c
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"gameplayGenerateWorld" : false,
|
"gameplayGenerateWorld" : false,
|
||||||
"gameplayPhysicsCellRadius" : 2,
|
"gameplayPhysicsCellRadius" : 3,
|
||||||
|
|
||||||
"displayWidth" : 1920,
|
"displayWidth" : 1920,
|
||||||
"displayHeight" : 1080,
|
"displayHeight" : 1080,
|
||||||
|
|||||||
@ -9,3 +9,8 @@ sines pulling from sines
|
|||||||
noise functions pulling from sines
|
noise functions pulling from sines
|
||||||
applying 2d values to the surface (top) of a 3d noise map
|
applying 2d values to the surface (top) of a 3d noise map
|
||||||
subtracting true 3d noise from a 2d heightmap to account for cave entrances
|
subtracting true 3d noise from a 2d heightmap to account for cave entrances
|
||||||
|
|
||||||
|
|
||||||
|
spatially partitioning 3d shapes using the same trick as the voronoi noise but in 3d
|
||||||
|
IE, have a torus defined in 3d that is bounded in cells
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
package electrosphere.client.ui.menu.debug;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||||
|
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
||||||
|
import electrosphere.server.datacell.GriddedDataCellManager;
|
||||||
|
import electrosphere.server.datacell.Realm;
|
||||||
|
import imgui.ImGui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ImGuiGriddedManager {
|
||||||
|
|
||||||
|
//window for viewing information about the ai state
|
||||||
|
protected static ImGuiWindow griddedManagerWindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the windows in this file
|
||||||
|
*/
|
||||||
|
protected static void createGriddedManagerWindows(){
|
||||||
|
createGriddedManagerWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client scene entity view
|
||||||
|
*/
|
||||||
|
protected static void createGriddedManagerWindow(){
|
||||||
|
griddedManagerWindow = new ImGuiWindow("Gridded Manager");
|
||||||
|
griddedManagerWindow.setCallback(new ImGuiWindowCallback() {
|
||||||
|
@Override
|
||||||
|
public void exec() {
|
||||||
|
GriddedDataCellManager manager = null;
|
||||||
|
if(Globals.realmManager != null && Globals.realmManager.first() != null){
|
||||||
|
Realm realm = Globals.realmManager.first();
|
||||||
|
if(realm.getDataCellManager() instanceof GriddedDataCellManager){
|
||||||
|
manager = (GriddedDataCellManager)realm.getDataCellManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(manager != null && manager.getLoadedCells() != null){
|
||||||
|
ImGui.text("Loaded Cells: " + manager.getLoadedCells().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
griddedManagerWindow.setOpen(false);
|
||||||
|
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(griddedManagerWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -52,6 +52,7 @@ public class ImGuiWindowMacros {
|
|||||||
ImGuiRenderer.createRendererWindows();
|
ImGuiRenderer.createRendererWindows();
|
||||||
ImGuiTestGen.createTestGenWindows();
|
ImGuiTestGen.createTestGenWindows();
|
||||||
ImGuiChunkMonitor.createChunkMonitorWindows();
|
ImGuiChunkMonitor.createChunkMonitorWindows();
|
||||||
|
ImGuiGriddedManager.createGriddedManagerWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -188,6 +189,10 @@ public class ImGuiWindowMacros {
|
|||||||
if(ImGui.button("Chunk Monitor")){
|
if(ImGui.button("Chunk Monitor")){
|
||||||
ImGuiChunkMonitor.chunkMonitorWindow.setOpen(true);
|
ImGuiChunkMonitor.chunkMonitorWindow.setOpen(true);
|
||||||
}
|
}
|
||||||
|
//gridded data cell monitor
|
||||||
|
if(ImGui.button("Gridded Data Cell Monitor")){
|
||||||
|
ImGuiGriddedManager.griddedManagerWindow.setOpen(true);
|
||||||
|
}
|
||||||
//close button
|
//close button
|
||||||
if(ImGui.button("Close")){
|
if(ImGui.button("Close")){
|
||||||
mainDebugWindow.setOpen(false);
|
mainDebugWindow.setOpen(false);
|
||||||
|
|||||||
@ -50,10 +50,15 @@ public class EntityCreationUtils {
|
|||||||
throw new IllegalStateException("Failed to create a server data cell");
|
throw new IllegalStateException("Failed to create a server data cell");
|
||||||
}
|
}
|
||||||
//register to entity data cell mapper
|
//register to entity data cell mapper
|
||||||
realm.getEntityDataCellMapper().registerEntity(rVal, cell);
|
Globals.entityDataCellMapper.registerEntity(rVal, cell);
|
||||||
//enable behavior tree tracking
|
//enable behavior tree tracking
|
||||||
ServerBehaviorTreeUtils.registerEntity(rVal);
|
ServerBehaviorTreeUtils.registerEntity(rVal);
|
||||||
|
|
||||||
|
if(Globals.entityDataCellMapper.getEntityDataCell(rVal) == null){
|
||||||
|
Globals.entityDataCellMapper.registerEntity(rVal, cell);
|
||||||
|
throw new Error("Failed to map entity to cell!");
|
||||||
|
}
|
||||||
|
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,11 +43,11 @@ public class EntityUtils {
|
|||||||
Realm realm = Globals.realmManager.getEntityRealm(e);
|
Realm realm = Globals.realmManager.getEntityRealm(e);
|
||||||
if(realm != null){
|
if(realm != null){
|
||||||
//get data cell
|
//get data cell
|
||||||
ServerDataCell dataCell = realm.getEntityDataCellMapper().getEntityDataCell(e);
|
ServerDataCell dataCell = Globals.entityDataCellMapper.getEntityDataCell(e);
|
||||||
if(dataCell != null){
|
if(dataCell != null){
|
||||||
dataCell.getScene().deregisterEntity(e);
|
dataCell.getScene().deregisterEntity(e);
|
||||||
}
|
}
|
||||||
realm.getEntityDataCellMapper().ejectEntity(e);
|
Globals.entityDataCellMapper.ejectEntity(e);
|
||||||
}
|
}
|
||||||
Globals.realmManager.removeEntity(e);
|
Globals.realmManager.removeEntity(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,9 @@ public class ServerEntityUtils {
|
|||||||
* @param position
|
* @param position
|
||||||
*/
|
*/
|
||||||
public static void initiallyPositionEntity(Realm realm, Entity entity, Vector3d position){
|
public static void initiallyPositionEntity(Realm realm, Entity entity, Vector3d position){
|
||||||
|
if(position == null){
|
||||||
|
throw new Error("Trying to set server entity position to null!");
|
||||||
|
}
|
||||||
//reposition entity, if the position isn't correct then it will spawn at 0,0,0 when the synchronization part is called
|
//reposition entity, if the position isn't correct then it will spawn at 0,0,0 when the synchronization part is called
|
||||||
CollisionObjUtils.serverPositionCharacter(entity, position);
|
CollisionObjUtils.serverPositionCharacter(entity, position);
|
||||||
//get current server data cell
|
//get current server data cell
|
||||||
@ -43,6 +46,9 @@ public class ServerEntityUtils {
|
|||||||
} else {
|
} else {
|
||||||
//if it doesn't already exist, try creating it and if successfull move creature
|
//if it doesn't already exist, try creating it and if successfull move creature
|
||||||
cell = realm.getDataCellManager().tryCreateCellAtPoint(position);
|
cell = realm.getDataCellManager().tryCreateCellAtPoint(position);
|
||||||
|
if(cell == null){
|
||||||
|
throw new Error("Trying to initially position entity to position that cannot generate a data cell! " + position);
|
||||||
|
}
|
||||||
//initialize server datacell tracking of this entity
|
//initialize server datacell tracking of this entity
|
||||||
realm.initializeServerSideEntity(entity, cell);
|
realm.initializeServerSideEntity(entity, cell);
|
||||||
}
|
}
|
||||||
@ -54,25 +60,34 @@ public class ServerEntityUtils {
|
|||||||
* @param position
|
* @param position
|
||||||
*/
|
*/
|
||||||
public static void repositionEntity(Entity entity, Vector3d position){
|
public static void repositionEntity(Entity entity, Vector3d position){
|
||||||
|
if(position == null){
|
||||||
|
throw new Error("Trying to set server entity position to null!");
|
||||||
|
}
|
||||||
Realm realm = Globals.realmManager.getEntityRealm(entity);
|
Realm realm = Globals.realmManager.getEntityRealm(entity);
|
||||||
//if server, get current server data cell
|
//if server, get current server data cell
|
||||||
ServerDataCell oldDataCell = realm.getDataCellManager().getDataCellAtPoint(EntityUtils.getPosition(entity));
|
ServerDataCell oldDataCell = Globals.entityDataCellMapper.getEntityDataCell(entity);
|
||||||
ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position);
|
ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position);
|
||||||
if(oldDataCell == null){
|
if(oldDataCell == null){
|
||||||
LoggerInterface.loggerEngine.WARNING("Trying to reposition entity on server when it's former position is null!");
|
LoggerInterface.loggerEngine.WARNING(
|
||||||
|
"Trying to reposition entity on server when it's former cell is null!\n" +
|
||||||
|
"Entity original position: " + EntityUtils.getPosition(entity) + "\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(oldDataCell != newDataCell){
|
if(oldDataCell != newDataCell){
|
||||||
if(newDataCell != null){
|
if(newDataCell == null){
|
||||||
ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell);
|
newDataCell = realm.getDataCellManager().tryCreateCellAtPoint(position);
|
||||||
ServerBehaviorTreeUtils.updateCell(entity, oldDataCell);
|
if(newDataCell == null){
|
||||||
} else {
|
LoggerInterface.loggerEngine.WARNING(
|
||||||
//if it doesn't already exist, try creating it and if successfull move creature
|
"Trying to reposition entity on server when it's new cell is null!\n" +
|
||||||
newDataCell = realm.getDataCellManager().tryCreateCellAtPoint(EntityUtils.getPosition(entity));
|
"Entity new position: " + position + "\n"
|
||||||
if(newDataCell != null){
|
);
|
||||||
ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell);
|
|
||||||
ServerBehaviorTreeUtils.updateCell(entity, oldDataCell);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell);
|
||||||
|
ServerBehaviorTreeUtils.updateCell(entity, oldDataCell);
|
||||||
|
if(oldDataCell.getScene().containsEntity(entity)){
|
||||||
|
throw new Error("Entity not removed from scene!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//reposition entity
|
//reposition entity
|
||||||
CollisionObjUtils.serverPositionCharacter(entity, position);
|
CollisionObjUtils.serverPositionCharacter(entity, position);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import electrosphere.entity.btree.BehaviorTree;
|
|||||||
import electrosphere.entity.state.attach.AttachUtils;
|
import electrosphere.entity.state.attach.AttachUtils;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -19,13 +20,24 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
*/
|
*/
|
||||||
public class Scene {
|
public class Scene {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of id -> entity
|
||||||
|
*/
|
||||||
Map<Integer,Entity> entityIdMap;
|
Map<Integer,Entity> entityIdMap;
|
||||||
Map<String,Set<Entity>> tagEntityMap;
|
|
||||||
List<Entity> entityList = new CopyOnWriteArrayList<Entity>();
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of tag -> set of entities corresponding to that tag
|
||||||
|
*/
|
||||||
|
Map<String,Set<Entity>> tagEntityMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of behavior trees
|
||||||
|
*/
|
||||||
List<BehaviorTree> behaviorTreeList;
|
List<BehaviorTree> behaviorTreeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
public Scene(){
|
public Scene(){
|
||||||
entityIdMap = new ConcurrentHashMap<Integer,Entity>();
|
entityIdMap = new ConcurrentHashMap<Integer,Entity>();
|
||||||
tagEntityMap = new ConcurrentHashMap<String,Set<Entity>>();
|
tagEntityMap = new ConcurrentHashMap<String,Set<Entity>>();
|
||||||
@ -53,9 +65,6 @@ public class Scene {
|
|||||||
* @param e The entity to register
|
* @param e The entity to register
|
||||||
*/
|
*/
|
||||||
public void registerEntity(Entity e){
|
public void registerEntity(Entity e){
|
||||||
if(!entityIdMap.containsKey(e.getId())){
|
|
||||||
entityList.add(e);
|
|
||||||
}
|
|
||||||
entityIdMap.put(e.getId(), e);
|
entityIdMap.put(e.getId(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +110,6 @@ public class Scene {
|
|||||||
tagEntityMap.get(key).remove(e);
|
tagEntityMap.get(key).remove(e);
|
||||||
}
|
}
|
||||||
entityIdMap.remove(e.getId());
|
entityIdMap.remove(e.getId());
|
||||||
entityList.remove(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,10 +120,10 @@ public class Scene {
|
|||||||
if(AttachUtils.hasChildren(target)){
|
if(AttachUtils.hasChildren(target)){
|
||||||
List<Entity> childrenList = AttachUtils.getChildrenList(target);
|
List<Entity> childrenList = AttachUtils.getChildrenList(target);
|
||||||
for(Entity currentChild : childrenList){
|
for(Entity currentChild : childrenList){
|
||||||
recursiveDeregister(currentChild);
|
this.recursiveDeregister(currentChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deregisterEntity(target);
|
this.deregisterEntity(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,11 +174,11 @@ public class Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the list of all entities in the scene
|
* Gets the collection of all entities in the scene
|
||||||
* @return The list of all entities in the scene
|
* @return The collection of all entities in the scene
|
||||||
*/
|
*/
|
||||||
public List<Entity> getEntityList(){
|
public Collection<Entity> getEntityList(){
|
||||||
return entityList;
|
return this.entityIdMap.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,7 +186,7 @@ public class Scene {
|
|||||||
*/
|
*/
|
||||||
public void describeScene(){
|
public void describeScene(){
|
||||||
LoggerInterface.loggerEngine.WARNING("Entities present in scene:");
|
LoggerInterface.loggerEngine.WARNING("Entities present in scene:");
|
||||||
for(Entity entity : this.entityList){
|
for(Entity entity : this.entityIdMap.values()){
|
||||||
LoggerInterface.loggerEngine.WARNING(entity.getId() + "");
|
LoggerInterface.loggerEngine.WARNING(entity.getId() + "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -166,6 +166,9 @@ public class InventoryUtils {
|
|||||||
* @return The in-inventory item
|
* @return The in-inventory item
|
||||||
*/
|
*/
|
||||||
public static Entity serverAttemptStoreItemTransform(Entity creature, Entity item){
|
public static Entity serverAttemptStoreItemTransform(Entity creature, Entity item){
|
||||||
|
if(item == null){
|
||||||
|
throw new Error("Null item provided! " + item);
|
||||||
|
}
|
||||||
boolean creatureIsCreature = CreatureUtils.isCreature(creature);
|
boolean creatureIsCreature = CreatureUtils.isCreature(creature);
|
||||||
boolean itemIsItem = ItemUtils.isItem(item);
|
boolean itemIsItem = ItemUtils.isItem(item);
|
||||||
boolean hasInventory = hasNaturalInventory(creature);
|
boolean hasInventory = hasNaturalInventory(creature);
|
||||||
@ -360,7 +363,7 @@ public class InventoryUtils {
|
|||||||
Realm realm = Globals.realmManager.getEntityRealm(realWorldItem);
|
Realm realm = Globals.realmManager.getEntityRealm(realWorldItem);
|
||||||
if(realm != null){
|
if(realm != null){
|
||||||
//get closest chunk
|
//get closest chunk
|
||||||
ServerDataCell dataCell = realm.getEntityDataCellMapper().getEntityDataCell(realWorldItem);
|
ServerDataCell dataCell = Globals.entityDataCellMapper.getEntityDataCell(realWorldItem);
|
||||||
//broadcast destroy item
|
//broadcast destroy item
|
||||||
NetworkMessage unequipMessage = InventoryMessage.constructserverCommandUnequipItemMessage(creature.getId(), InventoryProtocol.INVENTORY_TYPE_EQUIP, inventorySlot);
|
NetworkMessage unequipMessage = InventoryMessage.constructserverCommandUnequipItemMessage(creature.getId(), InventoryProtocol.INVENTORY_TYPE_EQUIP, inventorySlot);
|
||||||
dataCell.broadcastNetworkMessage(unequipMessage);
|
dataCell.broadcastNetworkMessage(unequipMessage);
|
||||||
|
|||||||
@ -240,56 +240,6 @@ public class ClientEditorMovementTree implements BehaviorTree {
|
|||||||
Quaterniond movementQuaternion = new Quaterniond().rotationTo(SpatialMathUtils.getOriginVector(), new Vector3d(facingVector.x,0,facingVector.z)).normalize();
|
Quaterniond movementQuaternion = new Quaterniond().rotationTo(SpatialMathUtils.getOriginVector(), new Vector3d(facingVector.x,0,facingVector.z)).normalize();
|
||||||
Quaterniond rotation = EntityUtils.getRotation(parent);
|
Quaterniond rotation = EntityUtils.getRotation(parent);
|
||||||
|
|
||||||
//parse attached network messages
|
|
||||||
for(EntityMessage message : networkMessageQueue){
|
|
||||||
networkMessageQueue.remove(message);
|
|
||||||
long updateTime = message.gettime();
|
|
||||||
// System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ());
|
|
||||||
switch(message.getMessageSubtype()){
|
|
||||||
case MOVEUPDATE:
|
|
||||||
if(updateTime >= lastUpdateTime){
|
|
||||||
lastUpdateTime = updateTime;
|
|
||||||
switch(message.gettreeState()){
|
|
||||||
case 0:
|
|
||||||
state = MovementTreeState.STARTUP;
|
|
||||||
// System.out.println("Set state STARTUP");
|
|
||||||
GravityUtils.clientAttemptActivateGravity(parent);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
state = MovementTreeState.MOVE;
|
|
||||||
// System.out.println("Set state MOVE");
|
|
||||||
GravityUtils.clientAttemptActivateGravity(parent);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
state = MovementTreeState.SLOWDOWN;
|
|
||||||
// System.out.println("Set state SLOWDOWN");
|
|
||||||
GravityUtils.clientAttemptActivateGravity(parent);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
state = MovementTreeState.IDLE;
|
|
||||||
// System.out.println("Set state IDLE");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//this should only fire on the client, we don't want the server snap updating due to client position reporting
|
|
||||||
lastServerPosition = new Vector3d(message.getpositionX(),message.getpositionY(),message.getpositionZ());
|
|
||||||
if(position.distance(lastServerPosition) > STATE_DIFFERENCE_HARD_UPDATE_THRESHOLD){
|
|
||||||
EntityUtils.getPosition(parent).set(lastServerPosition);
|
|
||||||
} else if(position.distance(lastServerPosition) > STATE_DIFFERENCE_SOFT_UPDATE_THRESHOLD){
|
|
||||||
EntityUtils.getPosition(parent).lerp(lastServerPosition,SOFT_UPDATE_MULTIPLIER);
|
|
||||||
}
|
|
||||||
//we want to always update the server facing vector with where the client says they're facing
|
|
||||||
EntityUtils.getRotation(parent).set(message.getrotationX(),message.getrotationY(),message.getrotationZ(),message.getrotationW());
|
|
||||||
CollisionObjUtils.clientPositionCharacter(parent, position, rotation);
|
|
||||||
// CreatureUtils.setFacingVector(parent, new Vector3d(message.getrotationX(),message.getrotationY(),message.getrotationZ()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// System.out.println(movementVector + " " + velocity * Main.deltaTime);
|
|
||||||
|
|
||||||
//state machine
|
//state machine
|
||||||
switch(state){
|
switch(state){
|
||||||
|
|||||||
@ -65,6 +65,11 @@ public class CollisionObjUtils {
|
|||||||
entity.putData(EntityDataStrings.PHYSICS_MASS, mass);
|
entity.putData(EntityDataStrings.PHYSICS_MASS, mass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repositions an entity on the server
|
||||||
|
* @param e The entity
|
||||||
|
* @param position The server
|
||||||
|
*/
|
||||||
public static void serverPositionCharacter(Entity e, Vector3d position){
|
public static void serverPositionCharacter(Entity e, Vector3d position){
|
||||||
EntityUtils.getPosition(e).set(position);
|
EntityUtils.getPosition(e).set(position);
|
||||||
Quaterniond rotation = EntityUtils.getRotation(e);
|
Quaterniond rotation = EntityUtils.getRotation(e);
|
||||||
@ -75,6 +80,12 @@ public class CollisionObjUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Positions an entity on the client
|
||||||
|
* @param e The entity
|
||||||
|
* @param position The position
|
||||||
|
* @param rotation The rotation
|
||||||
|
*/
|
||||||
public static void clientPositionCharacter(Entity e, Vector3d position, Quaterniond rotation){
|
public static void clientPositionCharacter(Entity e, Vector3d position, Quaterniond rotation){
|
||||||
EntityUtils.getPosition(e).set(position);
|
EntityUtils.getPosition(e).set(position);
|
||||||
DBody body = PhysicsEntityUtils.getDBody(e);
|
DBody body = PhysicsEntityUtils.getDBody(e);
|
||||||
|
|||||||
@ -689,6 +689,10 @@ public class CommonEntityUtils {
|
|||||||
ServerEntityTagUtils.attachTagToEntity(entity, EntityTags.LIFE_STATE);
|
ServerEntityTagUtils.attachTagToEntity(entity, EntityTags.LIFE_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Globals.entityDataCellMapper.getEntityDataCell(entity) == null){
|
||||||
|
throw new Error("Failed to map entity to cell!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -402,6 +402,13 @@ public class CreatureUtils {
|
|||||||
if(CreatureUtils.hasControllerPlayerId(creature)){
|
if(CreatureUtils.hasControllerPlayerId(creature)){
|
||||||
LoggerInterface.loggerNetworking.INFO("Sending controller packets");
|
LoggerInterface.loggerNetworking.INFO("Sending controller packets");
|
||||||
player.addMessage(NetUtils.createSetCreatureControllerIdEntityMessage(creature));
|
player.addMessage(NetUtils.createSetCreatureControllerIdEntityMessage(creature));
|
||||||
|
Player entityOwner = Globals.playerManager.getPlayerFromId(CreatureUtils.getControllerPlayerId(creature));
|
||||||
|
if(entityOwner == player){
|
||||||
|
player.setHasSentPlayerEntity(true);
|
||||||
|
}
|
||||||
|
if(Globals.playerEntity != null && player.getId() == Globals.clientPlayer.getId() && player.getPlayerEntity() == creature){
|
||||||
|
throw new Error("Re-sending player entity to player!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,6 +53,11 @@ public class Player {
|
|||||||
* The player's primary entity
|
* The player's primary entity
|
||||||
*/
|
*/
|
||||||
Entity playerEntity;
|
Entity playerEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks whether the player's entity has been sent or not
|
||||||
|
*/
|
||||||
|
boolean hasSentPlayerEntity = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -151,6 +156,24 @@ public class Player {
|
|||||||
idIncrementerLock.release();
|
idIncrementerLock.release();
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether the player has been sent their entity or not
|
||||||
|
* @return true if has been sent, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean hasSentPlayerEntity() {
|
||||||
|
return hasSentPlayerEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the player has been sent their entity or not
|
||||||
|
* @param hasSentPlayerEntity true if has been sent, false otherwise
|
||||||
|
*/
|
||||||
|
public void setHasSentPlayerEntity(boolean hasSentPlayerEntity) {
|
||||||
|
this.hasSentPlayerEntity = hasSentPlayerEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,14 +64,16 @@ public class ServerContentGenerator {
|
|||||||
double scale = foliageDescription.getScale();
|
double scale = foliageDescription.getScale();
|
||||||
double regularity = foliageDescription.getRegularity();
|
double regularity = foliageDescription.getRegularity();
|
||||||
double threshold = foliageDescription.getThreshold();
|
double threshold = foliageDescription.getThreshold();
|
||||||
if(NoiseUtils.relaxedPointGen(x * scale, z * scale, regularity, threshold) > 0){
|
double realX = realm.getServerWorldData().convertVoxelToRealSpace(x, worldPos.x);
|
||||||
|
double realZ = realm.getServerWorldData().convertVoxelToRealSpace(z, worldPos.z);
|
||||||
|
if(NoiseUtils.relaxedPointGen(realX * scale, realZ * scale, regularity, threshold) > 0){
|
||||||
String type = foliageDescription.getEntityIDs().get(random.nextInt(0,foliageDescription.getEntityIDs().size()));
|
String type = foliageDescription.getEntityIDs().get(random.nextInt(0,foliageDescription.getEntityIDs().size()));
|
||||||
FoliageUtils.serverSpawnTreeFoliage(
|
FoliageUtils.serverSpawnTreeFoliage(
|
||||||
realm,
|
realm,
|
||||||
new Vector3d(
|
new Vector3d(
|
||||||
realm.getServerWorldData().convertVoxelToRealSpace(x, worldPos.x),
|
realX,
|
||||||
height,
|
height,
|
||||||
realm.getServerWorldData().convertVoxelToRealSpace(z, worldPos.z)
|
realZ
|
||||||
),
|
),
|
||||||
type,
|
type,
|
||||||
random.nextLong()
|
random.nextLong()
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package electrosphere.server.content;
|
package electrosphere.server.content;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.joml.Vector3i;
|
import org.joml.Vector3i;
|
||||||
@ -73,9 +74,9 @@ public class ServerContentManager {
|
|||||||
/**
|
/**
|
||||||
* Saves entity content to disk
|
* Saves entity content to disk
|
||||||
* @param locationKey the location key to save under
|
* @param locationKey the location key to save under
|
||||||
* @param entities the list of entities to save
|
* @param entities the collection of entities to save
|
||||||
*/
|
*/
|
||||||
public void saveContentToDisk(Long locationKey, List<Entity> entities){
|
public void saveContentToDisk(Long locationKey, Collection<Entity> entities){
|
||||||
ContentSerialization serialization = ContentSerialization.constructContentSerialization(entities);
|
ContentSerialization serialization = ContentSerialization.constructContentSerialization(entities);
|
||||||
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSave.getName());
|
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSave.getName());
|
||||||
String fullPath = dirPath + "/content/" + locationKey + ".dat";
|
String fullPath = dirPath + "/content/" + locationKey + ".dat";
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package electrosphere.server.content.serialization;
|
package electrosphere.server.content.serialization;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ public class ContentSerialization {
|
|||||||
* @param entities The entities
|
* @param entities The entities
|
||||||
* @return The content serialization
|
* @return The content serialization
|
||||||
*/
|
*/
|
||||||
public static ContentSerialization constructContentSerialization(List<Entity> entities){
|
public static ContentSerialization constructContentSerialization(Collection<Entity> entities){
|
||||||
ContentSerialization rVal = new ContentSerialization();
|
ContentSerialization rVal = new ContentSerialization();
|
||||||
for(Entity entity : entities){
|
for(Entity entity : entities){
|
||||||
if(!CreatureUtils.hasControllerPlayerId(entity)){
|
if(!CreatureUtils.hasControllerPlayerId(entity)){
|
||||||
|
|||||||
@ -19,6 +19,9 @@ public class EntityDataCellMapper {
|
|||||||
* @param serverDataCell The server data cell to register this entity to
|
* @param serverDataCell The server data cell to register this entity to
|
||||||
*/
|
*/
|
||||||
public void registerEntity(Entity entity, ServerDataCell serverDataCell){
|
public void registerEntity(Entity entity, ServerDataCell serverDataCell){
|
||||||
|
if(serverDataCell == null){
|
||||||
|
throw new Error("Mapping entity to null!");
|
||||||
|
}
|
||||||
entityDataCellMap.put(entity, serverDataCell);
|
entityDataCellMap.put(entity, serverDataCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
package electrosphere.server.datacell;
|
package electrosphere.server.datacell;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
@ -50,34 +51,71 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
*/
|
*/
|
||||||
public static final int MAX_GRID_SIZE = TerrainModel.MAX_MACRO_DATA_SIZE * TerrainModel.DEFAULT_MACRO_DATA_SCALE * ServerTerrainChunk.CHUNK_DIMENSION;
|
public static final int MAX_GRID_SIZE = TerrainModel.MAX_MACRO_DATA_SIZE * TerrainModel.DEFAULT_MACRO_DATA_SCALE * ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of frames without players that must pass before a server data cell is unloaded
|
||||||
|
*/
|
||||||
|
static final int UNLOAD_FRAME_THRESHOLD = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks whether this manager has been flagged to unload cells or not
|
* Tracks whether this manager has been flagged to unload cells or not
|
||||||
*/
|
*/
|
||||||
boolean unloadCells = true;
|
boolean unloadCells = true;
|
||||||
|
|
||||||
//these are going to be the natural ground grid of data cells, but we're going to have more than this
|
/**
|
||||||
|
* These are going to be the natural ground grid of data cells, but we're going to have more than this
|
||||||
|
*/
|
||||||
Map<Long,ServerDataCell> groundDataCells = new HashMap<Long,ServerDataCell>();
|
Map<Long,ServerDataCell> groundDataCells = new HashMap<Long,ServerDataCell>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of server cell to its world position
|
||||||
|
*/
|
||||||
Map<ServerDataCell,Vector3i> cellPositionMap = new HashMap<ServerDataCell,Vector3i>();
|
Map<ServerDataCell,Vector3i> cellPositionMap = new HashMap<ServerDataCell,Vector3i>();
|
||||||
//Map of server data cell to the number of frames said cell has had no players
|
|
||||||
|
/**
|
||||||
|
* Map of server data cell to the number of frames said cell has had no players
|
||||||
|
*/
|
||||||
Map<ServerDataCell,Integer> cellPlayerlessFrameMap = new HashMap<ServerDataCell,Integer>();
|
Map<ServerDataCell,Integer> cellPlayerlessFrameMap = new HashMap<ServerDataCell,Integer>();
|
||||||
//The number of frames without players that must pass before a server data cell is unloaded
|
|
||||||
static final int UNLOAD_FRAME_THRESHOLD = 100;
|
/**
|
||||||
//loaded cells
|
* Loaded cells
|
||||||
|
*/
|
||||||
Semaphore loadedCellsLock = new Semaphore(1);
|
Semaphore loadedCellsLock = new Semaphore(1);
|
||||||
Set<ServerDataCell> loadedCells = new CopyOnWriteArraySet<ServerDataCell>();
|
|
||||||
//parent realm
|
/**
|
||||||
|
* Parent realm
|
||||||
|
*/
|
||||||
Realm parent;
|
Realm parent;
|
||||||
//the world data of the parent
|
|
||||||
|
/**
|
||||||
|
* The world data of the parent
|
||||||
|
*/
|
||||||
ServerWorldData serverWorldData;
|
ServerWorldData serverWorldData;
|
||||||
//Manager for terrain for this particular cell manager
|
|
||||||
|
/**
|
||||||
|
* Manager for terrain for this particular cell manager
|
||||||
|
*/
|
||||||
ServerTerrainManager serverTerrainManager;
|
ServerTerrainManager serverTerrainManager;
|
||||||
//manager for fluids for this particular cell manager
|
|
||||||
|
/**
|
||||||
|
* Manager for fluids for this particular cell manager
|
||||||
|
*/
|
||||||
ServerFluidManager serverFluidManager;
|
ServerFluidManager serverFluidManager;
|
||||||
//lock for terrain editing
|
|
||||||
|
/**
|
||||||
|
* Lock for terrain editing
|
||||||
|
*/
|
||||||
Semaphore terrainEditLock = new Semaphore(1);
|
Semaphore terrainEditLock = new Semaphore(1);
|
||||||
//manager for getting entities to fill in a cell
|
|
||||||
|
/**
|
||||||
|
* Manager for getting entities to fill in a cell
|
||||||
|
*/
|
||||||
ServerContentManager serverContentManager;
|
ServerContentManager serverContentManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for cleaning server data cells no longer in use from the realm
|
||||||
|
*/
|
||||||
|
Set<ServerDataCell> toCleanQueue = new HashSet<ServerDataCell>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of world position key -> physics cell
|
* Map of world position key -> physics cell
|
||||||
*/
|
*/
|
||||||
@ -132,22 +170,21 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
){
|
){
|
||||||
Vector3i targetPos = new Vector3i(x,y,z);
|
Vector3i targetPos = new Vector3i(x,y,z);
|
||||||
LoggerInterface.loggerEngine.DEBUG("GriddedDataCellManager: Add player to " + x + " " + y + " " + z);
|
LoggerInterface.loggerEngine.DEBUG("GriddedDataCellManager: Add player to " + x + " " + y + " " + z);
|
||||||
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
|
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
|
||||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||||
} else {
|
} else {
|
||||||
LoggerInterface.loggerEngine.DEBUG("Creating new cell @ " + x + " " + y + " " + z);
|
LoggerInterface.loggerEngine.DEBUG("Creating new cell @ " + x + " " + y + " " + z);
|
||||||
//create data cell
|
//create data cell
|
||||||
createServerDataCell(targetPos);
|
this.createServerDataCell(targetPos);
|
||||||
///generates physics for the cell in a dedicated thread then finally registers
|
///generates physics for the cell in a dedicated thread then finally registers
|
||||||
runPhysicsGenerationThread(targetPos);
|
this.runPhysicsGenerationThread(targetPos);
|
||||||
//add to loaded cells
|
//add to loaded cells
|
||||||
loadedCellsLock.acquireUninterruptibly();
|
cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(targetPos)),0);
|
||||||
loadedCells.add(groundDataCells.get(getServerDataCellKey(targetPos)));
|
|
||||||
cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(targetPos)),0);
|
|
||||||
loadedCellsLock.release();
|
|
||||||
//add player
|
//add player
|
||||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||||
}
|
}
|
||||||
|
loadedCellsLock.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,36 +200,29 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
int playerSimulationRadius = player.getSimulationRadius();
|
int playerSimulationRadius = player.getSimulationRadius();
|
||||||
Vector3i oldPosition = player.getWorldPos();
|
Vector3i oldPosition = player.getWorldPos();
|
||||||
player.setWorldPos(newPosition);
|
player.setWorldPos(newPosition);
|
||||||
// System.out.println("=======" + "SET" + newX + " " + newY + " FROM " + oldX + " " + oldY + "========");
|
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||||
// int removals = 0;
|
Vector3i worldPos = this.getCellWorldPosition(cell);
|
||||||
// int additions = 0;
|
if(
|
||||||
for(int x = oldPosition.x - playerSimulationRadius; x < oldPosition.x + playerSimulationRadius + 1; x++){
|
cell.containsPlayer(player) &&
|
||||||
for(int y = oldPosition.y - playerSimulationRadius; y < oldPosition.y + playerSimulationRadius + 1; y++){
|
(
|
||||||
for(int z = oldPosition.z - playerSimulationRadius; z < oldPosition.z + playerSimulationRadius + 1; z++){
|
worldPos.x < newPosition.x - playerSimulationRadius ||
|
||||||
if(
|
worldPos.x > newPosition.x + playerSimulationRadius ||
|
||||||
x >= 0 && x < this.serverWorldData.getWorldSizeDiscrete() &&
|
worldPos.y < newPosition.y - playerSimulationRadius ||
|
||||||
y >= 0 && y < this.serverWorldData.getWorldSizeDiscrete() &&
|
worldPos.y > newPosition.y + playerSimulationRadius ||
|
||||||
z >= 0 && z < this.serverWorldData.getWorldSizeDiscrete() &&
|
worldPos.z < newPosition.z - playerSimulationRadius ||
|
||||||
(
|
worldPos.z > newPosition.z + playerSimulationRadius
|
||||||
x < newPosition.x - playerSimulationRadius ||
|
)
|
||||||
x > newPosition.x + playerSimulationRadius ||
|
){
|
||||||
y < newPosition.y - playerSimulationRadius ||
|
cell.removePlayer(player);
|
||||||
y > newPosition.y + playerSimulationRadius ||
|
this.broadcastDestructionToPlayer(player, cell);
|
||||||
z < newPosition.z - playerSimulationRadius ||
|
if(cell.getScene().containsEntity(player.getPlayerEntity())){
|
||||||
z > newPosition.z + playerSimulationRadius
|
throw new Error(
|
||||||
)
|
"Unregistering player from cell that contains player's entity!\n " +
|
||||||
){
|
player + "\n " +
|
||||||
Vector3i targetPos = new Vector3i(x,y,z);
|
worldPos + "\n " +
|
||||||
Long key = this.getServerDataCellKey(targetPos);
|
player.getPlayerEntity() + "\n " +
|
||||||
if(
|
EntityUtils.getPosition(player.getPlayerEntity())
|
||||||
groundDataCells.get(key) != null &&
|
);
|
||||||
groundDataCells.get(key).containsPlayer(player)
|
|
||||||
){
|
|
||||||
// removals++;
|
|
||||||
groundDataCells.get(key).removePlayer(player);
|
|
||||||
this.broadcastDestructionToPlayer(player, groundDataCells.get(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,31 +243,26 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
)
|
)
|
||||||
){
|
){
|
||||||
Vector3i targetPos = new Vector3i(x,y,z);
|
Vector3i targetPos = new Vector3i(x,y,z);
|
||||||
// System.out.println("Add player to " + x + " " + y);
|
|
||||||
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
|
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
|
||||||
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||||
|
loadedCellsLock.release();
|
||||||
} else {
|
} else {
|
||||||
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
//create data cell
|
//create data cell
|
||||||
createServerDataCell(targetPos);
|
createServerDataCell(targetPos);
|
||||||
//generates physics for the cell in a dedicated thread then finally registers
|
//generates physics for the cell in a dedicated thread then finally registers
|
||||||
runPhysicsGenerationThread(targetPos);
|
runPhysicsGenerationThread(targetPos);
|
||||||
//add to loaded cells
|
//add to loaded cells
|
||||||
loadedCellsLock.acquireUninterruptibly();
|
|
||||||
loadedCells.add(groundDataCells.get(getServerDataCellKey(targetPos)));
|
|
||||||
cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(targetPos)),0);
|
cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(targetPos)),0);
|
||||||
loadedCellsLock.release();
|
|
||||||
//add player
|
//add player
|
||||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||||
|
loadedCellsLock.release();
|
||||||
}
|
}
|
||||||
// additions++;
|
|
||||||
} else {
|
|
||||||
// System.out.println(x + "\t" + (oldX - playerSimulationRadius) + "\t" + (oldX + playerSimulationRadius));
|
|
||||||
// System.out.println(y + "\t" + (oldY - playerSimulationRadius) + "\t" + (oldY + playerSimulationRadius));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// System.out.println("removals: " + removals + "\tadditions: " + additions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -280,25 +305,80 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
int currentWorldX = parent.getServerWorldData().convertRealToChunkSpace(position.x);
|
int currentWorldX = parent.getServerWorldData().convertRealToChunkSpace(position.x);
|
||||||
int currentWorldY = parent.getServerWorldData().convertRealToChunkSpace(position.y);
|
int currentWorldY = parent.getServerWorldData().convertRealToChunkSpace(position.y);
|
||||||
int currentWorldZ = parent.getServerWorldData().convertRealToChunkSpace(position.z);
|
int currentWorldZ = parent.getServerWorldData().convertRealToChunkSpace(position.z);
|
||||||
if(currentWorldX != player.getWorldPos().x || currentWorldY != player.getWorldPos().y || currentWorldZ != player.getWorldPos().z){
|
Vector3i newPosition = new Vector3i(currentWorldX,currentWorldY,currentWorldZ);
|
||||||
movePlayer(player,new Vector3i(currentWorldX,currentWorldY,currentWorldZ));
|
player.setWorldPos(newPosition);
|
||||||
playerChangedChunk = true;
|
|
||||||
|
int playerSimulationRadius = player.getSimulationRadius();
|
||||||
|
|
||||||
|
//remove from cells that are out of range
|
||||||
|
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||||
|
Vector3i cellWorldPos = this.getCellWorldPosition(cell);
|
||||||
|
if(
|
||||||
|
cell.containsPlayer(player) &&
|
||||||
|
(
|
||||||
|
cellWorldPos.x < newPosition.x - playerSimulationRadius ||
|
||||||
|
cellWorldPos.x > newPosition.x + playerSimulationRadius ||
|
||||||
|
cellWorldPos.y < newPosition.y - playerSimulationRadius ||
|
||||||
|
cellWorldPos.y > newPosition.y + playerSimulationRadius ||
|
||||||
|
cellWorldPos.z < newPosition.z - playerSimulationRadius ||
|
||||||
|
cellWorldPos.z > newPosition.z + playerSimulationRadius
|
||||||
|
)
|
||||||
|
){
|
||||||
|
if(cell.getScene().containsEntity(player.getPlayerEntity())){
|
||||||
|
throw new Error("Trying to remove player from a cell that contains its entity!");
|
||||||
|
}
|
||||||
|
cell.removePlayer(player);
|
||||||
|
this.broadcastDestructionToPlayer(player, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add to cells that are in range
|
||||||
|
for(int x = newPosition.x - playerSimulationRadius + 1; x < newPosition.x + playerSimulationRadius; x++){
|
||||||
|
for(int y = newPosition.y - playerSimulationRadius + 1; y < newPosition.y + playerSimulationRadius; y++){
|
||||||
|
for(int z = newPosition.x - playerSimulationRadius + 1; z < newPosition.z + playerSimulationRadius; z++){
|
||||||
|
if(
|
||||||
|
x >= 0 && x < this.serverWorldData.getWorldSizeDiscrete() &&
|
||||||
|
y >= 0 && y < this.serverWorldData.getWorldSizeDiscrete() &&
|
||||||
|
z >= 0 && z < this.serverWorldData.getWorldSizeDiscrete()
|
||||||
|
){
|
||||||
|
Vector3i targetPos = new Vector3i(x,y,z);
|
||||||
|
if(groundDataCells.get(this.getServerDataCellKey(targetPos)) != null){
|
||||||
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
|
ServerDataCell cell = groundDataCells.get(this.getServerDataCellKey(targetPos));
|
||||||
|
if(!cell.containsPlayer(player)){
|
||||||
|
cell.addPlayer(player);
|
||||||
|
}
|
||||||
|
loadedCellsLock.release();
|
||||||
|
} else {
|
||||||
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
|
//create data cell
|
||||||
|
this.createServerDataCell(targetPos);
|
||||||
|
//generates physics for the cell in a dedicated thread then finally registers
|
||||||
|
this.runPhysicsGenerationThread(targetPos);
|
||||||
|
//add to loaded cells
|
||||||
|
cellPlayerlessFrameMap.put(groundDataCells.get(this.getServerDataCellKey(targetPos)),0);
|
||||||
|
//add player
|
||||||
|
groundDataCells.get(this.getServerDataCellKey(targetPos)).addPlayer(player);
|
||||||
|
loadedCellsLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return playerChangedChunk;
|
return playerChangedChunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Used for cleaning server data cells no longer in use from the realm
|
|
||||||
Set<ServerDataCell> toCleanQueue = new HashSet<ServerDataCell>();
|
|
||||||
/**
|
/**
|
||||||
* Unloads all chunks that haven't had players in them for a set amount of time
|
* Unloads all chunks that haven't had players in them for a set amount of time
|
||||||
*/
|
*/
|
||||||
public void unloadPlayerlessChunks(){
|
public void unloadPlayerlessChunks(){
|
||||||
if(this.unloadCells){
|
if(this.unloadCells){
|
||||||
//TODO: improve to make have less performance impact
|
//TODO: improve to make have less performance impact
|
||||||
for(ServerDataCell cell : loadedCells){
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
loadedCellsLock.acquireUninterruptibly();
|
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||||
if(cell.getPlayers().size() < 1){
|
if(cell.getPlayers().size() < 1){
|
||||||
int frameCount = cellPlayerlessFrameMap.get(cell) + 1;
|
int frameCount = cellPlayerlessFrameMap.get(cell) + 1;
|
||||||
cellPlayerlessFrameMap.put(cell,frameCount);
|
cellPlayerlessFrameMap.put(cell,frameCount);
|
||||||
@ -310,11 +390,9 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
cellPlayerlessFrameMap.put(cell, 0);
|
cellPlayerlessFrameMap.put(cell, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadedCellsLock.release();
|
|
||||||
}
|
}
|
||||||
for(ServerDataCell cell : toCleanQueue){
|
for(ServerDataCell cell : toCleanQueue){
|
||||||
parent.deregisterCell(cell);
|
parent.deregisterCell(cell);
|
||||||
loadedCells.remove(cell);
|
|
||||||
Vector3i worldPos = getCellWorldPosition(cell);
|
Vector3i worldPos = getCellWorldPosition(cell);
|
||||||
Long key = getServerDataCellKey(worldPos);
|
Long key = getServerDataCellKey(worldPos);
|
||||||
groundDataCells.remove(key);
|
groundDataCells.remove(key);
|
||||||
@ -323,13 +401,20 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
//clear all entities in cell
|
//clear all entities in cell
|
||||||
for(Entity entity : cell.getScene().getEntityList()){
|
for(Entity entity : cell.getScene().getEntityList()){
|
||||||
if(ServerPlayerViewDirTree.hasTree(entity)){
|
if(ServerPlayerViewDirTree.hasTree(entity)){
|
||||||
throw new Error("Trying to unload a player's entity! " + entity + " " + worldPos);
|
throw new Error(
|
||||||
|
"Trying to unload a player's entity! " +
|
||||||
|
entity + "\n" +
|
||||||
|
EntityUtils.getPosition(entity) + "\n" +
|
||||||
|
serverWorldData.convertRealToWorldSpace(EntityUtils.getPosition(entity)) + "\n" +
|
||||||
|
worldPos
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ServerEntityUtils.destroyEntity(entity);
|
ServerEntityUtils.destroyEntity(entity);
|
||||||
}
|
}
|
||||||
//save terrain to disk
|
//save terrain to disk
|
||||||
serverTerrainManager.savePositionToDisk(worldPos);
|
serverTerrainManager.savePositionToDisk(worldPos);
|
||||||
}
|
}
|
||||||
|
loadedCellsLock.release();
|
||||||
toCleanQueue.clear();
|
toCleanQueue.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,16 +427,14 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
*/
|
*/
|
||||||
public void evictAll(){
|
public void evictAll(){
|
||||||
//TODO: improve to make have less performance impact
|
//TODO: improve to make have less performance impact
|
||||||
for(ServerDataCell cell : loadedCells){
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
loadedCellsLock.acquireUninterruptibly();
|
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||||
int frameCount = cellPlayerlessFrameMap.get(cell) + 1;
|
int frameCount = cellPlayerlessFrameMap.get(cell) + 1;
|
||||||
cellPlayerlessFrameMap.put(cell,frameCount);
|
cellPlayerlessFrameMap.put(cell,frameCount);
|
||||||
toCleanQueue.add(cell);
|
toCleanQueue.add(cell);
|
||||||
loadedCellsLock.release();
|
|
||||||
}
|
}
|
||||||
for(ServerDataCell cell : toCleanQueue){
|
for(ServerDataCell cell : toCleanQueue){
|
||||||
parent.deregisterCell(cell);
|
parent.deregisterCell(cell);
|
||||||
loadedCells.remove(cell);
|
|
||||||
Vector3i worldPos = getCellWorldPosition(cell);
|
Vector3i worldPos = getCellWorldPosition(cell);
|
||||||
Long key = getServerDataCellKey(worldPos);
|
Long key = getServerDataCellKey(worldPos);
|
||||||
groundDataCells.remove(key);
|
groundDataCells.remove(key);
|
||||||
@ -362,6 +445,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
ServerEntityUtils.destroyEntity(entity);
|
ServerEntityUtils.destroyEntity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loadedCellsLock.release();
|
||||||
this.serverTerrainManager.evictAll();
|
this.serverTerrainManager.evictAll();
|
||||||
toCleanQueue.clear();
|
toCleanQueue.clear();
|
||||||
}
|
}
|
||||||
@ -420,13 +504,12 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
//isn't null
|
//isn't null
|
||||||
groundDataCells.get(this.getServerDataCellKey(worldPos)) == null
|
groundDataCells.get(this.getServerDataCellKey(worldPos)) == null
|
||||||
){
|
){
|
||||||
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
//create data cell
|
//create data cell
|
||||||
this.createServerDataCell(worldPos);
|
this.createServerDataCell(worldPos);
|
||||||
//generates physics for the cell in a dedicated thread then finally registers
|
//generates physics for the cell in a dedicated thread then finally registers
|
||||||
this.runPhysicsGenerationThread(worldPos);
|
this.runPhysicsGenerationThread(worldPos);
|
||||||
//add to loaded cells
|
//add to loaded cells
|
||||||
loadedCellsLock.acquireUninterruptibly();
|
|
||||||
loadedCells.add(groundDataCells.get(this.getServerDataCellKey(worldPos)));
|
|
||||||
cellPlayerlessFrameMap.put(groundDataCells.get(this.getServerDataCellKey(worldPos)),0);
|
cellPlayerlessFrameMap.put(groundDataCells.get(this.getServerDataCellKey(worldPos)),0);
|
||||||
loadedCellsLock.release();
|
loadedCellsLock.release();
|
||||||
} else if(groundDataCells.get(this.getServerDataCellKey(worldPos)) == null) {
|
} else if(groundDataCells.get(this.getServerDataCellKey(worldPos)) == null) {
|
||||||
@ -464,7 +547,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
*/
|
*/
|
||||||
public void simulate(){
|
public void simulate(){
|
||||||
loadedCellsLock.acquireUninterruptibly();
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
for(ServerDataCell cell : loadedCells){
|
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||||
if(Globals.microSimulation != null && Globals.microSimulation.isReady()){
|
if(Globals.microSimulation != null && Globals.microSimulation.isReady()){
|
||||||
Globals.microSimulation.simulate(cell);
|
Globals.microSimulation.simulate(cell);
|
||||||
}
|
}
|
||||||
@ -477,7 +560,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadedCellsLock.release();
|
loadedCellsLock.release();
|
||||||
updatePlayerPositions();
|
this.updatePlayerPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -536,7 +619,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
*/
|
*/
|
||||||
private ServerDataCell createServerDataCell(Vector3i worldPos){
|
private ServerDataCell createServerDataCell(Vector3i worldPos){
|
||||||
ServerDataCell rVal = parent.createNewCell();
|
ServerDataCell rVal = parent.createNewCell();
|
||||||
Long cellKey = getServerDataCellKey(worldPos);
|
Long cellKey = this.getServerDataCellKey(worldPos);
|
||||||
groundDataCells.put(cellKey,rVal);
|
groundDataCells.put(cellKey,rVal);
|
||||||
LoggerInterface.loggerEngine.DEBUG("Create server data cell with key " + cellKey);
|
LoggerInterface.loggerEngine.DEBUG("Create server data cell with key " + cellKey);
|
||||||
cellPositionMap.put(rVal,new Vector3i(worldPos));
|
cellPositionMap.put(rVal,new Vector3i(worldPos));
|
||||||
@ -674,7 +757,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(String saveName) {
|
public void save(String saveName) {
|
||||||
for(ServerDataCell cell : loadedCells){
|
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||||
Long key = this.getServerDataCellKey(this.getCellWorldPosition(cell));
|
Long key = this.getServerDataCellKey(this.getCellWorldPosition(cell));
|
||||||
//offload all entities in cell to chunk file
|
//offload all entities in cell to chunk file
|
||||||
serverContentManager.saveContentToDisk(key, cell.getScene().getEntityList());
|
serverContentManager.saveContentToDisk(key, cell.getScene().getEntityList());
|
||||||
@ -705,4 +788,12 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
return returnPos;
|
return returnPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the set of loaded cells
|
||||||
|
* @return The set of loaded cells
|
||||||
|
*/
|
||||||
|
public Collection<ServerDataCell> getLoadedCells(){
|
||||||
|
return Collections.unmodifiableCollection(this.groundDataCells.values());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,14 +150,6 @@ public class Realm {
|
|||||||
Globals.entityDataCellMapper.registerEntity(entity, cell);
|
Globals.entityDataCellMapper.registerEntity(entity, cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the entity data cell mapper for this realm
|
|
||||||
* @return The entity data cell mapper for this realm
|
|
||||||
*/
|
|
||||||
public EntityDataCellMapper getEntityDataCellMapper(){
|
|
||||||
return this.entityDataCellMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data cell manager for this realm
|
* Gets the data cell manager for this realm
|
||||||
@ -167,14 +159,6 @@ public class Realm {
|
|||||||
return this.dataCellManager;
|
return this.dataCellManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the entity data cell mapper for this realm
|
|
||||||
* @param entityDataCellMapper The entity data cell mapper for this realm
|
|
||||||
*/
|
|
||||||
protected void setEntityDataCellMapper(EntityDataCellMapper entityDataCellMapper){
|
|
||||||
this.entityDataCellMapper = entityDataCellMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the data cell manager for this realm
|
* Sets the data cell manager for this realm
|
||||||
* @param dataCellManager The data cell manager for this realm
|
* @param dataCellManager The data cell manager for this realm
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import org.joml.Vector3d;
|
|||||||
import electrosphere.collision.CollisionEngine;
|
import electrosphere.collision.CollisionEngine;
|
||||||
import electrosphere.collision.CollisionWorldData;
|
import electrosphere.collision.CollisionWorldData;
|
||||||
import electrosphere.collision.hitbox.HitboxManager;
|
import electrosphere.collision.hitbox.HitboxManager;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.game.server.world.ServerWorldData;
|
import electrosphere.game.server.world.ServerWorldData;
|
||||||
import electrosphere.net.server.player.Player;
|
import electrosphere.net.server.player.Player;
|
||||||
@ -76,10 +77,8 @@ public class RealmManager {
|
|||||||
);
|
);
|
||||||
//create function classes
|
//create function classes
|
||||||
GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm);
|
GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm);
|
||||||
EntityDataCellMapper entityDataCellMapper = new EntityDataCellMapper();
|
|
||||||
//add function classes to realm
|
//add function classes to realm
|
||||||
realm.setDataCellManager(griddedDataCellManager);
|
realm.setDataCellManager(griddedDataCellManager);
|
||||||
realm.setEntityDataCellMapper(entityDataCellMapper);
|
|
||||||
//register within the manager
|
//register within the manager
|
||||||
realms.add(realm);
|
realms.add(realm);
|
||||||
return realm;
|
return realm;
|
||||||
@ -113,7 +112,6 @@ public class RealmManager {
|
|||||||
|
|
||||||
//add function classes to realm
|
//add function classes to realm
|
||||||
realm.setDataCellManager(ViewportDataCellManager.create(realm));
|
realm.setDataCellManager(ViewportDataCellManager.create(realm));
|
||||||
realm.setEntityDataCellMapper(new EntityDataCellMapper());
|
|
||||||
|
|
||||||
//register
|
//register
|
||||||
realms.add(realm);
|
realms.add(realm);
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import java.util.Set;
|
|||||||
* of simulation. It just acts as an object to relate players and entities by location.
|
* of simulation. It just acts as an object to relate players and entities by location.
|
||||||
* This SHOULD be used for networking purposes. This is the mechanism to scope
|
* This SHOULD be used for networking purposes. This is the mechanism to scope
|
||||||
* network messages by location. If you are looking for something closer to a scene from
|
* network messages by location. If you are looking for something closer to a scene from
|
||||||
* a traditional game engine, EntityManager is effectively a scene for all intents and
|
* a traditional game engine, Realm is effectively a scene for all intents and
|
||||||
* purposes.
|
* purposes.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -62,9 +62,9 @@ public class ServerDataCell {
|
|||||||
* @param p
|
* @param p
|
||||||
*/
|
*/
|
||||||
public void addPlayer(Player p){
|
public void addPlayer(Player p){
|
||||||
if(!activePlayers.contains(p)){
|
if(!this.containsPlayer(p)){
|
||||||
activePlayers.add(p);
|
activePlayers.add(p);
|
||||||
serializeStateToPlayer(p);
|
this.serializeStateToPlayer(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ public class ServerDataCell {
|
|||||||
*/
|
*/
|
||||||
void serializeStateToPlayer(Player player){
|
void serializeStateToPlayer(Player player){
|
||||||
for(Entity entity : scene.getEntityList()){
|
for(Entity entity : scene.getEntityList()){
|
||||||
serializeEntityToPlayer(entity,player);
|
this.serializeEntityToPlayer(entity,player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,21 +144,23 @@ public class ServerDataCell {
|
|||||||
* @param player The player to send the entity to
|
* @param player The player to send the entity to
|
||||||
*/
|
*/
|
||||||
void serializeEntityToPlayer(Entity entity, Player player){
|
void serializeEntityToPlayer(Entity entity, Player player){
|
||||||
EntityType type = CommonEntityUtils.getEntityType(entity);
|
if(!player.hasSentPlayerEntity() || player.getPlayerEntity() == null || player.getPlayerEntity() != entity){
|
||||||
if(type != null){
|
EntityType type = CommonEntityUtils.getEntityType(entity);
|
||||||
switch(type){
|
if(type != null){
|
||||||
case CREATURE: {
|
switch(type){
|
||||||
CreatureUtils.sendEntityToPlayer(player, entity);
|
case CREATURE: {
|
||||||
} break;
|
CreatureUtils.sendEntityToPlayer(player, entity);
|
||||||
case ITEM: {
|
} break;
|
||||||
ItemUtils.sendEntityToPlayer(player, entity);
|
case ITEM: {
|
||||||
} break;
|
ItemUtils.sendEntityToPlayer(player, entity);
|
||||||
case FOLIAGE: {
|
} break;
|
||||||
FoliageUtils.sendFoliageToPlayer(player, entity);
|
case FOLIAGE: {
|
||||||
} break;
|
FoliageUtils.sendFoliageToPlayer(player, entity);
|
||||||
case COMMON: {
|
} break;
|
||||||
CommonEntityUtils.sendEntityToPlayer(player, entity);
|
case COMMON: {
|
||||||
} break;
|
CommonEntityUtils.sendEntityToPlayer(player, entity);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,32 +183,42 @@ public class ServerDataCell {
|
|||||||
* @param newCell The new datacell it's moving to
|
* @param newCell The new datacell it's moving to
|
||||||
*/
|
*/
|
||||||
public static void moveEntityFromCellToCell(Entity entity, ServerDataCell oldCell, ServerDataCell newCell){
|
public static void moveEntityFromCellToCell(Entity entity, ServerDataCell oldCell, ServerDataCell newCell){
|
||||||
//swap which holds the entity
|
if(entity == null){
|
||||||
if(oldCell != null){
|
throw new Error("Passed null entity! " + entity);
|
||||||
oldCell.getScene().deregisterEntity(entity);
|
|
||||||
}
|
}
|
||||||
|
if(oldCell == null){
|
||||||
|
throw new Error("Passed null oldCell! " + oldCell);
|
||||||
|
}
|
||||||
|
if(newCell == null){
|
||||||
|
throw new Error("Passed null newCell! " + newCell);
|
||||||
|
}
|
||||||
|
//swap which holds the entity
|
||||||
|
oldCell.getScene().deregisterEntity(entity);
|
||||||
newCell.getScene().registerEntity(entity);
|
newCell.getScene().registerEntity(entity);
|
||||||
//update entity data cell mapper
|
//update entity data cell mapper
|
||||||
Globals.entityDataCellMapper.updateEntityCell(entity, newCell);
|
Globals.entityDataCellMapper.updateEntityCell(entity, newCell);
|
||||||
//send the entity to new players that should care about it
|
//send the entity to new players that should care about it
|
||||||
for(Player player : newCell.activePlayers){
|
for(Player player : newCell.activePlayers){
|
||||||
if(oldCell != null){
|
if(player.getPlayerEntity() == null || player.getPlayerEntity() != entity){
|
||||||
//if the player hasn't already seen the entity, serialize it
|
if(oldCell != null){
|
||||||
if(!oldCell.containsPlayer(player)){
|
//if the player hasn't already seen the entity, serialize it
|
||||||
|
if(!oldCell.containsPlayer(player)){
|
||||||
|
newCell.serializeEntityToPlayer(entity, player);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//if the entity wasn't in a previous cell, send it to all players
|
||||||
newCell.serializeEntityToPlayer(entity, player);
|
newCell.serializeEntityToPlayer(entity, player);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//if the entity wasn't in a previous cell, send it to all players
|
|
||||||
newCell.serializeEntityToPlayer(entity, player);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//delete the entity for players that dont care about it
|
//delete the entity for players that dont care about it
|
||||||
if(oldCell != null){
|
for(Player player : oldCell.activePlayers){
|
||||||
for(Player player : oldCell.activePlayers){
|
if(
|
||||||
if(!newCell.containsPlayer(player)){
|
!newCell.containsPlayer(player) &&
|
||||||
//if the player isn't also in the new cell, delete the entity
|
(player.getPlayerEntity() == null || player.getPlayerEntity() != entity)
|
||||||
player.addMessage(EntityMessage.constructDestroyMessage(entity.getId()));
|
){
|
||||||
}
|
//if the player isn't also in the new cell, delete the entity
|
||||||
|
player.addMessage(EntityMessage.constructDestroyMessage(entity.getId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public class DataCellSearchUtils {
|
|||||||
LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("Trying to get entity data cell of an entity that is not assigned to a realm!"));
|
LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("Trying to get entity data cell of an entity that is not assigned to a realm!"));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return realm.getEntityDataCellMapper().getEntityDataCell(entity);
|
return Globals.entityDataCellMapper.getEntityDataCell(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package electrosphere.server.datacell.utils;
|
package electrosphere.server.datacell.utils;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.server.datacell.ServerDataCell;
|
import electrosphere.server.datacell.ServerDataCell;
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ public class ServerEntityTagUtils {
|
|||||||
* @param tag The tag
|
* @param tag The tag
|
||||||
*/
|
*/
|
||||||
public static void attachTagToEntity(Entity entity, String tag){
|
public static void attachTagToEntity(Entity entity, String tag){
|
||||||
ServerDataCell cell = DataCellSearchUtils.getEntityDataCell(entity);
|
ServerDataCell cell = Globals.entityDataCellMapper.getEntityDataCell(entity);
|
||||||
cell.getScene().registerEntityToTag(entity, tag);
|
cell.getScene().registerEntityToTag(entity, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ public class ServerEntityTagUtils {
|
|||||||
* @param tag The tag
|
* @param tag The tag
|
||||||
*/
|
*/
|
||||||
public static void removeTagFromEntity(Entity entity, String tag){
|
public static void removeTagFromEntity(Entity entity, String tag){
|
||||||
ServerDataCell cell = DataCellSearchUtils.getEntityDataCell(entity);
|
ServerDataCell cell = Globals.entityDataCellMapper.getEntityDataCell(entity);
|
||||||
cell.getScene().removeEntityFromTag(entity, tag);
|
cell.getScene().removeEntityFromTag(entity, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user