ServerBlockManager places structures
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
69b7fe2f77
commit
12e95dc2b8
@ -1588,6 +1588,7 @@ Fab selection doesn't overflow anymore
|
|||||||
Cleaning up parts of Main class
|
Cleaning up parts of Main class
|
||||||
Spawn test structure in macro data on creation
|
Spawn test structure in macro data on creation
|
||||||
Macro data structures block regular foliage generation
|
Macro data structures block regular foliage generation
|
||||||
|
ServerBlockManager places macro data structures when generating chunks that contain them
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -149,6 +149,10 @@ public class SceneLoader {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//hook up macro data if relevant
|
||||||
|
if(macroData != null){
|
||||||
|
realm.getServerWorldData().getServerBlockManager().setMacroData(macroData);
|
||||||
|
}
|
||||||
//load scripts
|
//load scripts
|
||||||
if(!isLevelEditor && file.getInitScriptPath() != null){
|
if(!isLevelEditor && file.getInitScriptPath() != null){
|
||||||
Realm finalRealm = realm;
|
Realm finalRealm = realm;
|
||||||
|
|||||||
@ -211,6 +211,12 @@ public class BlockFab implements BlockMeshgenData {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short getType(int x, int y, int z) {
|
public short getType(int x, int y, int z) {
|
||||||
|
if(x < 0 || y < 0 || z < 0){
|
||||||
|
throw new Error("Negative bounds! " + x + " " + y + " " + z);
|
||||||
|
}
|
||||||
|
if(x >= dimensions.x || y >= dimensions.y || z >= dimensions.z){
|
||||||
|
throw new Error("Out of bounds! " + x + " " + y + " " + z);
|
||||||
|
}
|
||||||
return this.types[x * dimensions.y * dimensions.z + y * dimensions.z + z];
|
return this.types[x * dimensions.y * dimensions.z + y * dimensions.z + z];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -228,6 +228,21 @@ public class ServerWorldData {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a chunk space position to a real space position
|
||||||
|
* @param x the x coordinate
|
||||||
|
* @param y the y coordinate
|
||||||
|
* @param z the z coordinate
|
||||||
|
* @return The real space position
|
||||||
|
*/
|
||||||
|
public static Vector3d convertChunkToRealSpace(int x, int y, int z){
|
||||||
|
return new Vector3d(
|
||||||
|
ServerWorldData.convertChunkToRealSpace(x),
|
||||||
|
ServerWorldData.convertChunkToRealSpace(y),
|
||||||
|
ServerWorldData.convertChunkToRealSpace(z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a real position to a local block grid position
|
* Converts a real position to a local block grid position
|
||||||
* @param real The real position
|
* @param real The real position
|
||||||
@ -237,6 +252,30 @@ public class ServerWorldData {
|
|||||||
return (int)Math.floor(real * BlockChunkData.BLOCKS_PER_UNIT_DISTANCE % BlockChunkData.CHUNK_DATA_WIDTH);
|
return (int)Math.floor(real * BlockChunkData.BLOCKS_PER_UNIT_DISTANCE % BlockChunkData.CHUNK_DATA_WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a local block grid position to a real position
|
||||||
|
* @param chunk The chunk pos
|
||||||
|
* @param blockPos The block's local pos
|
||||||
|
* @return The real position
|
||||||
|
*/
|
||||||
|
public static double convertLocalBlockToRealSpace(int chunk, int blockPos){
|
||||||
|
return ServerWorldData.convertChunkToRealSpace(chunk + blockPos / BlockChunkData.CHUNK_DATA_WIDTH) + (blockPos % BlockChunkData.CHUNK_DATA_WIDTH) * BlockChunkData.BLOCK_SIZE_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a local block grid position to a real position
|
||||||
|
* @param chunk The chunk pos
|
||||||
|
* @param blockPos The block's local pos
|
||||||
|
* @return The real position
|
||||||
|
*/
|
||||||
|
public static Vector3d convertLocalBlockToRealSpace(Vector3i chunk, Vector3i blockPos){
|
||||||
|
return new Vector3d(
|
||||||
|
ServerWorldData.convertLocalBlockToRealSpace(chunk.x, blockPos.x),
|
||||||
|
ServerWorldData.convertLocalBlockToRealSpace(chunk.y, blockPos.y),
|
||||||
|
ServerWorldData.convertLocalBlockToRealSpace(chunk.z, blockPos.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a chunk space coordinate to a real space coordinate
|
* Converts a chunk space coordinate to a real space coordinate
|
||||||
* @param chunk The position within the chunk
|
* @param chunk The position within the chunk
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
package electrosphere.server.macro;
|
package electrosphere.server.macro;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import electrosphere.game.data.block.BlockFab;
|
||||||
|
import electrosphere.server.macro.structure.Structure;
|
||||||
import electrosphere.util.FileUtils;
|
import electrosphere.util.FileUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,6 +18,18 @@ public class MacroDataLoader {
|
|||||||
*/
|
*/
|
||||||
public static MacroData loadFromSave(String saveName){
|
public static MacroData loadFromSave(String saveName){
|
||||||
MacroData rVal = FileUtils.loadObjectFromSavePath(saveName, "macro.json", MacroData.class);
|
MacroData rVal = FileUtils.loadObjectFromSavePath(saveName, "macro.json", MacroData.class);
|
||||||
|
//preload and assign structure fabs
|
||||||
|
for(Structure structure : rVal.getStructures()){
|
||||||
|
File fabFile = FileUtils.getAssetFile(structure.getFabPath());
|
||||||
|
if(!fabFile.exists()){
|
||||||
|
throw new Error("Failed to locate structure that does not exist! " + fabFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
BlockFab fab = BlockFab.read(fabFile);
|
||||||
|
if(fab == null){
|
||||||
|
throw new Error("Failed to read fab!");
|
||||||
|
}
|
||||||
|
structure.setFab(fab);
|
||||||
|
}
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,12 @@ import java.util.List;
|
|||||||
import org.joml.AABBd;
|
import org.joml.AABBd;
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
import electrosphere.game.data.block.BlockFab;
|
||||||
import electrosphere.game.data.struct.StructureData;
|
import electrosphere.game.data.struct.StructureData;
|
||||||
import electrosphere.server.macro.character.CharacterData;
|
import electrosphere.server.macro.character.CharacterData;
|
||||||
import electrosphere.server.macro.character.CharacterDataStrings;
|
import electrosphere.server.macro.character.CharacterDataStrings;
|
||||||
import electrosphere.server.macro.spatial.MacroAreaObject;
|
import electrosphere.server.macro.spatial.MacroAreaObject;
|
||||||
|
import electrosphere.util.annotation.Exclude;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server representation of a structure
|
* Server representation of a structure
|
||||||
@ -32,6 +34,12 @@ public class Structure extends CharacterData implements MacroAreaObject {
|
|||||||
*/
|
*/
|
||||||
String fabPath;
|
String fabPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual fab
|
||||||
|
*/
|
||||||
|
@Exclude
|
||||||
|
BlockFab fab;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the structure
|
* The type of the structure
|
||||||
*/
|
*/
|
||||||
@ -135,6 +143,29 @@ public class Structure extends CharacterData implements MacroAreaObject {
|
|||||||
return this.aabb;
|
return this.aabb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the path to the corresponding fab
|
||||||
|
* @return The path
|
||||||
|
*/
|
||||||
|
public String getFabPath(){
|
||||||
|
return fabPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the fab object
|
||||||
|
* @return The fab object
|
||||||
|
*/
|
||||||
|
public BlockFab getFab() {
|
||||||
|
return fab;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the fab object
|
||||||
|
* @param fab The fab object
|
||||||
|
*/
|
||||||
|
public void setFab(BlockFab fab) {
|
||||||
|
this.fab = fab;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,21 @@
|
|||||||
package electrosphere.server.physics.block.manager;
|
package electrosphere.server.physics.block.manager;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.joml.AABBd;
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
import org.joml.Vector3i;
|
||||||
|
|
||||||
import electrosphere.client.block.BlockChunkCache;
|
import electrosphere.client.block.BlockChunkCache;
|
||||||
import electrosphere.client.block.BlockChunkData;
|
import electrosphere.client.block.BlockChunkData;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
import electrosphere.server.datacell.ServerWorldData;
|
||||||
|
import electrosphere.server.macro.MacroData;
|
||||||
|
import electrosphere.server.macro.structure.Structure;
|
||||||
import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
|
import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,6 +43,11 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
*/
|
*/
|
||||||
BlockChunkCache chunkCache;
|
BlockChunkCache chunkCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The macro data
|
||||||
|
*/
|
||||||
|
MacroData macroData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The world x coordinate
|
* The world x coordinate
|
||||||
*/
|
*/
|
||||||
@ -61,6 +75,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the chunk generation job
|
* Creates the chunk generation job
|
||||||
|
* @param macroData The macro data
|
||||||
* @param chunkDiskMap The chunk disk map
|
* @param chunkDiskMap The chunk disk map
|
||||||
* @param chunkCache The chunk cache on the server
|
* @param chunkCache The chunk cache on the server
|
||||||
* @param worldX The world x coordinate
|
* @param worldX The world x coordinate
|
||||||
@ -70,6 +85,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
* @param onLoad The work to do once the chunk is available
|
* @param onLoad The work to do once the chunk is available
|
||||||
*/
|
*/
|
||||||
public ServerBlockChunkGenerationThread(
|
public ServerBlockChunkGenerationThread(
|
||||||
|
MacroData macroData,
|
||||||
ServerBlockChunkDiskMap chunkDiskMap,
|
ServerBlockChunkDiskMap chunkDiskMap,
|
||||||
BlockChunkCache chunkCache,
|
BlockChunkCache chunkCache,
|
||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
@ -83,6 +99,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
this.worldZ = worldZ;
|
this.worldZ = worldZ;
|
||||||
this.stride = stride;
|
this.stride = stride;
|
||||||
this.onLoad = onLoad;
|
this.onLoad = onLoad;
|
||||||
|
this.macroData = macroData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -102,19 +119,12 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
}
|
}
|
||||||
//generate if it does not exist
|
//generate if it does not exist
|
||||||
if(chunk == null){
|
if(chunk == null){
|
||||||
//TODO: generate from macro-level data
|
|
||||||
chunk = BlockChunkData.allocate();
|
chunk = BlockChunkData.allocate();
|
||||||
chunk.setHomogenousValue(0);
|
chunk.setWorldX(worldX);
|
||||||
// if(worldX == 0 && worldY == 0 && worldZ == 0){
|
chunk.setWorldY(worldY);
|
||||||
// chunk.setHomogenousValue(BlockChunkData.NOT_HOMOGENOUS);
|
chunk.setWorldZ(worldZ);
|
||||||
// for(int x = 0; x < 16; x++){
|
|
||||||
// for(int y = 0; y < 16; y++){
|
ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ);
|
||||||
// for(int z = 0; z < 16; z++){
|
|
||||||
// chunk.setType(x, y, z, 1);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
if(chunk != null){
|
if(chunk != null){
|
||||||
chunkCache.add(worldX, worldY, worldZ, stride, chunk);
|
chunkCache.add(worldX, worldY, worldZ, stride, chunk);
|
||||||
@ -140,4 +150,59 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the actual values of the chunk
|
||||||
|
* @param chunk THe chunk
|
||||||
|
* @param macroData The macro data
|
||||||
|
* @param worldX THe world x coordinate
|
||||||
|
* @param worldY The world y coordinate
|
||||||
|
* @param worldZ The world z coordinate
|
||||||
|
*/
|
||||||
|
protected static void generate(BlockChunkData chunk, MacroData macroData, int worldX, int worldY, int worldZ){
|
||||||
|
//check if this chunk intersects any macro data
|
||||||
|
AABBd localAABB = new AABBd(ServerWorldData.convertChunkToRealSpace(worldX,worldY,worldZ),ServerWorldData.convertChunkToRealSpace(worldX+1,worldY+1,worldZ+1));
|
||||||
|
List<Structure> filtered = macroData.getStructures().stream().filter((Structure struct) -> {return struct.getAABB().testAABB(localAABB);}).collect(Collectors.toList());
|
||||||
|
if(filtered.size() > 0){
|
||||||
|
Vector3i chunkPos = new Vector3i(worldX, worldY, worldZ);
|
||||||
|
Vector3i blockPos = new Vector3i(0,0,0);
|
||||||
|
Vector3d chunkRealPos = ServerWorldData.convertChunkToRealSpace(chunkPos);
|
||||||
|
Vector3i localBlockPos = new Vector3i();
|
||||||
|
//contains at least one structure
|
||||||
|
for(int x = 0; x < BlockChunkData.CHUNK_DATA_WIDTH; x++){
|
||||||
|
for(int y = 0; y < BlockChunkData.CHUNK_DATA_WIDTH; y++){
|
||||||
|
for(int z = 0; z < BlockChunkData.CHUNK_DATA_WIDTH; z++){
|
||||||
|
boolean placedBlock = false;
|
||||||
|
|
||||||
|
//try placing a structure block
|
||||||
|
blockPos.set(x,y,z);
|
||||||
|
Vector3d currRealPoint = ServerWorldData.convertLocalBlockToRealSpace(chunkPos, blockPos);
|
||||||
|
for(Structure struct : filtered){
|
||||||
|
if(struct.getAABB().testPoint(currRealPoint.x, currRealPoint.y, currRealPoint.z)){
|
||||||
|
localBlockPos.set(
|
||||||
|
(int)((chunkRealPos.x + (x * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - struct.getStartPos().x) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
|
||||||
|
(int)((chunkRealPos.y + (y * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - struct.getStartPos().y) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
|
||||||
|
(int)((chunkRealPos.z + (z * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - struct.getStartPos().z) / BlockChunkData.BLOCK_SIZE_MULTIPLIER)
|
||||||
|
);
|
||||||
|
//structure file might have dimensions larger than fab, so need to make sure we're inbounds on fab file to draw data from fab file
|
||||||
|
if(localBlockPos.x < struct.getFab().getDimensions().x && localBlockPos.y < struct.getFab().getDimensions().y && localBlockPos.z < struct.getFab().getDimensions().z){
|
||||||
|
short blocktype = struct.getFab().getType(localBlockPos.x,localBlockPos.y,localBlockPos.z);
|
||||||
|
chunk.setType(x, y, z, blocktype);
|
||||||
|
placedBlock = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if failed to place structure block, place an empty block
|
||||||
|
if(!placedBlock){
|
||||||
|
chunk.setType(x, y, z, BlockChunkData.BLOCK_TYPE_EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//an empty chunk (no structures inside)
|
||||||
|
chunk.setHomogenousValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import electrosphere.client.block.BlockChunkCache;
|
|||||||
import electrosphere.client.block.BlockChunkData;
|
import electrosphere.client.block.BlockChunkData;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.server.datacell.ServerWorldData;
|
import electrosphere.server.datacell.ServerWorldData;
|
||||||
|
import electrosphere.server.macro.MacroData;
|
||||||
import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
|
import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
|
||||||
import electrosphere.util.annotation.Exclude;
|
import electrosphere.util.annotation.Exclude;
|
||||||
|
|
||||||
@ -39,6 +40,12 @@ public class ServerBlockManager {
|
|||||||
*/
|
*/
|
||||||
ServerBlockChunkDiskMap chunkDiskMap = null;
|
ServerBlockChunkDiskMap chunkDiskMap = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The macro data for this world
|
||||||
|
*/
|
||||||
|
@Exclude
|
||||||
|
MacroData macroData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The threadpool for chunk generation
|
* The threadpool for chunk generation
|
||||||
*/
|
*/
|
||||||
@ -120,17 +127,7 @@ public class ServerBlockManager {
|
|||||||
returnedChunk.setWorldX(worldX);
|
returnedChunk.setWorldX(worldX);
|
||||||
returnedChunk.setWorldY(worldY);
|
returnedChunk.setWorldY(worldY);
|
||||||
returnedChunk.setWorldZ(worldZ);
|
returnedChunk.setWorldZ(worldZ);
|
||||||
returnedChunk.setHomogenousValue(0);
|
ServerBlockChunkGenerationThread.generate(returnedChunk, macroData, worldX, worldY, worldZ);
|
||||||
// if(worldX == 0 && worldY == 0 && worldZ == 0){
|
|
||||||
// returnedChunk.setHomogenousValue(BlockChunkData.NOT_HOMOGENOUS);
|
|
||||||
// for(int x = 3; x < 16; x++){
|
|
||||||
// for(int y = 8; y < 16; y++){
|
|
||||||
// for(int z = 3; z < 16; z++){
|
|
||||||
// returnedChunk.setType(x, y, z, 1);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
this.chunkCache.add(worldX, worldY, worldZ, BlockChunkData.LOD_FULL_RES, returnedChunk);
|
this.chunkCache.add(worldX, worldY, worldZ, BlockChunkData.LOD_FULL_RES, returnedChunk);
|
||||||
}
|
}
|
||||||
@ -148,7 +145,7 @@ public class ServerBlockManager {
|
|||||||
*/
|
*/
|
||||||
public void getChunkAsync(int worldX, int worldY, int worldZ, int stride, Consumer<BlockChunkData> onLoad){
|
public void getChunkAsync(int worldX, int worldY, int worldZ, int stride, Consumer<BlockChunkData> onLoad){
|
||||||
Globals.profiler.beginAggregateCpuSample("ServerBlockManager.getChunkAsync");
|
Globals.profiler.beginAggregateCpuSample("ServerBlockManager.getChunkAsync");
|
||||||
chunkExecutorService.submit(new ServerBlockChunkGenerationThread(chunkDiskMap, chunkCache, worldX, worldY, worldZ, stride, onLoad));
|
chunkExecutorService.submit(new ServerBlockChunkGenerationThread(this.macroData, chunkDiskMap, chunkCache, worldX, worldY, worldZ, stride, onLoad));
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,4 +191,12 @@ public class ServerBlockManager {
|
|||||||
chunkExecutorService.shutdownNow();
|
chunkExecutorService.shutdownNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the macro data for the block manager
|
||||||
|
* @param macroData The macro data
|
||||||
|
*/
|
||||||
|
public void setMacroData(MacroData macroData){
|
||||||
|
this.macroData = macroData;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user