Fix beacons disappearing and not updating correctly

This commit is contained in:
James Seibel
2025-01-19 17:42:14 -06:00
parent 09962acca6
commit 995f80d553
9 changed files with 287 additions and 231 deletions
@@ -1,177 +0,0 @@
package com.seibel.distanthorizons.core.file.beacon;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler;
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
import com.seibel.distanthorizons.core.util.KeyedLockContainer;
import com.seibel.distanthorizons.core.util.LodUtil;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
public class BeaconBeamDataHandler
{
private final BeaconBeamRepo beaconBeamRepo;
@Nullable
private BeaconRenderHandler beaconRenderHandler;
private final KeyedLockContainer<Long> updateLockContainer = new KeyedLockContainer<>();
//=============//
// constructor //
//=============//
public BeaconBeamDataHandler(@NotNull BeaconBeamRepo beaconBeamRepo, @Nullable GenericObjectRenderer renderer)
{
this.beaconBeamRepo = beaconBeamRepo;
if (renderer != null)
{
this.beaconRenderHandler = new BeaconRenderHandler(renderer);
}
}
//==========//
// updating //
//==========//
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> activeBeamList)
{
long sectionPos = DhSectionPos.encode(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.getX(), chunkPos.getZ());
this.setBeaconBeamsForPos(sectionPos, activeBeamList);
}
public void setBeaconBeamsForPos(long sectionPos, List<BeaconBeamDTO> activeBeamList)
{
// locked to prevent two threads from updating the same section at the same time
ReentrantLock lock = this.updateLockContainer.getLockForPos(sectionPos);
try
{
lock.lock();
HashSet<DhBlockPos> allPosSet = new HashSet<>();
// sort new beams
HashMap<DhBlockPos, BeaconBeamDTO> activeBeamByPos = new HashMap<>(activeBeamList.size());
for (BeaconBeamDTO beam : activeBeamList)
{
activeBeamByPos.put(beam.blockPos, beam);
allPosSet.add(beam.blockPos);
}
// get existing beams
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(sectionPos);
HashMap<DhBlockPos, BeaconBeamDTO> existingBeamByPos = new HashMap<>(existingBeamList.size());
for (BeaconBeamDTO beam : existingBeamList)
{
existingBeamByPos.put(beam.blockPos, beam);
allPosSet.add(beam.blockPos);
}
for (DhBlockPos beaconPos : allPosSet)
{
if (!DhSectionPos.contains(sectionPos, beaconPos))
{
// don't update beacons outside the updated chunk
continue;
}
BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos);
BeaconBeamDTO activeBeam = activeBeamByPos.get(beaconPos);
if (activeBeam != null)
{
if (existingBeam == null)
{
// new beam found, add to DB
this.beaconBeamRepo.save(activeBeam);
if (this.beaconRenderHandler != null)
{
this.beaconRenderHandler.startRenderingBeacon(activeBeam);
}
}
else
{
// beam still exists in chunk
if (!existingBeam.color.equals(activeBeam.color))
{
// beam colors were changed
this.beaconBeamRepo.save(activeBeam);
if (this.beaconRenderHandler != null)
{
this.beaconRenderHandler.updateBeaconColor(activeBeam);
}
}
}
}
else if (existingBeam != null)
{
// beam no longer exists at position, remove from DB
this.beaconBeamRepo.deleteWithKey(beaconPos);
if (this.beaconRenderHandler != null)
{
this.beaconRenderHandler.stopRenderingBeaconAtPos(beaconPos);
}
}
}
}
finally
{
lock.unlock();
}
}
//===================//
// loading/unloading //
//===================//
public void loadBeaconBeamsInPos(long pos)
{
if (this.beaconRenderHandler == null)
{
return;
}
// get all beams in pos
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos);
for (BeaconBeamDTO newBeam : existingBeamList)
{
this.beaconRenderHandler.startRenderingBeacon(newBeam);
}
}
public void unloadBeaconBeamsInPos(long pos)
{
if (this.beaconRenderHandler == null)
{
return;
}
// get all beams in pos
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos);
for (BeaconBeamDTO beam : existingBeamList)
{
this.beaconRenderHandler.stopRenderingBeaconAtPos(beam.blockPos);
}
}
}
@@ -21,12 +21,12 @@ package com.seibel.distanthorizons.core.level;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkModifiedEvent;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.file.beacon.BeaconBeamDataHandler;
import com.seibel.distanthorizons.core.file.fullDatafile.DelayedFullDataSourceSaveCache;
import com.seibel.distanthorizons.core.generation.DhLightingEngine;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.render.renderer.generic.CloudRenderHandler;
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
@@ -34,6 +34,7 @@ import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO;
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
import com.seibel.distanthorizons.core.sql.repo.ChunkHashRepo;
import com.seibel.distanthorizons.core.util.KeyedLockContainer;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
@@ -43,10 +44,12 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
public abstract class AbstractDhLevel implements IDhLevel
{
@@ -59,6 +62,8 @@ public abstract class AbstractDhLevel implements IDhLevel
@Nullable
public BeaconBeamRepo beaconBeamRepo;
protected final KeyedLockContainer<Long> beaconUpdateLockContainer = new KeyedLockContainer<>();
protected final DelayedFullDataSourceSaveCache delayedFullDataSourceSaveCache = new DelayedFullDataSourceSaveCache(this::onDataSourceSaveAsync, 3_000);
/** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save */
protected final ConcurrentHashMap<Long, HashSet<DhChunkPos>> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>();
@@ -67,7 +72,6 @@ public abstract class AbstractDhLevel implements IDhLevel
/** Will be null if clouds shouldn't be rendered for this level. */
@Nullable
protected CloudRenderHandler cloudRenderHandler;
protected BeaconBeamDataHandler beaconBeamDataHandler;
@@ -126,13 +130,6 @@ public abstract class AbstractDhLevel implements IDhLevel
}
}
}
// shouldn't happen, but just in case
if (this.beaconBeamRepo != null)
{
this.beaconBeamDataHandler = new BeaconBeamDataHandler(this.beaconBeamRepo, genericRenderer);
}
}
@@ -228,31 +225,139 @@ public abstract class AbstractDhLevel implements IDhLevel
//=================//
@Override
public void updateBeaconBeamsForChunk(IChunkWrapper chunkToUpdate, ArrayList<IChunkWrapper> nearbyChunkList)
public void updateBeaconBeamsForSectionPos(long sectionPos, List<BeaconBeamDTO> activeBeamList)
{
if (this.beaconBeamDataHandler != null)
int minBlockX = DhSectionPos.getMinCornerBlockX(sectionPos);
int minBlockZ = DhSectionPos.getMinCornerBlockZ(sectionPos);
// TODO special logic had to be done for DhChunkPos.getMaxBlock,
// does that need to be done here?
// The DhChunkPos issue caused beacons to appear/disappear incorrectly on negative chunk borders
int maxBlockX = minBlockX + DhSectionPos.getBlockWidth(sectionPos);
int maxBlockZ = minBlockZ + DhSectionPos.getBlockWidth(sectionPos);
this.updateBeaconBeamsBetweenBlockPos(
sectionPos,
minBlockX, minBlockZ,
maxBlockX, maxBlockZ,
activeBeamList
);
}
@Override
public void updateBeaconBeamsForChunkPos(DhChunkPos chunkPos, List<BeaconBeamDTO> activeBeamList)
{
long sectionPos = DhSectionPos.encodeContaining(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, chunkPos);
int minBlockX = chunkPos.getMinBlockX();
int minBlockZ = chunkPos.getMinBlockZ();
int maxBlockX = chunkPos.getMaxBlockX();
int maxBlockZ = chunkPos.getMaxBlockZ();
//LOGGER.info("beacons ["+activeBeamList.size()+"] at ["+chunkPos+"] x["+minBlockX+"]-["+maxBlockX+"] z["+minBlockZ+"]-["+maxBlockZ+"].");
this.updateBeaconBeamsBetweenBlockPos(
sectionPos,
minBlockX, maxBlockX,
minBlockZ, maxBlockZ,
activeBeamList
);
}
private void updateBeaconBeamsBetweenBlockPos(
long sectionPosForLock,
int minBlockX, int maxBlockX,
int minBlockZ, int maxBlockZ,
List<BeaconBeamDTO> activeBeamList
) // TODO min/max block pos instead
{
if (this.beaconBeamRepo == null)
{
List<BeaconBeamDTO> activeBeamList = chunkToUpdate.getAllActiveBeacons(nearbyChunkList);
this.beaconBeamDataHandler.setBeaconBeamsForChunk(chunkToUpdate.getChunkPos(), activeBeamList);
return;
}
// locked to prevent two threads from updating the same section at the same time
ReentrantLock lock = this.beaconUpdateLockContainer.getLockForPos(sectionPosForLock);
try
{
lock.lock();
HashSet<DhBlockPos> allPosSet = new HashSet<>();
// sort new beams
HashMap<DhBlockPos, BeaconBeamDTO> activeBeamByPos = new HashMap<>(activeBeamList.size());
for (BeaconBeamDTO beam : activeBeamList)
{
activeBeamByPos.put(beam.blockPos, beam);
allPosSet.add(beam.blockPos);
}
// get existing beams
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsInBlockPosRange(
minBlockX, maxBlockX,
minBlockZ, maxBlockZ);
HashMap<DhBlockPos, BeaconBeamDTO> existingBeamByPos = new HashMap<>(existingBeamList.size());
for (BeaconBeamDTO beam : existingBeamList)
{
existingBeamByPos.put(beam.blockPos, beam);
allPosSet.add(beam.blockPos);
}
for (DhBlockPos beaconPos : allPosSet)
{
if (minBlockX <= beaconPos.getX() && beaconPos.getX() <= maxBlockX
&& minBlockZ <= beaconPos.getZ() && beaconPos.getZ() <= maxBlockZ)
{
//// don't modify beacons outside the updated range
//continue;
}
else
{
continue;
}
BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos);
BeaconBeamDTO activeBeam = activeBeamByPos.get(beaconPos);
if (activeBeam != null)
{
//LOGGER.info("add beacon ["+activeBeam.blockPos+"] x["+minBlockX+"]-["+maxBlockX+"] z["+minBlockZ+"]-["+maxBlockZ+"].");
if (existingBeam == null)
{
// new beam found, add to DB
this.beaconBeamRepo.save(activeBeam);
}
else
{
// beam still exists in chunk
if (!existingBeam.color.equals(activeBeam.color))
{
// beam colors were changed
this.beaconBeamRepo.save(activeBeam);
}
}
}
else if (existingBeam != null)
{
// beam no longer exists at position, remove from DB
this.beaconBeamRepo.deleteWithKey(beaconPos);
//LOGGER.info("remove beacon ["+beaconPos+"] x["+minBlockX+"]-["+maxBlockX+"] z["+minBlockZ+"]-["+maxBlockZ+"].");
}
}
}
finally
{
lock.unlock();
}
}
@Override
public void loadBeaconBeamsInPos(long pos)
{
if (this.beaconBeamDataHandler != null)
{
this.beaconBeamDataHandler.loadBeaconBeamsInPos(pos);
}
}
@Override
public void unloadBeaconBeamsInPos(long pos)
{
if (this.beaconBeamDataHandler != null)
{
this.beaconBeamDataHandler.unloadBeaconBeamsInPos(pos);
}
}
@Nullable
public BeaconBeamRepo getBeaconBeamRepo() { return this.beaconBeamRepo; }
@@ -24,7 +24,6 @@ import com.seibel.distanthorizons.core.config.AppliedConfigState;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.file.beacon.BeaconBeamDataHandler;
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
import com.seibel.distanthorizons.core.file.fullDatafile.RemoteFullDataSourceProvider;
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
@@ -144,7 +143,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
return;
}
this.beaconBeamDataHandler.setBeaconBeamsForPos(dataSourceDto.pos, message.payload.beaconBeams);
this.updateBeaconBeamsForSectionPos(dataSourceDto.pos, message.payload.beaconBeams);
this.updateDataSourcesAsync(dataSourceDto.createDataSource(this.levelWrapper));
}
catch (Exception e)
@@ -283,7 +282,6 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get();
return (renderState != null) ? renderState.renderBufferHandler : null;
}
public BeaconBeamDataHandler getBeaconBeamDataHandler() { return this.beaconBeamDataHandler; }
@@ -26,6 +26,8 @@ import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import org.jetbrains.annotations.Nullable;
@@ -50,9 +52,16 @@ public interface IDhLevel extends AutoCloseable, GeneratedFullDataSourceProvider
int getChunkHash(DhChunkPos pos);
void updateChunkAsync(IChunkWrapper chunk, int newChunkHash);
void loadBeaconBeamsInPos(long pos);
void updateBeaconBeamsForChunk(IChunkWrapper chunkToUpdate, ArrayList<IChunkWrapper> nearbyChunkList);
void unloadBeaconBeamsInPos(long pos);
default void updateBeaconBeamsForChunk(IChunkWrapper chunkToUpdate, ArrayList<IChunkWrapper> nearbyChunkList)
{
List<BeaconBeamDTO> activeBeamList = chunkToUpdate.getAllActiveBeacons(nearbyChunkList);
this.updateBeaconBeamsForChunkPos(chunkToUpdate.getChunkPos(), activeBeamList);
}
void updateBeaconBeamsForChunkPos(DhChunkPos chunkPos, List<BeaconBeamDTO> activeBeamList);
void updateBeaconBeamsForSectionPos(long sectionPos, List<BeaconBeamDTO> activeBeamList);
@Nullable
BeaconBeamRepo getBeaconBeamRepo();
FullDataSourceProviderV2 getFullDataProvider();
@@ -239,7 +239,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
{
try
{
this.level.getBeaconBeamDataHandler().setBeaconBeamsForPos(dataSourceDto.pos, response.payload.beaconBeams);
this.level.updateBeaconBeamsForSectionPos(dataSourceDto.pos, response.payload.beaconBeams);
try (FullDataSourceV2 fullDataSource = dataSourceDto.createDataSource(this.level.getLevelWrapper()))
{
entry.dataSourceConsumer.accept(fullDataSource);
@@ -83,6 +83,19 @@ public class DhChunkPos
public int getMinBlockX() { return this.x << 4; }
public int getMinBlockZ() { return this.z << 4; }
public int getMaxBlockX()
{
int minBlockPos = this.getMinBlockX() + LodUtil.CHUNK_WIDTH;
minBlockPos += (minBlockPos < 0) ? -1 : 0;
return minBlockPos;
}
public int getMaxBlockZ()
{
int minBlockPos = this.getMinBlockZ() + LodUtil.CHUNK_WIDTH;
minBlockPos += (minBlockPos < 0) ? -1 : 0;
return minBlockPos;
}
public DhBlockPos2D getMinBlockPos() { return new DhBlockPos2D(this.x << 4, this.z << 4); }
public boolean contains(DhBlockPos pos)
@@ -92,8 +105,8 @@ public class DhChunkPos
int maxBlockX = minBlockX + LodUtil.CHUNK_WIDTH;
int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH;
return minBlockX <= pos.getX() && pos.getX() < maxBlockX
&& minBlockZ <= pos.getZ() && pos.getZ() < maxBlockZ;
return minBlockX >= pos.getX() && pos.getX() < maxBlockX
&& minBlockZ >= pos.getZ() && pos.getZ() < maxBlockZ;
}
public double distance(DhChunkPos other)
@@ -34,6 +34,8 @@ import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler;
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
import com.seibel.distanthorizons.core.util.KeyedLockContainer;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.ThreadUtil;
@@ -43,6 +45,7 @@ import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.coreapi.util.MathUtil;
import it.unimi.dsi.fastutil.longs.LongIterator;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import javax.annotation.WillNotClose;
import java.awt.*;
@@ -138,6 +141,9 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
})
.<Long, ColumnRenderSource>build();
@Nullable
public final BeaconRenderHandler beaconRenderHandler;
/** the smallest numerical detail level number that can be rendered */
private byte maxRenderDetailLevel;
@@ -167,6 +173,10 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
this.level = level;
this.fullDataSourceProvider = fullDataSourceProvider;
this.blockRenderDistanceDiameter = viewDiameterInBlocks;
GenericObjectRenderer genericObjectRenderer = this.level.getGenericRenderer();
this.beaconRenderHandler = (genericObjectRenderer != null) ? new BeaconRenderHandler(genericObjectRenderer) : null;
}
@@ -340,9 +350,11 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
}
else
{
// onRenderingDisabled() needs to be fired before the children are enabled so beacons render correctly
// children are all loaded, unload this and parents
if (renderSection.getRenderingEnabled())
{
// needs to be fired before the children are enabled so beacons render correctly
renderSection.onRenderingDisabled();
@@ -463,7 +475,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
}
});
// onRenderingEnabled() needs to be fired after the children are disabled so beacons render correctly
// needs to be fired after the children are disabled so beacons render correctly
renderSection.onRenderingEnabled();
}
@@ -38,6 +38,9 @@ import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.ColumnRenderBuffer;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
import com.seibel.distanthorizons.core.util.KeyedLockContainer;
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
@@ -49,6 +52,7 @@ import org.jetbrains.annotations.Nullable;
import javax.annotation.WillNotClose;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@@ -83,6 +87,15 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
private final KeyedLockContainer<Long> renderLoadLockContainer;
private final Cache<Long, ColumnRenderSource> cachedRenderSourceByPos;
/**
* contains the list of beacons currently being rendered in this section
* if this list is modified the {@link LodRenderSection#beaconRenderHandler} should be updated to match.
*/
private final List<BeaconBeamDTO> activeBeaconList = new ArrayList<>();
@Nullable
public final BeaconRenderHandler beaconRenderHandler;
@Nullable
public final BeaconBeamRepo beaconBeamRepo;
private boolean renderingEnabled = false;
@@ -139,6 +152,9 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
this.level = level;
this.fullDataSourceProvider = fullDataSourceProvider;
this.beaconRenderHandler = this.quadTree.beaconRenderHandler;
this.beaconBeamRepo = this.level.getBeaconBeamRepo();
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
}
@@ -193,6 +209,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
this.getAndBuildRenderDataRunnable = () ->
{
this.getAndRefreshRenderingBeacons();
this.getAndUploadRenderDataToGpu();
// the future is passed in separate to prevent any possible race condition null pointers
@@ -350,25 +367,24 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
public void setRenderingEnabled(boolean enabled) { this.renderingEnabled = enabled;}
/** @see LodRenderSection#setRenderingEnabled */
public void onRenderingEnabled() { this.level.loadBeaconBeamsInPos(this.pos); }
public void onRenderingEnabled() { this.startRenderingBeacons(); }
/** @see LodRenderSection#setRenderingEnabled */
public void onRenderingDisabled()
{
this.level.unloadBeaconBeamsInPos(this.pos);
this.stopRenderingBeacons();
if (Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus.get())
{
// show that this position has just been disabled
DebugRenderer.makeParticle(
new DebugRenderer.BoxParticle(
new DebugRenderer.Box(this.pos, 128f, 156f, 0.09f, Color.CYAN.darker()),
0.2, 32f
)
new DebugRenderer.BoxParticle(
new DebugRenderer.Box(this.pos, 128f, 156f, 0.09f, Color.CYAN.darker()),
0.2, 32f
)
);
}
}
public boolean gpuUploadInProgress() { return this.getAndBuildRenderDataFuture != null; }
@@ -465,6 +481,85 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
//=================//
// beacon handling //
//=================//
/** gets the active beacon list and stops/starts beacon rendering as necessary */
private void getAndRefreshRenderingBeacons()
{
// do nothing if beacon rendering or repos are unavailable
if (this.beaconBeamRepo == null
|| this.beaconRenderHandler == null)
{
return;
}
// Synchronized to prevent two threads for starting/stopping rendering at once
// Shouldn't be necessary, but just in case.
synchronized (this.activeBeaconList)
{
List<BeaconBeamDTO> activeBeacons = this.beaconBeamRepo.getAllBeamsForPos(this.pos);
// stop rendering current beacons
for (BeaconBeamDTO beam : this.activeBeaconList)
{
this.beaconRenderHandler.stopRenderingBeaconAtPos(beam.blockPos);
}
// swap old and new active beacon list
this.activeBeaconList.clear();
this.activeBeaconList.addAll(activeBeacons);
// start rendering new beacon list
for (BeaconBeamDTO beam : this.activeBeaconList)
{
this.beaconRenderHandler.startRenderingBeacon(beam);
}
}
}
private void stopRenderingBeacons()
{
// do nothing if beacon rendering is unavailable
if (this.beaconRenderHandler == null)
{
return;
}
synchronized (this.activeBeaconList)
{
for (BeaconBeamDTO beam : this.activeBeaconList)
{
this.beaconRenderHandler.stopRenderingBeaconAtPos(beam.blockPos);
}
}
}
private void startRenderingBeacons()
{
// do nothing if beacon rendering is unavailable
if (this.beaconRenderHandler == null)
{
return;
}
synchronized (this.activeBeaconList)
{
for (BeaconBeamDTO beam : this.activeBeaconList)
{
this.beaconRenderHandler.startRenderingBeacon(beam);
}
}
}
//==============//
// base methods //
//==============//
@@ -514,7 +609,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
}
this.level.unloadBeaconBeamsInPos(this.pos);
this.stopRenderingBeacons();
if (this.renderBuffer != null)
{
@@ -551,6 +646,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
// while this should generally be a fast operation
// this is run on a separate thread to prevent lag on the render thread
executor.execute(() -> this.fullDataSourceProvider.removeRetrievalRequestIf((genPos) -> DhSectionPos.contains(this.pos, genPos)));
}
@@ -174,8 +174,8 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH;
return this.getAllBeamsInBlockPosRange(
minBlockX, minBlockZ,
maxBlockX, maxBlockZ
minBlockX, maxBlockX,
minBlockZ, maxBlockZ
);
}
@@ -187,8 +187,8 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
int maxBlockZ = minBlockZ + DhSectionPos.getBlockWidth(pos);
return this.getAllBeamsInBlockPosRange(
minBlockX, minBlockZ,
maxBlockX, maxBlockZ
minBlockX, maxBlockX,
minBlockZ, maxBlockZ
);
}
@@ -199,8 +199,8 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
"? <= BlockPosX AND BlockPosX <= ? AND " +
"? <= BlockPosZ AND BlockPosZ <= ?";
public List<BeaconBeamDTO> getAllBeamsInBlockPosRange(
int minBlockX, int minBlockZ,
int maxBlockX, int maxBlockZ
int minBlockX, int maxBlockX,
int minBlockZ, int maxBlockZ
)
{
ArrayList<BeaconBeamDTO> beamList = new ArrayList<>();
@@ -214,8 +214,8 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
int i = 1;
statement.setInt(i++, minBlockX);
statement.setInt(i++, minBlockZ);
statement.setInt(i++, maxBlockX);
statement.setInt(i++, minBlockZ);
statement.setInt(i++, maxBlockZ);