block chunks properly stride
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
456036c0d2
commit
086c6da72e
@ -1948,6 +1948,7 @@ Small fixes
|
|||||||
(05/23/2025)
|
(05/23/2025)
|
||||||
Town layout work
|
Town layout work
|
||||||
Macro broadphase filters prior to per-voxel macro data intersection checks
|
Macro broadphase filters prior to per-voxel macro data intersection checks
|
||||||
|
Block chunks properly stride
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -30,64 +30,68 @@ public class BlockDrawCell {
|
|||||||
/**
|
/**
|
||||||
* Number of child cells per parent cell
|
* Number of child cells per parent cell
|
||||||
*/
|
*/
|
||||||
static final int CHILD_CELLS_PER_PARENT = 8;
|
private static final int CHILD_CELLS_PER_PARENT = 8;
|
||||||
|
|
||||||
//the position of the draw cell in world coordinates
|
/**
|
||||||
Vector3i worldPos;
|
* the position of the draw cell in world coordinates
|
||||||
|
*/
|
||||||
|
private Vector3i worldPos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The LOD of the draw cell
|
* The LOD of the draw cell
|
||||||
*/
|
*/
|
||||||
int lod;
|
protected int lod;
|
||||||
|
|
||||||
//the main entity for the cell
|
/**
|
||||||
List<Entity> modelEntities = new LinkedList<Entity>();
|
* the main entity for the cell
|
||||||
|
*/
|
||||||
|
private List<Entity> modelEntities = new LinkedList<Entity>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data for generating the visuals
|
* The data for generating the visuals
|
||||||
*/
|
*/
|
||||||
BlockChunkData chunkData;
|
private BlockChunkData chunkData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks whether the draw cell has requested its chunk data or not
|
* Tracks whether the draw cell has requested its chunk data or not
|
||||||
*/
|
*/
|
||||||
boolean hasRequested = false;
|
private boolean hasRequested = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks whether the draw cell has generated its entity or not
|
* Tracks whether the draw cell has generated its entity or not
|
||||||
*/
|
*/
|
||||||
boolean hasGenerated = false;
|
private boolean hasGenerated = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks whether this draw cell is flagged as homogenous from the server or not
|
* Tracks whether this draw cell is flagged as homogenous from the server or not
|
||||||
*/
|
*/
|
||||||
boolean homogenous = false;
|
private boolean homogenous = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of failed generation attempts
|
* Number of failed generation attempts
|
||||||
*/
|
*/
|
||||||
int failedGenerationAttempts = 0;
|
private int failedGenerationAttempts = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Labels an invalid distance cache
|
* Labels an invalid distance cache
|
||||||
*/
|
*/
|
||||||
static final int INVALID_DIST_CACHE = -1;
|
private static final int INVALID_DIST_CACHE = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cached minimum distance
|
* The cached minimum distance
|
||||||
*/
|
*/
|
||||||
long cachedMinDistance = -1;
|
private long cachedMinDistance = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target to notify on generation completion
|
* Target to notify on generation completion
|
||||||
*/
|
*/
|
||||||
BlockDrawCell notifyTarget = null;
|
private BlockDrawCell notifyTarget = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of cells that have alerted this one
|
* The number of cells that have alerted this one
|
||||||
*/
|
*/
|
||||||
int generationAlertCount = 0;
|
private int generationAlertCount = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -480,7 +480,7 @@ public class CursorState {
|
|||||||
public void setSelectedFab(BlockFab fab){
|
public void setSelectedFab(BlockFab fab){
|
||||||
Map<Integer,Boolean> solidsMap = Globals.gameConfigCurrent.getBlockData().getSolidsMap();
|
Map<Integer,Boolean> solidsMap = Globals.gameConfigCurrent.getBlockData().getSolidsMap();
|
||||||
QueuedModel queuedModel = new QueuedModel(() -> {
|
QueuedModel queuedModel = new QueuedModel(() -> {
|
||||||
return BlockMeshgen.generateBlockModel(BlockMeshgen.rasterize(fab,false,solidsMap));
|
return BlockMeshgen.generateBlockModel(BlockMeshgen.rasterize(fab,false,solidsMap,BlockMeshgen.DEFAULT_SCALING_FACTOR));
|
||||||
});
|
});
|
||||||
Globals.assetManager.queuedAsset(queuedModel);
|
Globals.assetManager.queuedAsset(queuedModel);
|
||||||
EntityCreationUtils.makeEntityDrawablePreexistingModel(playerFabCursor, queuedModel.getPromisedPath());
|
EntityCreationUtils.makeEntityDrawablePreexistingModel(playerFabCursor, queuedModel.getPromisedPath());
|
||||||
|
|||||||
@ -71,7 +71,7 @@ public class BlockChunkEntity {
|
|||||||
generationService.submit(() -> {
|
generationService.submit(() -> {
|
||||||
BlockMeshData data;
|
BlockMeshData data;
|
||||||
try {
|
try {
|
||||||
data = BlockMeshgen.rasterize(chunkData, true, solidsMap);
|
data = BlockMeshgen.rasterize(chunkData, true, solidsMap,(int)Math.pow(2,levelOfDetail));
|
||||||
if(Globals.clientState.clientScene.containsEntity(solidsEnt) && data.getFaceElements().length > 0){
|
if(Globals.clientState.clientScene.containsEntity(solidsEnt) && data.getFaceElements().length > 0){
|
||||||
String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> {
|
String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> {
|
||||||
return BlockMeshgen.generateBlockModel(data);
|
return BlockMeshgen.generateBlockModel(data);
|
||||||
@ -122,7 +122,7 @@ public class BlockChunkEntity {
|
|||||||
generationService.submit(() -> {
|
generationService.submit(() -> {
|
||||||
BlockMeshData data;
|
BlockMeshData data;
|
||||||
try {
|
try {
|
||||||
data = BlockMeshgen.rasterize(chunkData, false, solidsMap);
|
data = BlockMeshgen.rasterize(chunkData, false, solidsMap, (int)Math.pow(2,levelOfDetail));
|
||||||
if(Globals.clientState.clientScene.containsEntity(transparentEnt) && data.getFaceElements().length > 0){
|
if(Globals.clientState.clientScene.containsEntity(transparentEnt) && data.getFaceElements().length > 0){
|
||||||
String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> {
|
String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> {
|
||||||
return BlockMeshgen.generateBlockModel(data);
|
return BlockMeshgen.generateBlockModel(data);
|
||||||
|
|||||||
@ -334,7 +334,7 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
|
|||||||
* @param worldZ the world z
|
* @param worldZ the world z
|
||||||
* @param stride The stride of the data
|
* @param stride The stride of the data
|
||||||
*/
|
*/
|
||||||
static void sendBlocksAsyncStrided(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ, int stride){
|
private static void sendBlocksAsyncStrided(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ, int stride){
|
||||||
Globals.profiler.beginAggregateCpuSample("TerrainProtocol(server).sendWorldSubChunk");
|
Globals.profiler.beginAggregateCpuSample("TerrainProtocol(server).sendWorldSubChunk");
|
||||||
|
|
||||||
// System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY());
|
// System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY());
|
||||||
|
|||||||
@ -66,6 +66,11 @@ public class BlockMeshgen {
|
|||||||
*/
|
*/
|
||||||
static final int SAMPLER_DATA_SIZE = 1;
|
static final int SAMPLER_DATA_SIZE = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default scaling factor
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_SCALING_FACTOR = 1;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether this block should be rasterized or not
|
* Checks whether this block should be rasterized or not
|
||||||
@ -394,9 +399,10 @@ public class BlockMeshgen {
|
|||||||
* @param chunkData The block chunk data
|
* @param chunkData The block chunk data
|
||||||
* @param solids true to rasterize solid blocks, false to rasterize transparent blocks
|
* @param solids true to rasterize solid blocks, false to rasterize transparent blocks
|
||||||
* @param solidsMap The solids map
|
* @param solidsMap The solids map
|
||||||
|
* @param scalingFactor Scaling applied to the verts
|
||||||
* @return The mesh data
|
* @return The mesh data
|
||||||
*/
|
*/
|
||||||
public static BlockMeshData rasterize(BlockMeshgenData chunkData, boolean solids, Map<Integer,Boolean> solidsMap){
|
public static BlockMeshData rasterize(BlockMeshgenData chunkData, boolean solids, Map<Integer,Boolean> solidsMap, int scalingFactor){
|
||||||
BlockMeshData rVal = new BlockMeshData();
|
BlockMeshData rVal = new BlockMeshData();
|
||||||
|
|
||||||
//calculate quad meshes
|
//calculate quad meshes
|
||||||
@ -447,7 +453,7 @@ public class BlockMeshgen {
|
|||||||
lastFaceCount = indices.size();
|
lastFaceCount = indices.size();
|
||||||
rVal.shapeData.add(blockSingleShape);
|
rVal.shapeData.add(blockSingleShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//store in flat arrays
|
//store in flat arrays
|
||||||
//
|
//
|
||||||
@ -456,9 +462,9 @@ public class BlockMeshgen {
|
|||||||
rVal.vertices = new float[verts.size() * 3];
|
rVal.vertices = new float[verts.size() * 3];
|
||||||
for(int i = 0; i < verts.size(); i++){
|
for(int i = 0; i < verts.size(); i++){
|
||||||
Vector3f currentVert = verts.get(i);
|
Vector3f currentVert = verts.get(i);
|
||||||
rVal.vertices[3 * i + 0] = currentVert.x;
|
rVal.vertices[3 * i + 0] = currentVert.x * scalingFactor;
|
||||||
rVal.vertices[3 * i + 1] = currentVert.y;
|
rVal.vertices[3 * i + 1] = currentVert.y * scalingFactor;
|
||||||
rVal.vertices[3 * i + 2] = currentVert.z;
|
rVal.vertices[3 * i + 2] = currentVert.z * scalingFactor;
|
||||||
}
|
}
|
||||||
rVal.vertBuffer = BufferUtils.createFloatBuffer(rVal.vertices.length);
|
rVal.vertBuffer = BufferUtils.createFloatBuffer(rVal.vertices.length);
|
||||||
rVal.vertBuffer.put(rVal.vertices);
|
rVal.vertBuffer.put(rVal.vertices);
|
||||||
@ -486,8 +492,8 @@ public class BlockMeshgen {
|
|||||||
rVal.uvs = new float[uvs.size() * 2];
|
rVal.uvs = new float[uvs.size() * 2];
|
||||||
for(int i = 0; i < uvs.size(); i++){
|
for(int i = 0; i < uvs.size(); i++){
|
||||||
Vector2f currentUV = uvs.get(i);
|
Vector2f currentUV = uvs.get(i);
|
||||||
rVal.uvs[2 * i + 0] = currentUV.x;
|
rVal.uvs[2 * i + 0] = currentUV.x * scalingFactor;
|
||||||
rVal.uvs[2 * i + 1] = currentUV.y;
|
rVal.uvs[2 * i + 1] = currentUV.y * scalingFactor;
|
||||||
}
|
}
|
||||||
rVal.uvBuffer = BufferUtils.createFloatBuffer(rVal.uvs.length);
|
rVal.uvBuffer = BufferUtils.createFloatBuffer(rVal.uvs.length);
|
||||||
rVal.uvBuffer.put(rVal.uvs);
|
rVal.uvBuffer.put(rVal.uvs);
|
||||||
@ -509,7 +515,7 @@ public class BlockMeshgen {
|
|||||||
* @return The mesh data
|
* @return The mesh data
|
||||||
*/
|
*/
|
||||||
public static BlockMeshData rasterize(BlockMeshgenData chunkData){
|
public static BlockMeshData rasterize(BlockMeshgenData chunkData){
|
||||||
return BlockMeshgen.rasterize(chunkData, true, null);
|
return BlockMeshgen.rasterize(chunkData, true, null, BlockMeshgen.DEFAULT_SCALING_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -326,6 +326,15 @@ public class ServerWorldData {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void convertRealToChunkSpace(Vector3d position, Vector3i destVec){
|
||||||
|
destVec.set(
|
||||||
|
ServerWorldData.convertRealToChunkSpace(position.x),
|
||||||
|
ServerWorldData.convertRealToChunkSpace(position.y),
|
||||||
|
ServerWorldData.convertRealToChunkSpace(position.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@ -387,6 +396,19 @@ public class ServerWorldData {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a real coordinate to a local block grid space coordinate
|
||||||
|
* @param position The real coordinate
|
||||||
|
* @param destVec The vector to store the result in
|
||||||
|
*/
|
||||||
|
public static void convertRealToLocalBlockSpace(Vector3d position, Vector3i destVec){
|
||||||
|
destVec.set(
|
||||||
|
ServerWorldData.convertRealToLocalBlockSpace(position.x),
|
||||||
|
ServerWorldData.convertRealToLocalBlockSpace(position.y),
|
||||||
|
ServerWorldData.convertRealToLocalBlockSpace(position.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a world coordinate to a macro scale coordinate
|
* Converts a world coordinate to a macro scale coordinate
|
||||||
* @param worldPos The world position
|
* @param worldPos The world position
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import electrosphere.server.macro.spatial.MacroLODObject;
|
|||||||
import electrosphere.server.macro.spatial.MacroObject;
|
import electrosphere.server.macro.spatial.MacroObject;
|
||||||
import electrosphere.server.macro.structure.VirtualStructure;
|
import electrosphere.server.macro.structure.VirtualStructure;
|
||||||
import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
|
import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
|
||||||
|
import electrosphere.server.physics.terrain.manager.ServerChunkCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A job that fetches a chunk, either by generating it or by reading it from disk
|
* A job that fetches a chunk, either by generating it or by reading it from disk
|
||||||
@ -177,7 +178,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
chunk = chunkCache.get(worldX, worldY, worldZ, stride);
|
chunk = chunkCache.get(worldX, worldY, worldZ, stride);
|
||||||
} else {
|
} else {
|
||||||
//pull from disk if it exists
|
//pull from disk if it exists
|
||||||
if(chunkDiskMap != null){
|
if(chunkDiskMap != null && stride == ServerChunkCache.STRIDE_FULL_RES){
|
||||||
if(chunkDiskMap.containsBlocksAtPosition(worldX, worldY, worldZ)){
|
if(chunkDiskMap.containsBlocksAtPosition(worldX, worldY, worldZ)){
|
||||||
chunk = chunkDiskMap.getBlockChunk(worldX, worldY, worldZ);
|
chunk = chunkDiskMap.getBlockChunk(worldX, worldY, worldZ);
|
||||||
}
|
}
|
||||||
@ -188,7 +189,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
chunk.setWorldX(worldX);
|
chunk.setWorldX(worldX);
|
||||||
chunk.setWorldY(worldY);
|
chunk.setWorldY(worldY);
|
||||||
chunk.setWorldZ(worldZ);
|
chunk.setWorldZ(worldZ);
|
||||||
ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ);
|
ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ, stride);
|
||||||
}
|
}
|
||||||
if(chunk != null){
|
if(chunk != null){
|
||||||
chunkCache.add(worldX, worldY, worldZ, stride, chunk);
|
chunkCache.add(worldX, worldY, worldZ, stride, chunk);
|
||||||
@ -204,36 +205,45 @@ public class ServerBlockChunkGenerationThread implements Runnable {
|
|||||||
* @param worldX THe world x coordinate
|
* @param worldX THe world x coordinate
|
||||||
* @param worldY The world y coordinate
|
* @param worldY The world y coordinate
|
||||||
* @param worldZ The world z coordinate
|
* @param worldZ The world z coordinate
|
||||||
|
* @param stride The stride of the data to generate
|
||||||
*/
|
*/
|
||||||
protected static void generate(BlockChunkData chunk, MacroData macroData, int worldX, int worldY, int worldZ){
|
protected static void generate(BlockChunkData chunk, MacroData macroData, int worldX, int worldY, int worldZ, int stride){
|
||||||
if(macroData == null){
|
if(macroData == null){
|
||||||
chunk.setHomogenousValue(0);
|
chunk.setHomogenousValue(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//check if this chunk intersects any macro data
|
//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));
|
int strideMultiplier = (int)Math.pow(2,stride);
|
||||||
|
if(strideMultiplier > 16){
|
||||||
|
throw new Error("Invalid stride size!");
|
||||||
|
}
|
||||||
|
AABBd localAABB = new AABBd(ServerWorldData.convertChunkToRealSpace(worldX,worldY,worldZ),ServerWorldData.convertChunkToRealSpace(worldX+strideMultiplier,worldY+strideMultiplier,worldZ+strideMultiplier));
|
||||||
List<VirtualStructure> filtered = macroData.getStructures().stream().filter((VirtualStructure struct) -> {return !struct.isRepairable() && struct.getAABB().testAABB(localAABB);}).collect(Collectors.toList());
|
List<VirtualStructure> filtered = macroData.getStructures().stream().filter((VirtualStructure struct) -> {return !struct.isRepairable() && struct.getAABB().testAABB(localAABB);}).collect(Collectors.toList());
|
||||||
if(filtered.size() > 0){
|
if(filtered.size() > 0){
|
||||||
Vector3i chunkPos = new Vector3i(worldX, worldY, worldZ);
|
Vector3i chunkPos = new Vector3i(worldX, worldY, worldZ);
|
||||||
Vector3i blockPos = new Vector3i(0,0,0);
|
Vector3i blockPos = new Vector3i(0,0,0);
|
||||||
Vector3d chunkRealPos = ServerWorldData.convertChunkToRealSpace(chunkPos);
|
Vector3d chunkRealPos = ServerWorldData.convertChunkToRealSpace(chunkPos);
|
||||||
Vector3i localBlockPos = new Vector3i();
|
Vector3i localBlockPos = new Vector3i();
|
||||||
|
Vector3d currRealPos = new Vector3d(chunkRealPos);
|
||||||
//contains at least one structure
|
//contains at least one structure
|
||||||
for(int x = 0; x < BlockChunkData.CHUNK_DATA_WIDTH; x++){
|
for(int x = 0; x < BlockChunkData.CHUNK_DATA_WIDTH; x++){
|
||||||
for(int y = 0; y < BlockChunkData.CHUNK_DATA_WIDTH; y++){
|
for(int y = 0; y < BlockChunkData.CHUNK_DATA_WIDTH; y++){
|
||||||
for(int z = 0; z < BlockChunkData.CHUNK_DATA_WIDTH; z++){
|
for(int z = 0; z < BlockChunkData.CHUNK_DATA_WIDTH; z++){
|
||||||
boolean placedBlock = false;
|
boolean placedBlock = false;
|
||||||
|
|
||||||
|
currRealPos.set(chunkRealPos).add(x * strideMultiplier * BlockChunkData.BLOCK_SIZE_MULTIPLIER,y * strideMultiplier * BlockChunkData.BLOCK_SIZE_MULTIPLIER,z * strideMultiplier * BlockChunkData.BLOCK_SIZE_MULTIPLIER);
|
||||||
|
ServerWorldData.convertRealToLocalBlockSpace(currRealPos,blockPos);
|
||||||
|
ServerWorldData.convertRealToChunkSpace(currRealPos,chunkPos);
|
||||||
|
|
||||||
//try placing a structure block
|
//try placing a structure block
|
||||||
blockPos.set(x,y,z);
|
blockPos.set(x*strideMultiplier,y*strideMultiplier,z*strideMultiplier);
|
||||||
Vector3d currRealPoint = ServerWorldData.convertLocalBlockToRealSpace(chunkPos, blockPos);
|
|
||||||
for(VirtualStructure struct : filtered){
|
for(VirtualStructure struct : filtered){
|
||||||
if(struct.getAABB().testPoint(currRealPoint.x, currRealPoint.y, currRealPoint.z)){
|
if(struct.getAABB().testPoint(currRealPos.x, currRealPos.y, currRealPos.z)){
|
||||||
AABBd aabb = struct.getAABB();
|
AABBd aabb = struct.getAABB();
|
||||||
localBlockPos.set(
|
localBlockPos.set(
|
||||||
(int)((chunkRealPos.x + (x * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - aabb.minX) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
|
(int)((currRealPos.x - aabb.minX) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
|
||||||
(int)((chunkRealPos.y + (y * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - aabb.minY) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
|
(int)((currRealPos.y - aabb.minY) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
|
||||||
(int)((chunkRealPos.z + (z * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - aabb.minZ) / BlockChunkData.BLOCK_SIZE_MULTIPLIER)
|
(int)((currRealPos.z - aabb.minZ) / 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
|
//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){
|
if(localBlockPos.x < struct.getFab().getDimensions().x && localBlockPos.y < struct.getFab().getDimensions().y && localBlockPos.z < struct.getFab().getDimensions().z){
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user