Fix beacons un-loading incorrectly in some situations

Specifically neighboring chunks updating and in some cases flying away too fast
This commit is contained in:
James Seibel
2024-07-02 07:50:21 -05:00
parent e91afc17a3
commit 55cb4595bd
8 changed files with 152 additions and 15 deletions
@@ -26,10 +26,8 @@ import com.seibel.distanthorizons.core.generation.DhLightingEngine;
import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.util.TimerUtil;
@@ -350,7 +348,7 @@ public class SharedApi
// get this chunk's active beacons
List<BeaconBeamDTO> beaconBeamList = chunkWrapper.getAllActiveBeacons();
dhLevel.ensureBeaconBeamsAtPos(DhSectionPos.encode(chunkWrapper.getChunkPos()), beaconBeamList);
dhLevel.setBeaconBeamsForChunk(chunkWrapper.getChunkPos(), beaconBeamList);
dhLevel.updateChunkAsync(chunkWrapper);
@@ -48,6 +48,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractDhLevel implements IDhLevel
{
@@ -199,11 +200,13 @@ public abstract class AbstractDhLevel implements IDhLevel
}
HashMap<DhBlockPos, IDhApiRenderableBoxGroup> beamRenderGroupByPos = new HashMap<>();
HashMap<DhBlockPos, IDhApiRenderableBoxGroup> beamRenderGroupByBlockPos = new HashMap<>();
HashMap<DhBlockPos, AtomicInteger> beamRefCountByPos = new HashMap<>();
@Override
public void ensureBeaconBeamsAtPos(long pos, List<BeaconBeamDTO> newBeamList)
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> newBeamList)
{
long pos = DhSectionPos.encode(chunkPos);
if (this.beaconBeamRepo != null)
{
HashSet<DhBlockPos> allPosSet = new HashSet<>();
@@ -231,6 +234,12 @@ public abstract class AbstractDhLevel implements IDhLevel
for (DhBlockPos beaconPos : allPosSet)
{
if (!chunkPos.contains(beaconPos))
{
// don't update beacons outside the updated chunk
continue;
}
BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos);
BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos);
@@ -245,19 +254,31 @@ public abstract class AbstractDhLevel implements IDhLevel
IDhApiRenderableBoxGroup beaconBox = GenericObjectRenderer.INSTANCE.createForSingleBox(new DhApiRenderableBox(
new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z),
new DhApiVec3f(newBeam.pos.x+1, 2_000, newBeam.pos.z+1),
new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1),
newBeam.color
));
beaconBox.setBlockLight(LodUtil.MAX_MC_LIGHT);
beaconBox.setSkyLight(LodUtil.MAX_MC_LIGHT);
this.beamRenderGroupByPos.put(newBeam.pos, beaconBox);
this.beamRenderGroupByBlockPos.put(newBeam.pos, beaconBox);
this.beamRefCountByPos.compute(newBeam.pos, (beamPos, refCount) ->
{
if (refCount == null)
{
refCount = new AtomicInteger(0);
}
refCount.getAndIncrement();
return refCount;
});
GenericObjectRenderer.INSTANCE.add(beaconBox);
}
else if (existingBeam != null && newBeam == null)
{
// beam no longer exists at position, remove
this.beaconBeamRepo.deleteWithKey(beaconPos);
IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByPos.remove(existingBeam.pos);
this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks
this.beamRefCountByPos.remove(existingBeam.pos);
IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByBlockPos.remove(existingBeam.pos);
if (beaconBox != null)
{
GenericObjectRenderer.INSTANCE.remove(beaconBox.getId());
@@ -269,6 +290,81 @@ public abstract class AbstractDhLevel implements IDhLevel
}
}
@Override
public void loadBeaconBeamsInPos(long pos)
{
if (this.beaconBeamRepo != null)
{
// get beams in pos
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForSectionPos(pos);
for (int i = 0; i < existingBeamList.size(); i++)
{
BeaconBeamDTO beam = existingBeamList.get(i);
IDhApiRenderableBoxGroup beaconBox = GenericObjectRenderer.INSTANCE.createForSingleBox(new DhApiRenderableBox(
new DhApiVec3f(beam.pos.x, beam.pos.y+1, beam.pos.z),
new DhApiVec3f(beam.pos.x+1, 6_000, beam.pos.z+1),
beam.color
));
beaconBox.setBlockLight(LodUtil.MAX_MC_LIGHT);
beaconBox.setSkyLight(LodUtil.MAX_MC_LIGHT);
this.beamRefCountByPos.compute(beam.pos, (beamPos, refCount) ->
{
if (refCount == null)
{
refCount = new AtomicInteger(0);
}
if (refCount.getAndIncrement() == 0)
{
this.beamRenderGroupByBlockPos.put(beam.pos, beaconBox);
GenericObjectRenderer.INSTANCE.add(beaconBox);
}
return refCount;
});
}
}
}
@Override
public void unloadBeaconBeamsInPos(long pos)
{
if (this.beaconBeamRepo != null)
{
// get beams in pos
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForSectionPos(pos);
for (int i = 0; i < existingBeamList.size(); i++)
{
BeaconBeamDTO beam = existingBeamList.get(i);
// beam no longer exists at position, remove
this.beamRefCountByPos.compute(beam.pos, (beamPos, refCount) ->
{
if (refCount == null)
{
return null;
}
if (refCount.decrementAndGet() == 0)
{
IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByBlockPos.remove(beam.pos);
if (beaconBox != null)
{
GenericObjectRenderer.INSTANCE.remove(beaconBox.getId());
}
return null;
}
else
{
return refCount;
}
});
}
}
}
//================//
@@ -22,7 +22,6 @@ package com.seibel.distanthorizons.core.level;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
@@ -46,8 +45,10 @@ public interface IDhLevel extends AutoCloseable
void setChunkHash(DhChunkPos pos, int chunkHash);
void updateChunkAsync(IChunkWrapper chunk);
void loadBeaconBeamsInPos(long pos);
List<BeaconBeamDTO> getAllBeamsForSectionPos(long pos);
void ensureBeaconBeamsAtPos(long pos, List<BeaconBeamDTO> beamList);
void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> beamList);
void unloadBeaconBeamsInPos(long pos);
FullDataSourceProviderV2 getFullDataProvider();
@@ -19,6 +19,8 @@
package com.seibel.distanthorizons.core.pos;
import com.seibel.distanthorizons.core.util.LodUtil;
public class DhChunkPos
{
public final int x; // Low 32 bits
@@ -29,6 +31,10 @@ public class DhChunkPos
//==============//
// constructors //
//==============//
public DhChunkPos(int x, int z)
{
this.x = x;
@@ -51,6 +57,10 @@ public class DhChunkPos
//=========//
// methods //
//=========//
public DhBlockPos center() { return new DhBlockPos(8 + this.x << 4, 0, 8 + this.z << 4); }
public DhBlockPos corner() { return new DhBlockPos(this.x << 4, 0, this.z << 4); }
@@ -64,8 +74,24 @@ public class DhChunkPos
public DhBlockPos2D getMinBlockPos() { return new DhBlockPos2D(this.x << 4, this.z << 4); }
public boolean contains(DhBlockPos pos)
{
int minBlockX = this.getMinBlockX();
int minBlockZ = this.getMinBlockZ();
int maxBlockX = minBlockX + LodUtil.CHUNK_WIDTH;
int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH;
return minBlockX <= pos.x && pos.x <= maxBlockX
&& minBlockZ <= pos.z && pos.z <= maxBlockZ;
}
public long getLong() { return toLong(this.x, this.z); }
//================//
// base overrides //
//================//
@Override
public boolean equals(Object obj)
{
@@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.pos.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.sql.repo.BeaconBeamRepo;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.ThreadUtil;
import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode;
@@ -329,6 +330,10 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
}
// all child positions are loaded, disable this section and enable its children.
if (renderSection.renderingEnabled)
{
this.level.unloadBeaconBeamsInPos(renderSection.pos);
}
renderSection.renderingEnabled = false;
// walk back down the tree and enable the child sections //TODO there are probably more efficient ways of doing this, but this will work for now
@@ -383,6 +388,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
if (!renderSection.renderingEnabled)
{
renderSection.renderingEnabled = true;
this.level.loadBeaconBeamsInPos(renderSection.pos);
// delete/disable children, all of them will be a lower detail level than requested
quadNode.deleteAllChildren((childRenderSection) ->
@@ -19,6 +19,9 @@
package com.seibel.distanthorizons.core.render;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
@@ -28,11 +31,16 @@ import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
import com.seibel.distanthorizons.core.level.IDhClientLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer;
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.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import org.apache.logging.log4j.Logger;
@@ -41,6 +49,7 @@ import org.jetbrains.annotations.Nullable;
import javax.annotation.WillNotClose;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
@@ -416,6 +425,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
}
this.level.unloadBeaconBeamsInPos(this.pos);
if (this.renderBuffer != null)
{
@@ -121,7 +121,7 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
"UPDATE "+this.getTableName()+" \n" +
"SET \n" +
" ColorR = ?, ColorG = ?, ColorB = ?, \n" +
" ,LastModifiedUnixDateTime = ? \n" +
" LastModifiedUnixDateTime = ? \n" +
"WHERE BlockPosX = ? AND BlockPosY = ? AND BlockPosZ = ?";
PreparedStatement statement = this.createPreparedStatement(sql);
@@ -254,11 +254,11 @@ public interface IChunkWrapper extends IBindable
ArrayList<DhBlockPos> blockPosList = this.getBlockLightPosList();
for (int i = 0; i < blockPosList.size(); i++)
{
DhBlockPos pos = blockPosList.get(i).convertToChunkRelativePos();
IBlockStateWrapper block = this.getBlockState(pos);
DhBlockPos pos = blockPosList.get(i);
IBlockStateWrapper block = this.getBlockState(pos.convertToChunkRelativePos());
if (block.getSerialString().toLowerCase().contains("minecraft:beacon"))
{
BeaconBeamDTO beam = new BeaconBeamDTO(pos, Color.WHITE); // TODO
BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), Color.WHITE);
beaconPosList.add(beam);
}
}