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
|
||||
Spawn test structure in macro data on creation
|
||||
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();
|
||||
}
|
||||
}
|
||||
//hook up macro data if relevant
|
||||
if(macroData != null){
|
||||
realm.getServerWorldData().getServerBlockManager().setMacroData(macroData);
|
||||
}
|
||||
//load scripts
|
||||
if(!isLevelEditor && file.getInitScriptPath() != null){
|
||||
Realm finalRealm = realm;
|
||||
|
||||
@ -211,6 +211,12 @@ public class BlockFab implements BlockMeshgenData {
|
||||
|
||||
@Override
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param chunk The position within the chunk
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
package electrosphere.server.macro;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import electrosphere.game.data.block.BlockFab;
|
||||
import electrosphere.server.macro.structure.Structure;
|
||||
import electrosphere.util.FileUtils;
|
||||
|
||||
/**
|
||||
@ -14,6 +18,18 @@ public class MacroDataLoader {
|
||||
*/
|
||||
public static MacroData loadFromSave(String saveName){
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -7,10 +7,12 @@ import java.util.List;
|
||||
import org.joml.AABBd;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.game.data.block.BlockFab;
|
||||
import electrosphere.game.data.struct.StructureData;
|
||||
import electrosphere.server.macro.character.CharacterData;
|
||||
import electrosphere.server.macro.character.CharacterDataStrings;
|
||||
import electrosphere.server.macro.spatial.MacroAreaObject;
|
||||
import electrosphere.util.annotation.Exclude;
|
||||
|
||||
/**
|
||||
* Server representation of a structure
|
||||
@ -31,6 +33,12 @@ public class Structure extends CharacterData implements MacroAreaObject {
|
||||
* The path to the block fab for the structure
|
||||
*/
|
||||
String fabPath;
|
||||
|
||||
/**
|
||||
* The actual fab
|
||||
*/
|
||||
@Exclude
|
||||
BlockFab fab;
|
||||
|
||||
/**
|
||||
* The type of the structure
|
||||
@ -134,7 +142,30 @@ public class Structure extends CharacterData implements MacroAreaObject {
|
||||
public AABBd getAABB() {
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
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.BlockChunkData;
|
||||
import electrosphere.engine.Globals;
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -34,6 +43,11 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
||||
*/
|
||||
BlockChunkCache chunkCache;
|
||||
|
||||
/**
|
||||
* The macro data
|
||||
*/
|
||||
MacroData macroData;
|
||||
|
||||
/**
|
||||
* The world x coordinate
|
||||
*/
|
||||
@ -61,6 +75,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
||||
|
||||
/**
|
||||
* Creates the chunk generation job
|
||||
* @param macroData The macro data
|
||||
* @param chunkDiskMap The chunk disk map
|
||||
* @param chunkCache The chunk cache on the server
|
||||
* @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
|
||||
*/
|
||||
public ServerBlockChunkGenerationThread(
|
||||
MacroData macroData,
|
||||
ServerBlockChunkDiskMap chunkDiskMap,
|
||||
BlockChunkCache chunkCache,
|
||||
int worldX, int worldY, int worldZ,
|
||||
@ -83,6 +99,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
||||
this.worldZ = worldZ;
|
||||
this.stride = stride;
|
||||
this.onLoad = onLoad;
|
||||
this.macroData = macroData;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -102,19 +119,12 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
||||
}
|
||||
//generate if it does not exist
|
||||
if(chunk == null){
|
||||
//TODO: generate from macro-level data
|
||||
chunk = BlockChunkData.allocate();
|
||||
chunk.setHomogenousValue(0);
|
||||
// if(worldX == 0 && worldY == 0 && worldZ == 0){
|
||||
// chunk.setHomogenousValue(BlockChunkData.NOT_HOMOGENOUS);
|
||||
// for(int x = 0; x < 16; x++){
|
||||
// for(int y = 0; y < 16; y++){
|
||||
// for(int z = 0; z < 16; z++){
|
||||
// chunk.setType(x, y, z, 1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
chunk.setWorldX(worldX);
|
||||
chunk.setWorldY(worldY);
|
||||
chunk.setWorldZ(worldZ);
|
||||
|
||||
ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ);
|
||||
}
|
||||
if(chunk != null){
|
||||
chunkCache.add(worldX, worldY, worldZ, stride, chunk);
|
||||
@ -139,5 +149,60 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
||||
LoggerInterface.loggerEngine.ERROR(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.engine.Globals;
|
||||
import electrosphere.server.datacell.ServerWorldData;
|
||||
import electrosphere.server.macro.MacroData;
|
||||
import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
|
||||
import electrosphere.util.annotation.Exclude;
|
||||
|
||||
@ -39,11 +40,17 @@ public class ServerBlockManager {
|
||||
*/
|
||||
ServerBlockChunkDiskMap chunkDiskMap = null;
|
||||
|
||||
/**
|
||||
* The macro data for this world
|
||||
*/
|
||||
@Exclude
|
||||
MacroData macroData;
|
||||
|
||||
/**
|
||||
* The threadpool for chunk generation
|
||||
*/
|
||||
@Exclude
|
||||
static final ExecutorService chunkExecutorService = Executors.newFixedThreadPool(GENERATION_THREAD_POOL_SIZE);
|
||||
static final ExecutorService chunkExecutorService = Executors.newFixedThreadPool(GENERATION_THREAD_POOL_SIZE);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -120,17 +127,7 @@ public class ServerBlockManager {
|
||||
returnedChunk.setWorldX(worldX);
|
||||
returnedChunk.setWorldY(worldY);
|
||||
returnedChunk.setWorldZ(worldZ);
|
||||
returnedChunk.setHomogenousValue(0);
|
||||
// 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);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
ServerBlockChunkGenerationThread.generate(returnedChunk, macroData, worldX, worldY, worldZ);
|
||||
}
|
||||
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){
|
||||
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();
|
||||
}
|
||||
|
||||
@ -194,4 +191,12 @@ public class ServerBlockManager {
|
||||
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