small changes

This commit is contained in:
Leonardo
2021-08-27 14:31:13 +02:00
parent 21069d6479
commit 9990132db2
3 changed files with 370 additions and 320 deletions
@@ -60,7 +60,7 @@ public class LodBufferBuilder
/**
* This holds the threads used to generate buffers.
*/
private ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new LodThreadFactory(this.getClass().getSimpleName() + " - builder"));
private ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get(), new LodThreadFactory(this.getClass().getSimpleName() + " - builder"));
/**
* The buffers that are used to create LODs using far fog
@@ -21,13 +21,13 @@ import java.io.File;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.*;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.stream.Collectors;
import java.util.concurrent.*;
import com.seibel.lod.enums.DistanceGenerationMode;
import com.seibel.lod.handlers.LodDimensionFileHandler;
import com.seibel.lod.objects.LevelPos.LevelPos;
import com.seibel.lod.util.DetailDistanceUtil;
import com.seibel.lod.util.LodThreadFactory;
import com.seibel.lod.util.LodUtil;
import net.minecraft.client.Minecraft;
@@ -36,6 +36,7 @@ import net.minecraft.world.DimensionType;
import net.minecraft.world.server.ServerChunkProvider;
import net.minecraft.world.server.ServerWorld;
/**
* This object holds all loaded LOD regions
* for a given dimension.
@@ -63,8 +64,10 @@ public class LodDimension
public volatile boolean isRegionDirty[][];
private volatile RegionPos center;
private volatile ChunkPos lastGenChunk;
private volatile ChunkPos lastCutChunk;
private LodDimensionFileHandler fileHandler;
private ExecutorService cutAndGenThreads = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - cutAndGen"));
/**
* Creates the dimension centered at (0,0)
@@ -73,6 +76,8 @@ public class LodDimension
*/
public LodDimension(DimensionType newDimension, LodWorld lodWorld, int newWidth)
{
lastCutChunk = null;
lastGenChunk = null;
dimension = newDimension;
width = newWidth;
halfWidth = (int) Math.floor(width / 2);
@@ -237,7 +242,8 @@ public class LodDimension
for (int z = 0; z < regions.length; z++)
{
region = regions[x][z];
if(region != null){
if (region != null)
{
count += region.getMinMemoryNeeded();
}
}
@@ -304,92 +310,124 @@ public class LodDimension
/**
*
*/
public void treeCutter(int playerPosX, int playerPosZ)
{
int regionX;
int regionZ;
LevelPos levelPos = new LevelPos();
for (int x = 0; x < regions.length; x++)
ChunkPos newPlayerChunk = (new LevelPos((byte) 0, playerPosX, playerPosZ)).getChunkPos();
if (lastCutChunk == null)
lastCutChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1);
if (newPlayerChunk.x != lastCutChunk.x || newPlayerChunk.z != lastCutChunk.z)
{
for (int z = 0; z < regions.length; z++)
lastCutChunk = newPlayerChunk;
Thread thread = new Thread(() ->
{
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ);
//we start checking from the first circle. If the whole region is in the circle
//we proceed to cut all the level lower than the level of circle 1 and we break
//if this is not the case w
for(byte index = LodUtil.BLOCK_DETAIL_LEVEL; index <= LodUtil.DETAIL_OPTIONS; index++){
if(DetailDistanceUtil.getDistanceTreeCut(index + 1) > levelPos.minDistance(playerPosX, playerPosZ)){
int regionX;
int regionZ;
LevelPos levelPos = new LevelPos();
byte cutDetailLevel = DetailDistanceUtil.getCutLodDetail(index);
if(regions[x][z] != null)
for (int x = 0; x < regions.length; x++)
{
for (int z = 0; z < regions.length; z++)
{
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ);
//we start checking from the first circle. If the whole region is in the circle
//we proceed to cut all the level lower than the level of circle 1 and we break
//if this is not the case w
for (byte index = LodUtil.BLOCK_DETAIL_LEVEL; index <= LodUtil.DETAIL_OPTIONS; index++)
{
if(regions[x][z].getMinDetailLevel() > cutDetailLevel){
regions[x][z].cutTree(cutDetailLevel);
if (DetailDistanceUtil.getDistanceTreeCut(index + 1) > levelPos.minDistance(playerPosX, playerPosZ))
{
byte cutDetailLevel = DetailDistanceUtil.getCutLodDetail(index);
if (regions[x][z] != null)
{
if (regions[x][z].getMinDetailLevel() > cutDetailLevel)
{
regions[x][z].cutTree(cutDetailLevel);
}
}
//once we
break;
}
}
//once we
break;
}
}
}
}// region z
}// region z
});
cutAndGenThreads.execute(thread);
}
}
/**
*
*/
public void treeGenerator(int playerPosX, int playerPosZ)
{
int regionX;
int regionZ;
LevelPos levelPos = new LevelPos();
RegionPos regionPos;
LodRegion region;
byte targetDetailLevel;
for (int x = 0; x < regions.length; x++)
ChunkPos newPlayerChunk = (new LevelPos((byte) 0, playerPosX, playerPosZ)).getChunkPos();
if (lastGenChunk == null)
lastGenChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1);
if (newPlayerChunk.x != lastGenChunk.x || newPlayerChunk.z != lastGenChunk.z)
{
for (int z = 0; z < regions.length; z++)
lastGenChunk = newPlayerChunk;
Thread thread = new Thread(() ->
{
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ);
regionPos = new RegionPos(regionX, regionZ);
for(byte index = LodUtil.BLOCK_DETAIL_LEVEL; index <= LodUtil.REGION_DETAIL_LEVEL; index++){
//As soon as we find in which circle the region should be we analyze it
if(DetailDistanceUtil.getDistanceTreeGen(index + 1) > levelPos.minDistance(playerPosX, playerPosZ)){
region = regions[x][z];
//We require that the region we are checking is loaded with at least this level
targetDetailLevel = DetailDistanceUtil.getLodDetail(index).detailLevel;
if (region == null)
int regionX;
int regionZ;
LodRegion region;
LevelPos levelPos = new LevelPos();
List<Callable<Boolean>> genThreads = new ArrayList<>();
for (int x = 0; x < regions.length; x++)
{
for (int z = 0; z < regions.length; z++)
{
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ);
final RegionPos regionPos = new RegionPos(regionX, regionZ);
for (byte index = LodUtil.BLOCK_DETAIL_LEVEL; index <= LodUtil.REGION_DETAIL_LEVEL; index++)
{
//First case, region has to be initialized
//We check if there is a file at the target level
regions[x][z] = getRegionFromFile(regionPos, targetDetailLevel);
//if there is no file we initialize the region
if (regions[x][z] == null)
//As soon as we find in which circle the region should be we analyze it
if (DetailDistanceUtil.getDistanceTreeGen(index + 1) > levelPos.minDistance(playerPosX, playerPosZ))
{
regions[x][z] = new LodRegion(targetDetailLevel, regionPos);
}
}else if(region.getMinDetailLevel() > targetDetailLevel){
//Second case, region has been initialized but at a higher level
//We expand the region by introducing the missing layer
region.expand(targetDetailLevel);
region = regions[x][z];
//We require that the region we are checking is loaded with at least this level
byte targetDetailLevel = DetailDistanceUtil.getLodDetail(index).detailLevel;
if (region == null)
{
//First case, region has to be initialized
//We check if there is a file at the target level
regions[x][z] = getRegionFromFile(regionPos, targetDetailLevel);
//if there is no file we initialize the region
if (regions[x][z] == null)
{
regions[x][z] = new LodRegion(targetDetailLevel, regionPos);
}
} else if (region.getMinDetailLevel() > targetDetailLevel)
{
//Second case, region has been initialized but at a higher level
//We expand the region by introducing the missing layer
region.expand(targetDetailLevel);
}
break;
}
}
break;
}
}
}
;
});
cutAndGenThreads.execute(thread);
}
}
@@ -461,7 +499,8 @@ public class LodDimension
region = getRegion(new LevelPos(LodUtil.REGION_DETAIL_LEVEL, regionPos.x, regionPos.z).getConvertedLevelPos(detailLevel));
listOfData.addAll(region.getDataToGenerate(playerPosX, playerPosZ, start, end, generation, detailLevel, dataNumber));
}
}catch (Exception e){
} catch (Exception e)
{
//e.printStackTrace();
}
}
@@ -470,9 +509,9 @@ public class LodDimension
List<LevelPos> levelMinPosList = new ArrayList<>();
dataNumber = Math.min(dataNumber, listOfData.size());
for(int i=0; i<dataNumber; i++)
for (int i = 0; i < dataNumber; i++)
{
LevelPos min = Collections.min(listOfData, LevelPos.getPosComparator(playerPosX,playerPosZ));
LevelPos min = Collections.min(listOfData, LevelPos.getPosComparator(playerPosX, playerPosZ));
listOfData.remove(min);
levelMinPosList.add(min);
}
@@ -484,7 +523,7 @@ public class LodDimension
*
* @return list of nodes
*/
public void getDataToRender(ConcurrentNavigableMap<LevelPos,List<Integer>> dataToRender, RegionPos regionPos, int playerPosX, int playerPosZ, int start, int end, byte detailLevel, boolean zFix)
public void getDataToRender(ConcurrentNavigableMap<LevelPos, List<Integer>> dataToRender, RegionPos regionPos, int playerPosX, int playerPosZ, int start, int end, byte detailLevel, boolean zFix)
{
LevelPos regionLevelPos = new LevelPos(LodUtil.REGION_DETAIL_LEVEL, regionPos.x, regionPos.z);
try
@@ -493,9 +532,10 @@ public class LodDimension
start <= regionLevelPos.maxDistance(playerPosX, playerPosZ))
{
LodRegion region = getRegion(new LevelPos(LodUtil.REGION_DETAIL_LEVEL, regionPos.x, regionPos.z).getConvertedLevelPos(detailLevel));
region.getDataToRender(dataToRender,playerPosX, playerPosZ, start, end, detailLevel,zFix);
region.getDataToRender(dataToRender, playerPosX, playerPosZ, start, end, detailLevel, zFix);
}
}catch (Exception e){
} catch (Exception e)
{
e.printStackTrace();
}
}
@@ -536,7 +576,8 @@ public class LodDimension
return region.getData(levelPos);
}catch (Exception e){
} catch (Exception e)
{
return null;
}
}
@@ -595,7 +636,8 @@ public class LodDimension
}
return region.doesDataExist(levelPos.clone());
}catch (Exception e){
} catch (Exception e)
{
return false;
}
}
@@ -704,12 +746,12 @@ public class LodDimension
for (int z = 0; z < regions.length; z++)
{
region = regions[x][z];
if(region == null)
if (region == null)
{
stringBuilder.append("n");
stringBuilder.append("\t");
}else
} else
{
stringBuilder.append(region.getMinDetailLevel());
stringBuilder.append("\t");
@@ -57,258 +57,266 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
*/
public class ClientProxy
{
public static final Logger LOGGER = LogManager.getLogger("LOD");
private static LodWorld lodWorld = new LodWorld();
private static LodBuilder lodBuilder = new LodBuilder();
private static LodBufferBuilder lodBufferBuilder = new LodBufferBuilder();
private static LodRenderer renderer = new LodRenderer(lodBufferBuilder);
private static LodWorldGenerator lodWorldGenerator = LodWorldGenerator.INSTANCE;
public static final Logger LOGGER = LogManager.getLogger("LOD");
private boolean configOverrideReminderPrinted = false;
Minecraft mc = Minecraft.getInstance();
private static LodWorld lodWorld = new LodWorld();
private static LodBuilder lodBuilder = new LodBuilder();
private static LodBufferBuilder lodBufferBuilder = new LodBufferBuilder();
private static LodRenderer renderer = new LodRenderer(lodBufferBuilder);
private static LodWorldGenerator lodWorldGenerator = LodWorldGenerator.INSTANCE;
private boolean configOverrideReminderPrinted = false;
Minecraft mc = Minecraft.getInstance();
/** This is used to determine if the LODs should be regenerated */
public static int previousChunkRenderDistance = 0;
/** This is used to determine if the LODs should be regenerated */
public static int previousLodRenderDistance = 0;
/** can be set if we want to recalculate variables related
* to the LOD view distance */
private boolean recalculateWidths = false;
/**
* This is used to determine if the LODs should be regenerated
*/
public static int previousChunkRenderDistance = 0;
/**
* This is used to determine if the LODs should be regenerated
*/
public static int previousLodRenderDistance = 0;
public ClientProxy()
{
}
//==============//
// render event //
//==============//
/**
* Do any setup that is required to draw LODs
* and then tell the LodRenderer to draw.
*/
public void renderLods(float partialTicks)
{
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
return;
applyConfigOverrides();
viewDistanceChangedEvent();
LodDimension lodDim = lodWorld.getLodDimension(mc.player.level.dimensionType());
if (lodDim == null)
return;
/**
* can be set if we want to recalculate variables related
* to the LOD view distance
*/
private boolean recalculateWidths = false;
playerMoveEvent(lodDim);
//System.out.println("memory needed " + lodDim.getMinMemoryNeeded() + " byte");
//System.out.println(lodDim);
public ClientProxy()
{
lodDim.treeCutter((int) mc.player.getX(),(int) mc.player.getZ());
lodDim.treeGenerator((int) mc.player.getX(),(int) mc.player.getZ());
// comment out when creating a release
// Note to self:
// if "unspecified" shows up in the pie chart, it is
// possibly because the amount of time between sections
// is too small for the profiler to measure
IProfiler profiler = mc.getProfiler();
profiler.pop(); // get out of "terrain"
profiler.push("LOD");
renderer.drawLODs(lodDim, partialTicks, mc.getProfiler());
}
profiler.pop(); // end LOD
profiler.push("terrain"); // restart "terrain"
// these can't be set until after the buffers are built (in renderer.drawLODs)
// otherwise the buffers may be set to the wrong size, or not changed at all
previousChunkRenderDistance = mc.options.renderDistance;
previousLodRenderDistance = LodConfig.CLIENT.lodChunkRenderDistance.get();
}
private void applyConfigOverrides()
{
// remind the developer(s). that config override is active
if (!configOverrideReminderPrinted)
{
mc.player.sendMessage(new StringTextComponent("Debug settings enabled!"), mc.player.getUUID());
configOverrideReminderPrinted = true;
}
// LodConfig.CLIENT.drawLODs.set(true);
LodConfig.CLIENT.debugMode.set(false);
LodConfig.CLIENT.maxDrawDetail.set(LodDetail.FULL);
LodConfig.CLIENT.maxGenerationDetail.set(LodDetail.FULL);
//==============//
// render event //
//==============//
LodConfig.CLIENT.fogDistance.set(FogDistance.FAR);
LodConfig.CLIENT.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
LodConfig.CLIENT.shadingMode.set(ShadingMode.DARKEN_SIDES);
LodConfig.CLIENT.brightnessMultiplier.set(1.0);
LodConfig.CLIENT.saturationMultiplier.set(1.0);
LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
LodConfig.CLIENT.lodChunkRenderDistance.set(128);
LodConfig.CLIENT.lodDistanceCalculatorType.set(DistanceCalculatorType.LINEAR);
LodConfig.CLIENT.lodQuality.set(2);
LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
LodConfig.CLIENT.numberOfWorldGenerationThreads.set(Runtime.getRuntime().availableProcessors());
// has to be set in the config file
// LodConfig.CLIENT.numberOfWorldGenerationThreads.set(16);
}
//==============//
// forge events //
//==============//
@SubscribeEvent
public void serverTickEvent(TickEvent.ServerTickEvent event)
{
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
return;
LodDimension lodDim = lodWorld.getLodDimension(mc.player.level.dimensionType());
if (lodDim == null)
return;
lodWorldGenerator.queueGenerationRequests(lodDim, renderer, lodBuilder);
}
@SubscribeEvent
public void chunkLoadEvent(ChunkEvent.Load event)
{
lodBuilder.generateLodNodeAsync(event.getChunk(), lodWorld, event.getWorld(), DistanceGenerationMode.SERVER);
}
@SubscribeEvent
public void worldSaveEvent(WorldEvent.Save event)
{
if (lodWorld != null)
lodWorld.saveAllDimensions();
}
@SubscribeEvent
public void worldLoadEvent(WorldEvent.Load event)
{
// the player just loaded a new world/dimension
lodWorld.selectWorld(LodUtil.getWorldID(event.getWorld()));
// make sure the correct LODs are being rendered
// (if this isn't done the previous world's LODs may be drawn)
renderer.regenerateLODsNextFrame();
}
@SubscribeEvent
public void worldUnloadEvent(WorldEvent.Unload event)
{
// the player just unloaded a world/dimension
if (mc.getConnection().getLevel() == null)
{
// if this isn't done unfinished tasks may be left in the queue
// preventing new LodChunks form being generated
LodNodeGenWorker.restartExecuterService();
LodWorldGenerator.INSTANCE.numberOfChunksWaitingToGenerate.set(0);
// the player has disconnected from a server
lodWorld.deselectWorld();
// hopefully this should reduce issues related to the buffer builder
// breaking when changing worlds.
renderer.destroyBuffers();
recalculateWidths = true;
}
}
@SubscribeEvent
public void blockChangeEvent(BlockEvent event)
{
if (event.getClass() == BlockEvent.BreakEvent.class ||
event.getClass() == BlockEvent.EntityPlaceEvent.class ||
event.getClass() == BlockEvent.EntityMultiPlaceEvent.class ||
event.getClass() == BlockEvent.FluidPlaceBlockEvent.class ||
event.getClass() == BlockEvent.PortalSpawnEvent.class)
{
// recreate the LOD where the blocks were changed
lodBuilder.generateLodNodeAsync(event.getWorld().getChunk(event.getPos()), lodWorld, event.getWorld());
}
}
//==================//
// frame LOD events //
//==================//
/**
* Re-centers the given LodDimension if it needs to be.
*/
private void playerMoveEvent(LodDimension lodDim)
{
// make sure the dimension is centered
RegionPos playerRegionPos = new RegionPos(mc.player.blockPosition());
RegionPos worldRegionOffset = new RegionPos(playerRegionPos.x - lodDim.getCenterX(), playerRegionPos.z - lodDim.getCenterZ());
if (worldRegionOffset.x != 0 || worldRegionOffset.z != 0)
{
lodWorld.saveAllDimensions();
lodDim.move(worldRegionOffset);
LOGGER.info("offset: " + worldRegionOffset.x + "," + worldRegionOffset.z + "\t center: " + lodDim.getCenterX() + "," + lodDim.getCenterZ());
}
}
/**
* Re-sizes all LodDimensions if they needs to be.
*/
private void viewDistanceChangedEvent()
{
// calculate how wide the dimension(s) should be in regions
int chunksWide = LodConfig.CLIENT.lodChunkRenderDistance.get() * 2 + 1;
int newWidth = (int) Math.ceil(chunksWide / (float) LodUtil.REGION_WIDTH_IN_CHUNKS);
newWidth = (newWidth % 2 == 0) ? (newWidth += 1) : (newWidth += 2); // make sure we have a odd number of regions
// do the dimensions need to change in size?
if (lodBuilder.defaultDimensionWidthInRegions != newWidth || recalculateWidths)
{
// update the dimensions to fit the new width
lodWorld.resizeDimensionRegionWidth(newWidth);
lodBuilder.defaultDimensionWidthInRegions = newWidth;
renderer.setupBuffers(newWidth);
recalculateWidths = false;
//LOGGER.info("new dimension width in regions: " + newWidth + "\t potential: " + newWidth );
}
}
//================//
// public getters //
//================//
public static LodWorld getLodWorld()
{
return lodWorld;
}
public static LodBuilder getLodBuilder()
{
return lodBuilder;
}
public static LodRenderer getRenderer()
{
return renderer;
}
/**
* Do any setup that is required to draw LODs
* and then tell the LodRenderer to draw.
*/
public void renderLods(float partialTicks)
{
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
return;
viewDistanceChangedEvent();
LodDimension lodDim = lodWorld.getLodDimension(mc.player.level.dimensionType());
if (lodDim == null)
return;
playerMoveEvent(lodDim);
//System.out.println("memory needed " + lodDim.getMinMemoryNeeded() + " byte");
//System.out.println(lodDim);
lodDim.treeCutter((int) mc.player.getX(), (int) mc.player.getZ());
lodDim.treeGenerator((int) mc.player.getX(), (int) mc.player.getZ());
// comment out when creating a release
applyConfigOverrides();
// Note to self:
// if "unspecified" shows up in the pie chart, it is
// possibly because the amount of time between sections
// is too small for the profiler to measure
IProfiler profiler = mc.getProfiler();
profiler.pop(); // get out of "terrain"
profiler.push("LOD");
renderer.drawLODs(lodDim, partialTicks, mc.getProfiler());
profiler.pop(); // end LOD
profiler.push("terrain"); // restart "terrain"
// these can't be set until after the buffers are built (in renderer.drawLODs)
// otherwise the buffers may be set to the wrong size, or not changed at all
previousChunkRenderDistance = mc.options.renderDistance;
previousLodRenderDistance = LodConfig.CLIENT.lodChunkRenderDistance.get();
}
private void applyConfigOverrides()
{
// remind the developer(s). that config override is active
if (!configOverrideReminderPrinted)
{
mc.player.sendMessage(new StringTextComponent("Debug settings enabled!"), mc.player.getUUID());
configOverrideReminderPrinted = true;
}
// LodConfig.CLIENT.drawLODs.set(true);
LodConfig.CLIENT.debugMode.set(false);
LodConfig.CLIENT.maxDrawDetail.set(LodDetail.FULL);
LodConfig.CLIENT.maxGenerationDetail.set(LodDetail.FULL);
LodConfig.CLIENT.fogDistance.set(FogDistance.FAR);
LodConfig.CLIENT.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
LodConfig.CLIENT.shadingMode.set(ShadingMode.DARKEN_SIDES);
LodConfig.CLIENT.brightnessMultiplier.set(1.0);
LodConfig.CLIENT.saturationMultiplier.set(1.0);
LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
LodConfig.CLIENT.lodChunkRenderDistance.set(128);
LodConfig.CLIENT.lodDistanceCalculatorType.set(DistanceCalculatorType.LINEAR);
LodConfig.CLIENT.lodQuality.set(2);
LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
LodConfig.CLIENT.numberOfWorldGenerationThreads.set(Runtime.getRuntime().availableProcessors());
// has to be set in the config file
// LodConfig.CLIENT.numberOfWorldGenerationThreads.set(16);
}
//==============//
// forge events //
//==============//
@SubscribeEvent
public void serverTickEvent(TickEvent.ServerTickEvent event)
{
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
return;
LodDimension lodDim = lodWorld.getLodDimension(mc.player.level.dimensionType());
if (lodDim == null)
return;
lodWorldGenerator.queueGenerationRequests(lodDim, renderer, lodBuilder);
}
@SubscribeEvent
public void chunkLoadEvent(ChunkEvent.Load event)
{
lodBuilder.generateLodNodeAsync(event.getChunk(), lodWorld, event.getWorld(), DistanceGenerationMode.SERVER);
}
@SubscribeEvent
public void worldSaveEvent(WorldEvent.Save event)
{
if (lodWorld != null)
lodWorld.saveAllDimensions();
}
@SubscribeEvent
public void worldLoadEvent(WorldEvent.Load event)
{
// the player just loaded a new world/dimension
lodWorld.selectWorld(LodUtil.getWorldID(event.getWorld()));
// make sure the correct LODs are being rendered
// (if this isn't done the previous world's LODs may be drawn)
renderer.regenerateLODsNextFrame();
}
@SubscribeEvent
public void worldUnloadEvent(WorldEvent.Unload event)
{
// the player just unloaded a world/dimension
if (mc.getConnection().getLevel() == null)
{
// if this isn't done unfinished tasks may be left in the queue
// preventing new LodChunks form being generated
LodNodeGenWorker.restartExecuterService();
LodWorldGenerator.INSTANCE.numberOfChunksWaitingToGenerate.set(0);
// the player has disconnected from a server
lodWorld.deselectWorld();
// hopefully this should reduce issues related to the buffer builder
// breaking when changing worlds.
renderer.destroyBuffers();
recalculateWidths = true;
}
}
@SubscribeEvent
public void blockChangeEvent(BlockEvent event)
{
if (event.getClass() == BlockEvent.BreakEvent.class ||
event.getClass() == BlockEvent.EntityPlaceEvent.class ||
event.getClass() == BlockEvent.EntityMultiPlaceEvent.class ||
event.getClass() == BlockEvent.FluidPlaceBlockEvent.class ||
event.getClass() == BlockEvent.PortalSpawnEvent.class)
{
// recreate the LOD where the blocks were changed
lodBuilder.generateLodNodeAsync(event.getWorld().getChunk(event.getPos()), lodWorld, event.getWorld());
}
}
//==================//
// frame LOD events //
//==================//
/**
* Re-centers the given LodDimension if it needs to be.
*/
private void playerMoveEvent(LodDimension lodDim)
{
// make sure the dimension is centered
RegionPos playerRegionPos = new RegionPos(mc.player.blockPosition());
RegionPos worldRegionOffset = new RegionPos(playerRegionPos.x - lodDim.getCenterX(), playerRegionPos.z - lodDim.getCenterZ());
if (worldRegionOffset.x != 0 || worldRegionOffset.z != 0)
{
lodWorld.saveAllDimensions();
lodDim.move(worldRegionOffset);
LOGGER.info("offset: " + worldRegionOffset.x + "," + worldRegionOffset.z + "\t center: " + lodDim.getCenterX() + "," + lodDim.getCenterZ());
}
}
/**
* Re-sizes all LodDimensions if they needs to be.
*/
private void viewDistanceChangedEvent()
{
// calculate how wide the dimension(s) should be in regions
int chunksWide = LodConfig.CLIENT.lodChunkRenderDistance.get() * 2 + 1;
int newWidth = (int) Math.ceil(chunksWide / (float) LodUtil.REGION_WIDTH_IN_CHUNKS);
newWidth = (newWidth % 2 == 0) ? (newWidth += 1) : (newWidth += 2); // make sure we have a odd number of regions
// do the dimensions need to change in size?
if (lodBuilder.defaultDimensionWidthInRegions != newWidth || recalculateWidths)
{
// update the dimensions to fit the new width
lodWorld.resizeDimensionRegionWidth(newWidth);
lodBuilder.defaultDimensionWidthInRegions = newWidth;
renderer.setupBuffers(newWidth);
recalculateWidths = false;
//LOGGER.info("new dimension width in regions: " + newWidth + "\t potential: " + newWidth );
}
}
//================//
// public getters //
//================//
public static LodWorld getLodWorld()
{
return lodWorld;
}
public static LodBuilder getLodBuilder()
{
return lodBuilder;
}
public static LodRenderer getRenderer()
{
return renderer;
}
}