Fix terrain editing
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-11-23 16:47:33 -05:00
parent a34dc4a4dc
commit 5fee2d06af
15 changed files with 199 additions and 55 deletions

View File

@ -1132,6 +1132,8 @@ Disable tunnel noise to align foliage better + adjust manual value for foliage p
(11/23/2024) (11/23/2024)
Clean up top level folder Clean up top level folder
Break out dependency documentation into a dedicated file Break out dependency documentation into a dedicated file
Fix terrain editing
Fix foliage not updating at edited chunk
# TODO # TODO
@ -1168,6 +1170,7 @@ Bug Fixes
- Fix particles not spawning in correct positions - Fix particles not spawning in correct positions
- Fix flickering when applying yoga signal (may need to rethink arch here) - Fix flickering when applying yoga signal (may need to rethink arch here)
- Fix virtual scrollables not working - Fix virtual scrollables not working
- Fix foliage flickering on edit
Startup Performance Startup Performance
- Allow texture map to bind multiple model paths to a single set of mesh->textures - Allow texture map to bind multiple model paths to a single set of mesh->textures

View File

@ -154,6 +154,31 @@ public class ClientWorldData {
); );
} }
/**
* Converts a relative voxel position to its absolute voxel equivalent
* @param voxelPos The relative voxel position
* @param worldPos The position of the chunk
* @return The absolute voxel position ie the voxel-aligned position not clamped to the current chunk
*/
public Vector3i convertRelativeVoxelToAbsoluteVoxelSpace(Vector3i voxelPos, Vector3i worldPos){
return new Vector3i(
worldPos.x * ServerTerrainChunk.CHUNK_DIMENSION + voxelPos.x,
worldPos.y * ServerTerrainChunk.CHUNK_DIMENSION + voxelPos.y,
worldPos.z * ServerTerrainChunk.CHUNK_DIMENSION + voxelPos.z
);
}
/**
* Converts a relative voxel position to its absolute voxel equivalent
* @param voxelPos The relative voxel position
* @param worldPos The position of the chunk
* @return The absolute voxel position ie the voxel-aligned position not clamped to the current chunk
*/
public int convertRelativeVoxelToAbsoluteVoxelSpace(int voxelPos, int worldPos){
return worldPos * ServerTerrainChunk.CHUNK_DIMENSION + voxelPos;
}
/** /**
* Converts a world space vector to a real space vector * Converts a world space vector to a real space vector
* @param position The world space vector * @param position The world space vector

View File

@ -14,6 +14,11 @@ import electrosphere.entity.Entity;
*/ */
public class ScriptClientVoxelUtils { public class ScriptClientVoxelUtils {
/**
* Increment to edit terrain by
*/
static final float EDIT_INCREMENT = 0.1f;
/** /**
* Applies the current voxel palette where the player's cursor is looking * Applies the current voxel palette where the player's cursor is looking
*/ */
@ -29,7 +34,7 @@ public class ScriptClientVoxelUtils {
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera)); Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE); Vector3d cursorPos = collisionEngine.rayCastPosition(new Vector3d(centerPos), new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
if(Globals.clientSelectedVoxelType != null){ if(Globals.clientSelectedVoxelType != null){
TerrainEditing.editTerrain(cursorPos, 1.1f, Globals.clientSelectedVoxelType.getId(), 0.1f); TerrainEditing.editTerrain(cursorPos, 1.1f, Globals.clientSelectedVoxelType.getId(), EDIT_INCREMENT);
} }
} }
} }

View File

@ -159,7 +159,7 @@ public class ChunkData {
voxelWeight[localX][localY][localZ] = weight; voxelWeight[localX][localY][localZ] = weight;
voxelType[localX][localY][localZ] = type; voxelType[localX][localY][localZ] = type;
//store as modified in cache //store as modified in cache
String key = getVoxelPositionKey(new Vector3i(localX,localY,localZ)); String key = this.getVoxelPositionKey(new Vector3i(localX,localY,localZ));
if(!modifiedSinceLastGeneration.contains(key)){ if(!modifiedSinceLastGeneration.contains(key)){
modifiedSinceLastGeneration.add(key); modifiedSinceLastGeneration.add(key);
} }

View File

@ -799,8 +799,11 @@ public class ClientDrawCellManager {
* @param worldY The world y position * @param worldY The world y position
* @param worldZ The world z position * @param worldZ The world z position
*/ */
public void markUpdateable(float worldX, float worldY, float worldZ){ public void markUpdateable(int worldX, int worldY, int worldZ){
throw new Error("Unimplemented"); DrawCell drawCell = this.getDrawCell(worldX, worldY, worldZ);
drawCell.ejectChunkData();
drawCell.setHasGenerated(false);
drawCell.setHasRequested(false);
} }
/** /**

View File

@ -175,10 +175,11 @@ public class DrawCell {
} }
} }
} }
Entity toDelete = this.modelEntity;
modelEntity = TerrainChunk.clientCreateTerrainChunkEntity( modelEntity = TerrainChunk.clientCreateTerrainChunkEntity(
this.chunkData, this.chunkData,
this.notifyTarget, this.notifyTarget,
this.modelEntity, toDelete,
lod, lod,
atlas, atlas,
this.hasPolygons() this.hasPolygons()
@ -555,6 +556,13 @@ public class DrawCell {
this.failedGenerationAttempts = this.failedGenerationAttempts + attempts; this.failedGenerationAttempts = this.failedGenerationAttempts + attempts;
} }
/**
* Ejects the chunk data
*/
public void ejectChunkData(){
this.chunkData = null;
}
/** /**
* Gets whether this draw cell is homogenous or not * Gets whether this draw cell is homogenous or not
* @return true if it is homogenous, false otherwise * @return true if it is homogenous, false otherwise

View File

@ -19,7 +19,6 @@ import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils; import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.btree.BehaviorTree;
import electrosphere.renderer.OpenGLState; import electrosphere.renderer.OpenGLState;
@ -267,7 +266,6 @@ public class FoliageCell {
this.chunkData = new TransvoxelChunkData(currentChunk.getVoxelWeight(), currentChunk.getVoxelType(), 0); this.chunkData = new TransvoxelChunkData(currentChunk.getVoxelWeight(), currentChunk.getVoxelType(), 0);
} }
this.generate(); this.generate();
this.setHasGenerated(true);
} }
@ -276,9 +274,6 @@ public class FoliageCell {
*/ */
protected void generate(){ protected void generate(){
boolean shouldGenerate = false; boolean shouldGenerate = false;
if(!Globals.clientDrawCellManager.hasGeneratedPhysics(worldPos.x, worldPos.y, worldPos.z)){
return;
}
ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos,ChunkData.NO_STRIDE); ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos,ChunkData.NO_STRIDE);
if(data == null){ if(data == null){
return; return;
@ -315,9 +310,12 @@ public class FoliageCell {
if(shouldGenerate){ if(shouldGenerate){
Entity oldEntity = this.modelEntity; Entity oldEntity = this.modelEntity;
//create entity //create entity
this.modelEntity = EntityCreationUtils.createClientSpatialEntity(); this.modelEntity = FoliageModel.clientCreateFoliageChunkEntity(foliageTypesSupported,scale,this.getRealPos(),worldPos,voxelPos,notifyTarget,oldEntity);
FoliageModel.clientCreateFoliageChunkEntity(foliageTypesSupported,scale,this.modelEntity,this.getRealPos(),worldPos,voxelPos,notifyTarget,oldEntity);
} else { } else {
if(this.modelEntity != null){
ClientEntityUtils.destroyEntity(this.modelEntity);
this.modelEntity = null;
}
this.homogenous = true; this.homogenous = true;
} }
this.hasGenerated = true; this.hasGenerated = true;
@ -650,6 +648,13 @@ public class FoliageCell {
this.failedGenerationAttempts = this.failedGenerationAttempts + attempts; this.failedGenerationAttempts = this.failedGenerationAttempts + attempts;
} }
/**
* Ejects the chunk data
*/
public void ejectChunkData(){
this.chunkData = null;
}
/** /**
* Gets whether this foliage cell is homogenous or not * Gets whether this foliage cell is homogenous or not
* @return true if it is homogenous, false otherwise * @return true if it is homogenous, false otherwise

View File

@ -723,9 +723,18 @@ public class FoliageCellManager {
* @param worldX The world x position * @param worldX The world x position
* @param worldY The world y position * @param worldY The world y position
* @param worldZ The world z position * @param worldZ The world z position
* @param voxelX The voxel x position
* @param voxelY The voxel y position
* @param voxelZ The voxel z position
*/ */
public void markUpdateable(float worldX, float worldY, float worldZ){ public void markUpdateable(int worldX, int worldY, int worldZ, int voxelX, int voxelY, int voxelZ){
throw new Error("Unimplemented"); int absVoxelX = Globals.clientWorldData.convertRelativeVoxelToAbsoluteVoxelSpace(voxelX,worldX);
int absVoxelY = Globals.clientWorldData.convertRelativeVoxelToAbsoluteVoxelSpace(voxelY,worldY);
int absVoxelZ = Globals.clientWorldData.convertRelativeVoxelToAbsoluteVoxelSpace(voxelZ,worldZ);
FoliageCell foliageCell = this.getFoliageCell(absVoxelX, absVoxelY, absVoxelZ);
foliageCell.ejectChunkData();
foliageCell.setHasGenerated(false);
foliageCell.setHasRequested(false);
} }
/** /**

View File

@ -137,7 +137,6 @@ public class FoliageModel {
public static Entity clientCreateFoliageChunkEntity( public static Entity clientCreateFoliageChunkEntity(
List<String> foliageTypesSupported, List<String> foliageTypesSupported,
int scale, int scale,
Entity modelEntity,
Vector3d realPos, Vector3d realPos,
Vector3i worldPos, Vector3i worldPos,
Vector3i voxelPos, Vector3i voxelPos,
@ -218,11 +217,17 @@ public class FoliageModel {
QueuedTexture queuedAsset = new QueuedTexture(buffer,textureWidth,textureHeight); QueuedTexture queuedAsset = new QueuedTexture(buffer,textureWidth,textureHeight);
Globals.assetManager.queuedAsset(queuedAsset); Globals.assetManager.queuedAsset(queuedAsset);
TextureInstancedActor.attachTextureInstancedActor(modelEntity, foliageType.getGraphicsTemplate().getModel().getPath(), vertexPath, fragmentPath, queuedAsset, drawCount, textureHeight); TextureInstancedActor.attachTextureInstancedActor(rVal, foliageType.getGraphicsTemplate().getModel().getPath(), vertexPath, fragmentPath, queuedAsset, drawCount, textureHeight);
ClientEntityUtils.initiallyPositionEntity(modelEntity, realPos, new Quaterniond()); ClientEntityUtils.initiallyPositionEntity(rVal, realPos, new Quaterniond());
EntityUtils.getScale(modelEntity).set(1,1,1); EntityUtils.getScale(rVal).set(1,1,1);
//add ambient foliage behavior tree //add ambient foliage behavior tree
AmbientFoliage.attachAmbientFoliageTree(modelEntity, 1.0f, foliageType.getGrowthModel().getGrowthRate()); AmbientFoliage.attachAmbientFoliageTree(rVal, 1.0f, foliageType.getGrowthModel().getGrowthRate());
}
if(toDelete != null){
ClientEntityUtils.destroyEntity(toDelete);
}
if(notifyTarget != null){
notifyTarget.alertToGeneration();
} }
} catch (Error e){ } catch (Error e){
LoggerInterface.loggerEngine.ERROR(e); LoggerInterface.loggerEngine.ERROR(e);

View File

@ -10,6 +10,7 @@ import electrosphere.entity.state.attach.AttachUtils;
import electrosphere.entity.state.hitbox.HitboxCollectionState; import electrosphere.entity.state.hitbox.HitboxCollectionState;
import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.renderer.actor.ActorUtils; import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.actor.instance.TextureInstancedActor;
/** /**
* Client only entity utility functions * Client only entity utility functions
@ -55,6 +56,12 @@ public class ClientEntityUtils {
//deregister all behavior trees //deregister all behavior trees
EntityUtils.cleanUpEntity(entity); EntityUtils.cleanUpEntity(entity);
//instanced actor
if(TextureInstancedActor.getTextureInstancedActor(entity) != null){
TextureInstancedActor actor = TextureInstancedActor.getTextureInstancedActor(entity);
actor.free();
}
if(Globals.clientSceneWrapper != null){ if(Globals.clientSceneWrapper != null){
Globals.clientSceneWrapper.getScene().deregisterEntity(entity); Globals.clientSceneWrapper.getScene().deregisterEntity(entity);
Globals.clientSceneWrapper.deregisterTranslationMapping(entity); Globals.clientSceneWrapper.deregisterTranslationMapping(entity);

View File

@ -107,13 +107,67 @@ public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
// //
//mark all relevant drawcells as updateable //mark all relevant drawcells as updateable
for(Vector3i worldPosToUpdate : positionsToUpdate){ for(Vector3i worldPosToUpdate : positionsToUpdate){
if(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z, ChunkData.NO_STRIDE)){ if(
ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z, ChunkData.NO_STRIDE); worldPosToUpdate.x >= 0 && worldPosToUpdate.x < Globals.clientWorldData.getWorldDiscreteSize() &&
if(data != null){ worldPosToUpdate.y >= 0 && worldPosToUpdate.y < Globals.clientWorldData.getWorldDiscreteSize() &&
Globals.clientDrawCellManager.markUpdateable(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z); worldPosToUpdate.z >= 0 && worldPosToUpdate.z < Globals.clientWorldData.getWorldDiscreteSize()
){
//
//mark terrain chunk for update
Globals.clientDrawCellManager.markUpdateable(worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z);
//
//update foliage manager
Globals.foliageCellManager.markUpdateable(
worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z,
message.getvoxelX(), message.getvoxelY(), message.getvoxelZ()
);
if(message.getvoxelX() > 0){
Globals.foliageCellManager.markUpdateable(
worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z,
message.getvoxelX() - 1, message.getvoxelY(), message.getvoxelZ()
);
if(message.getvoxelY() > 0){
Globals.foliageCellManager.markUpdateable(
worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z,
message.getvoxelX() - 1, message.getvoxelY() - 1, message.getvoxelZ()
);
if(message.getvoxelZ() > 0){
Globals.foliageCellManager.markUpdateable(
worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z,
message.getvoxelX() - 1, message.getvoxelY() - 1, message.getvoxelZ() - 1
);
}
} else {
if(message.getvoxelZ() > 0){
Globals.foliageCellManager.markUpdateable(
worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z,
message.getvoxelX() - 1, message.getvoxelY(), message.getvoxelZ() - 1
);
}
}
} else {
if(message.getvoxelY() > 0){
Globals.foliageCellManager.markUpdateable(
worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z,
message.getvoxelX(), message.getvoxelY() - 1, message.getvoxelZ()
);
if(message.getvoxelZ() > 0){
Globals.foliageCellManager.markUpdateable(
worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z,
message.getvoxelX(), message.getvoxelY() - 1, message.getvoxelZ() - 1
);
}
} else {
if(message.getvoxelZ() > 0){
Globals.foliageCellManager.markUpdateable(
worldPosToUpdate.x, worldPosToUpdate.y, worldPosToUpdate.z,
message.getvoxelX(), message.getvoxelY(), message.getvoxelZ() - 1
);
}
}
} }
} }
// Globals.clientFoliageManager.evaluateChunk(worldPos);
} }
} break; } break;
case SENDFLUIDDATA: { case SENDFLUIDDATA: {

View File

@ -28,13 +28,13 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
public TerrainMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, TerrainMessage message) { public TerrainMessage handleAsyncMessage(ServerConnectionHandler connectionHandler, TerrainMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case REQUESTCHUNKDATA: { case REQUESTCHUNKDATA: {
sendWorldSubChunkAsync(connectionHandler, TerrainProtocol.sendWorldSubChunkAsync(connectionHandler,
message.getworldX(), message.getworldY(), message.getworldZ() message.getworldX(), message.getworldY(), message.getworldZ()
); );
return null; return null;
} }
case REQUESTREDUCEDCHUNKDATA: { case REQUESTREDUCEDCHUNKDATA: {
sendWorldSubChunkAsyncStrided(connectionHandler, TerrainProtocol.sendWorldSubChunkAsyncStrided(connectionHandler,
message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution() message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution()
); );
return null; return null;
@ -49,25 +49,25 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
public void handleSyncMessage(ServerConnectionHandler connectionHandler, TerrainMessage message) { public void handleSyncMessage(ServerConnectionHandler connectionHandler, TerrainMessage message) {
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case REQUESTMETADATA: { case REQUESTMETADATA: {
sendWorldMetadata(connectionHandler); TerrainProtocol.sendWorldMetadata(connectionHandler);
} break; } break;
case REQUESTCHUNKDATA: { case REQUESTCHUNKDATA: {
LoggerInterface.loggerNetworking.DEBUG("(Server) Received request for terrain " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ()); LoggerInterface.loggerNetworking.DEBUG("(Server) Received request for terrain " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ());
// System.out.println("Received request for terrain " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ()); // System.out.println("Received request for terrain " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ());
sendWorldSubChunk(connectionHandler, TerrainProtocol.sendWorldSubChunk(connectionHandler,
message.getworldX(), message.getworldY(), message.getworldZ() message.getworldX(), message.getworldY(), message.getworldZ()
); );
} break; } break;
case REQUESTEDITVOXEL: { case REQUESTEDITVOXEL: {
attemptTerrainEdit(connectionHandler, message); TerrainProtocol.attemptTerrainEdit(connectionHandler, message);
} break; } break;
case REQUESTUSETERRAINPALETTE: { case REQUESTUSETERRAINPALETTE: {
attemptUseTerrainEditPalette(connectionHandler, message); TerrainProtocol.attemptUseTerrainEditPalette(connectionHandler, message);
} break; } break;
case REQUESTFLUIDDATA: { case REQUESTFLUIDDATA: {
LoggerInterface.loggerNetworking.DEBUG("(Server) Received request for fluid " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ()); LoggerInterface.loggerNetworking.DEBUG("(Server) Received request for fluid " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ());
// System.out.println("Received request for fluid " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ()); // System.out.println("Received request for fluid " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ());
sendWorldFluidSubChunk(connectionHandler, TerrainProtocol.sendWorldFluidSubChunk(connectionHandler,
message.getworldX(), message.getworldY(), message.getworldZ() message.getworldX(), message.getworldY(), message.getworldZ()
); );
} break; } break;

View File

@ -185,4 +185,13 @@ public class TextureInstancedActor {
model.setWorldPos(worldPos); model.setWorldPos(worldPos);
} }
} }
/**
* Frees the texture instanced actor
*/
public void free(){
if(this.queuedTexture != null && this.queuedTexture.getTexture() != null){
Globals.assetManager.queueTextureForDeletion(this.queuedTexture.getTexture().getPath());
}
}
} }

View File

@ -653,8 +653,6 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
*/ */
public void editChunk(Vector3i worldPosition, Vector3i voxelPosition, float weight, int type) { public void editChunk(Vector3i worldPosition, Vector3i voxelPosition, float weight, int type) {
terrainEditLock.acquireUninterruptibly(); terrainEditLock.acquireUninterruptibly();
//update terrain
serverTerrainManager.deformTerrainAtLocationToValue(worldPosition, voxelPosition, weight, type);
List<Vector3i> worldPositionsToUpdate = new LinkedList<Vector3i>(); List<Vector3i> worldPositionsToUpdate = new LinkedList<Vector3i>();
worldPositionsToUpdate.add(worldPosition); worldPositionsToUpdate.add(worldPosition);
if(voxelPosition.x < 1){ if(voxelPosition.x < 1){
@ -664,32 +662,45 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
if(voxelPosition.z < 1){ if(voxelPosition.z < 1){
worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(1,1,1)); worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(1,1,1));
} }
} else {
if(voxelPosition.z < 1){
worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(1,0,1));
}
} }
} else { if(voxelPosition.z < 1){
if(voxelPosition.y < 1){ worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(1,0,1));
worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,1,0));
if(voxelPosition.z < 1){
worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,1,1));
}
} else {
if(voxelPosition.z < 1){
worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,0,1));
}
} }
} }
if(voxelPosition.y < 1){
worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,1,0));
if(voxelPosition.z < 1){
worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,1,1));
}
}
if(voxelPosition.z < 1){
worldPositionsToUpdate.add(new Vector3i(worldPosition).sub(0,0,1));
}
//update all loaded cells //update all loaded cells
for(Vector3i toUpdate : worldPositionsToUpdate){ for(Vector3i toUpdate : worldPositionsToUpdate){
ServerDataCell cell = groundDataCells.get(getServerDataCellKey(toUpdate)); if(
if(cell != null){ toUpdate.x >= 0 && toUpdate.x < this.serverWorldData.getWorldSizeDiscrete() &&
this.createTerrainPhysicsEntities(toUpdate); toUpdate.y >= 0 && toUpdate.y < this.serverWorldData.getWorldSizeDiscrete() &&
cell.broadcastNetworkMessage(TerrainMessage.constructUpdateVoxelMessage( toUpdate.z >= 0 && toUpdate.z < this.serverWorldData.getWorldSizeDiscrete()
worldPosition.x, worldPosition.y, worldPosition.z, ){
voxelPosition.x, voxelPosition.y, voxelPosition.z, //update terrain
weight, type)); int localVoxelX = voxelPosition.x + (ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1) * (worldPosition.x - toUpdate.x);
int localVoxelY = voxelPosition.y + (ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1) * (worldPosition.y - toUpdate.y);
int localVoxelZ = voxelPosition.z + (ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1) * (worldPosition.z - toUpdate.z);
serverTerrainManager.deformTerrainAtLocationToValue(toUpdate, new Vector3i(localVoxelX, localVoxelY, localVoxelZ), weight, type);
//update anything loaded
ServerDataCell cell = groundDataCells.get(this.getServerDataCellKey(toUpdate));
if(cell != null){
//update physics
this.createTerrainPhysicsEntities(toUpdate);
//broadcast update
cell.broadcastNetworkMessage(TerrainMessage.constructUpdateVoxelMessage(
toUpdate.x, toUpdate.y, toUpdate.z,
localVoxelX, localVoxelY, localVoxelZ,
weight, type));
}
} }
} }
terrainEditLock.release(); terrainEditLock.release();

View File

@ -223,7 +223,7 @@ public class WorldOctTree <T> {
){ ){
throw new Error("Trying to search for node outside tree range!"); throw new Error("Trying to search for node outside tree range!");
} }
WorldOctTreeNode<T> searchResult = recursiveSearchUnsafe(root,position,maxLevel); WorldOctTreeNode<T> searchResult = this.recursiveSearchUnsafe(root,position,maxLevel);
if(!returnNonLeaf && !searchResult.isLeaf()){ if(!returnNonLeaf && !searchResult.isLeaf()){
return null; return null;
} }