Decouple beacon beam data handling from render handling, send beacon beams to clients

This commit is contained in:
s809
2024-10-05 14:03:02 +05:00
parent 0b49d1a007
commit c1a405b755
14 changed files with 297 additions and 155 deletions
@@ -31,7 +31,7 @@ public final class ModInfo
public static final String DEDICATED_SERVER_INITIAL_PATH = "dedicated_server_initial";
/** Incremented every time any packets are added, changed or removed, with a few exceptions. */
public static final int PROTOCOL_VERSION = 4;
public static final int PROTOCOL_VERSION = 5;
public static final String WRAPPER_PACKET_PATH = "message";
/** The internal mod name */
@@ -0,0 +1,166 @@
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.LodUtil;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
public class BeaconBeamDataHandler
{
private final BeaconBeamRepo beaconBeamRepo;
@Nullable
private BeaconRenderHandler beaconRenderHandler;
//=============//
// 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)
{
// synchronized to prevent two threads from updating the same chunk at the same time
synchronized (this)
{
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);
}
}
}
}
}
//===================//
// 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);
}
}
}
@@ -3,7 +3,7 @@ package com.seibel.distanthorizons.core.generation;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker;
import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult;
import com.seibel.distanthorizons.core.level.IDhClientLevel;
import com.seibel.distanthorizons.core.level.DhClientLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.multiplayer.client.AbstractFullDataNetworkRequestQueue;
import com.seibel.distanthorizons.core.multiplayer.client.ClientNetworkState;
@@ -26,7 +26,7 @@ public class RemoteWorldRetrievalQueue extends AbstractFullDataNetworkRequestQue
// constructor //
//=============//
public RemoteWorldRetrievalQueue(ClientNetworkState networkState, IDhClientLevel level)
public RemoteWorldRetrievalQueue(ClientNetworkState networkState, DhClientLevel level)
{ super(networkState, level, false, Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue); }
@@ -21,6 +21,7 @@ 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;
@@ -66,7 +67,7 @@ public abstract class AbstractDhLevel implements IDhLevel
/** Will be null if clouds shouldn't be rendered for this level. */
@Nullable
protected CloudRenderHandler cloudRenderHandler;
protected BeaconRenderHandler beaconRenderHandler;
protected BeaconBeamDataHandler beaconBeamDataHandler;
@@ -124,13 +125,13 @@ public abstract class AbstractDhLevel implements IDhLevel
this.cloudRenderHandler = new CloudRenderHandler((IDhClientLevel)this, genericRenderer);
}
}
// shouldn't happen, but just in case
if (this.beaconBeamRepo != null)
{
this.beaconRenderHandler = new BeaconRenderHandler(this.beaconBeamRepo, genericRenderer);
}
}
// shouldn't happen, but just in case
if (this.beaconBeamRepo != null)
{
this.beaconBeamDataHandler = new BeaconBeamDataHandler(this.beaconBeamRepo, genericRenderer);
}
}
@@ -228,27 +229,27 @@ public abstract class AbstractDhLevel implements IDhLevel
@Override
public void updateBeaconBeamsForChunk(IChunkWrapper chunkToUpdate, ArrayList<IChunkWrapper> nearbyChunkList)
{
if (this.beaconRenderHandler != null)
if (this.beaconBeamDataHandler != null)
{
List<BeaconBeamDTO> activeBeamList = chunkToUpdate.getAllActiveBeacons(nearbyChunkList);
this.beaconRenderHandler.setBeaconBeamsForChunk(chunkToUpdate.getChunkPos(), activeBeamList);
this.beaconBeamDataHandler.setBeaconBeamsForChunk(chunkToUpdate.getChunkPos(), activeBeamList);
}
}
@Override
public void loadBeaconBeamsInPos(long pos)
{
if (this.beaconRenderHandler != null)
if (this.beaconBeamDataHandler != null)
{
this.beaconRenderHandler.loadBeaconBeamsInPos(pos);
this.beaconBeamDataHandler.loadBeaconBeamsInPos(pos);
}
}
@Override
public void unloadBeaconBeamsInPos(long pos)
{
if (this.beaconRenderHandler != null)
if (this.beaconBeamDataHandler != null)
{
this.beaconRenderHandler.unloadBeaconBeamsInPos(pos);
this.beaconBeamDataHandler.unloadBeaconBeamsInPos(pos);
}
}
@@ -32,6 +32,7 @@ import org.apache.logging.log4j.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.*;
public abstract class AbstractDhServerLevel extends AbstractDhLevel implements IDhServerLevel
@@ -126,7 +127,8 @@ public abstract class AbstractDhServerLevel extends AbstractDhLevel implements I
}
CompletableFuture.runAsync(() ->
{
FullDataPayload payload = new FullDataPayload(requestGroup.fullDataSource);
Objects.requireNonNull(this.beaconBeamRepo);
FullDataPayload payload = new FullDataPayload(requestGroup.fullDataSource, this.beaconBeamRepo.getAllBeamsForPos(entry.getKey()));
for (FullDataSourceRequestMessage msg : requestGroup.requestMessages.values())
{
this.requestGroupByFutureId.remove(msg.futureId);
@@ -273,7 +275,8 @@ public abstract class AbstractDhServerLevel extends AbstractDhLevel implements I
{
rateLimiterSet.syncOnLoginRateLimiter.release();
FullDataPayload payload = new FullDataPayload(fullDataSource);
Objects.requireNonNull(this.beaconBeamRepo);
FullDataPayload payload = new FullDataPayload(fullDataSource, this.beaconBeamRepo.getAllBeamsForPos(message.sectionPos));
payload.splitAndSend(FULL_DATA_SPLIT_SIZE_IN_BYTES, message.getSession()::sendMessage);
message.sendResponse(new FullDataSourceResponseMessage(payload));
}, executor);
@@ -412,7 +415,8 @@ public abstract class AbstractDhServerLevel extends AbstractDhLevel implements I
}
CompletableFuture.runAsync(() ->
{
FullDataPayload payload = new FullDataPayload(data);
Objects.requireNonNull(this.beaconBeamRepo);
FullDataPayload payload = new FullDataPayload(data, this.beaconBeamRepo.getAllBeamsForPos(data.getPos()));
for (ServerPlayerState serverPlayerState : this.serverPlayerStateManager.getReadyPlayers())
{
if (serverPlayerState.getServerPlayer().getLevel() != this.serverLevelWrapper)
@@ -24,6 +24,7 @@ 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;
@@ -138,6 +139,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
return;
}
this.beaconBeamDataHandler.setBeaconBeamsForPos(dataSourceDto.pos, message.payload.beaconBeams);
this.updateDataSourcesAsync(dataSourceDto.createPooledDataSource(this.levelWrapper));
}
catch (Exception e)
@@ -276,6 +278,7 @@ 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; }
@@ -360,7 +363,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
private static class WorldGenState extends WorldGenModule.AbstractWorldGenState
{
WorldGenState(IDhClientLevel level, ClientNetworkState networkState)
WorldGenState(DhClientLevel level, ClientNetworkState networkState)
{
this.worldGenerationQueue = new RemoteWorldRetrievalQueue(networkState, level);
}
@@ -5,8 +5,7 @@ import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.level.DhServerLevel;
import com.seibel.distanthorizons.core.level.IDhClientLevel;
import com.seibel.distanthorizons.core.level.DhClientLevel;
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
import com.seibel.distanthorizons.core.network.exceptions.InvalidLevelException;
import com.seibel.distanthorizons.core.network.exceptions.RateLimitedException;
@@ -56,7 +55,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
public final ClientNetworkState networkState;
protected final IDhClientLevel level;
protected final DhClientLevel level;
private final boolean changedOnly;
private volatile CompletableFuture<Void> closingFuture = null;
@@ -84,7 +83,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
//=============//
public AbstractFullDataNetworkRequestQueue(
ClientNetworkState networkState, IDhClientLevel level,
ClientNetworkState networkState, DhClientLevel level,
boolean changedOnly, ConfigEntry<Boolean> showDebugWireframeConfig)
{
this.networkState = networkState;
@@ -206,6 +205,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
{
try
{
this.level.getBeaconBeamDataHandler().setBeaconBeamsForPos(dataSourceDto.pos, response.payload.beaconBeams);
FullDataSourceV2 fullDataSource = dataSourceDto.createPooledDataSource(this.level.getLevelWrapper());
entry.dataSourceConsumer.accept(fullDataSource);
FullDataSourceV2.DATA_SOURCE_POOL.returnPooledDataSource(fullDataSource);
@@ -2,7 +2,7 @@ package com.seibel.distanthorizons.core.multiplayer.client;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.generation.RemoteWorldRetrievalQueue;
import com.seibel.distanthorizons.core.level.IDhClientLevel;
import com.seibel.distanthorizons.core.level.DhClientLevel;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
/**
@@ -20,7 +20,7 @@ public class SyncOnLoginRequestQueue extends AbstractFullDataNetworkRequestQueue
// constructor //
//=============//
public SyncOnLoginRequestQueue(IDhClientLevel level, ClientNetworkState networkState)
public SyncOnLoginRequestQueue(DhClientLevel level, ClientNetworkState networkState)
{ super(networkState, level, true, Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue); }
@@ -98,21 +98,21 @@ public interface INetworkObject
// collections //
default <T> void writeCollection(ByteBuf outputByteBuf, Collection<T> collection)
default void writeCollection(ByteBuf outputByteBuf, Collection<?> collection)
{
outputByteBuf.writeInt(collection.size());
this.writeFixedLengthCollection(outputByteBuf, collection);
}
default <T> void writeFixedLengthCollection(ByteBuf outputByteBuf, Collection<T> collection)
default void writeFixedLengthCollection(ByteBuf outputByteBuf, Collection<?> collection)
{
for (T item : collection)
for (Object item : collection)
{
Codec codec = Codec.getCodec(item.getClass());
codec.encode.accept(item, outputByteBuf);
}
}
default <T> void readCollection(ByteBuf inputByteBuf, Collection<T> collection, Supplier<T> innerValueConstructor)
default <TCollection extends Collection<T>, T> TCollection readCollection(ByteBuf inputByteBuf, TCollection collection, Supplier<T> innerValueConstructor)
{
int size = inputByteBuf.readInt();
@@ -130,9 +130,11 @@ public interface INetworkObject
collection.add(item);
}
return collection;
}
default <K, V> void readMap(ByteBuf inputByteBuf, Map<K, V> map, Supplier<K> keySupplier, Supplier<V> valueSupplier)
default <TMap extends Map<K, V>, K, V> TMap readMap(ByteBuf inputByteBuf, TMap map, Supplier<K> keySupplier, Supplier<V> valueSupplier)
{
ArrayList<Map.Entry<K, V>> entryList = new ArrayList<>();
@@ -141,6 +143,8 @@ public interface INetworkObject
{
map.put(entry.getKey(), entry.getValue());
}
return map;
}
@@ -150,11 +154,10 @@ public interface INetworkObject
//================//
/**
* Defines (de)serialization for different classes,
* specifically for base classes like {@link Integer}, {@link Boolean}, and {@link String}. <br><br>
*
* Should only be used for non-editable classes;
* otherwise, you may want to implement {@link INetworkObject} and use its methods where applicable.
* Defines (de)serialization for classes that cannot be directly edited,
* specifically for primitives, Java and third-party library classes and other types.
* <p>
* If you're able to edit the target class yourself, implement {@link INetworkObject} and use its methods where applicable instead.
*/
class Codec
{
@@ -209,18 +212,18 @@ public interface INetworkObject
public static <T> Codec getCodec(Class<T> clazz)
{
return CODEC_MAP.computeIfAbsent(clazz, ignored ->
{
// TODO when would this ever return true?
return CODEC_MAP.computeIfAbsent(clazz, classToAdd -> {
// Check if the class is a subclass of any existing key in the map.
// If it is, return the existing codec and bind it to this class for faster future searches.
for (Map.Entry<Class<?>, Codec> entry : CODEC_MAP.entrySet())
{
if (entry.getKey().isAssignableFrom(clazz))
if (entry.getKey().isAssignableFrom(classToAdd))
{
return entry.getValue();
}
}
throw new AssertionError("Class has no compatible codec: " + clazz.getSimpleName());
throw new AssertionError("Class has no compatible codec: " + classToAdd.getSimpleName());
});
}
@@ -5,6 +5,7 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.network.INetworkObject;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
import com.seibel.distanthorizons.core.util.TimerUtil;
import io.netty.buffer.ByteBuf;
@@ -12,9 +13,7 @@ import io.netty.buffer.ByteBufAllocator;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@@ -31,6 +30,8 @@ public class FullDataPayload implements INetworkObject
public int dtoBufferId;
public ByteBuf dtoBuffer;
public List<BeaconBeamDTO> beaconBeams;
//==============//
@@ -38,7 +39,7 @@ public class FullDataPayload implements INetworkObject
//==============//
public FullDataPayload() { }
public FullDataPayload(@NotNull FullDataSourceV2 fullDataSource)
public FullDataPayload(@NotNull FullDataSourceV2 fullDataSource, List<BeaconBeamDTO> beaconBeams)
{
Objects.requireNonNull(fullDataSource);
@@ -65,6 +66,8 @@ public class FullDataPayload implements INetworkObject
{
throw new RuntimeException(e);
}
this.beaconBeams = beaconBeams;
}
@@ -77,12 +80,14 @@ public class FullDataPayload implements INetworkObject
public void encode(ByteBuf out)
{
out.writeInt(this.dtoBufferId);
this.writeCollection(out, this.beaconBeams);
}
@Override
public void decode(ByteBuf in)
{
this.dtoBufferId = in.readInt();
this.beaconBeams = this.readCollection(in, new ArrayList<>(), () -> new BeaconBeamDTO(null, null));
}
/**
@@ -121,6 +126,7 @@ public class FullDataPayload implements INetworkObject
return MoreObjects.toStringHelper(this)
.add("dtoBufferId", this.dtoBufferId)
.add("dtoBuffer", this.dtoBuffer)
.add("beaconBeams", this.beaconBeams)
.toString();
}
@@ -348,6 +348,22 @@ public class DhSectionPos
return aMinX <= bMinX && bMinX <= aMaxX &&
aMinZ <= bMinZ && bMinZ <= aMaxZ;
}
public static boolean contains(long aPos, DhBlockPos blockPos)
{
int sectionMinX = getMinCornerBlockX(aPos);
int sectionMinZ = getMinCornerBlockZ(aPos);
int blockX = blockPos.getX();
int blockZ = blockPos.getZ();
int sectionBlockWidth = getBlockWidth(aPos) - 1; // minus 1 to account for zero based positional indexing
int sectionMaxX = sectionMinX + sectionBlockWidth;
int sectionMaxZ = sectionMinZ + sectionBlockWidth;
return sectionMinX <= blockX && blockX <= sectionMaxX &&
sectionMinZ <= blockZ && blockZ <= sectionMaxZ;
}
@@ -20,8 +20,10 @@
package com.seibel.distanthorizons.core.pos.blockPos;
import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.network.INetworkObject;
import com.seibel.distanthorizons.core.util.LodUtil;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
@@ -34,7 +36,7 @@ import java.util.Objects;
*
* @see DhBlockPosMutable
*/
public class DhBlockPos
public class DhBlockPos implements INetworkObject
{
/** Useful for methods that need a position passed in but won't actually be used */
public static final DhBlockPos ZERO = new DhBlockPos(0, 0, 0);
@@ -191,4 +193,26 @@ public class DhBlockPos
@Override
public String toString() { return "DHBlockPos["+ this.x +", "+ this.y +", "+ this.z +"]"; }
//=========//
// network //
//=========//
@Override
public void encode(ByteBuf out)
{
out.writeInt(this.x);
out.writeInt(this.y);
out.writeInt(this.z);
}
@Override
public void decode(ByteBuf in)
{
this.x = in.readInt();
this.y = in.readInt();
this.z = in.readInt();
}
}
@@ -29,9 +29,7 @@ import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
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.math.Vec3d;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
@@ -41,9 +39,7 @@ import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.ReentrantLock;
@@ -61,9 +57,6 @@ public class BeaconRenderHandler
/** if this is null then the other handler is probably null too, but just in case */
private final BeaconBeamRepo beaconBeamRepo;
private final ReentrantLock updateLock = new ReentrantLock();
private final IDhApiRenderableBoxGroup beaconBoxGroup;
@@ -79,10 +72,8 @@ public class BeaconRenderHandler
// constructor //
//=============//
public BeaconRenderHandler(@NotNull BeaconBeamRepo beaconBeamRepo, @NotNull GenericObjectRenderer renderer)
public BeaconRenderHandler(@NotNull GenericObjectRenderer renderer)
{
this.beaconBeamRepo = beaconBeamRepo;
this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(ModInfo.NAME+":Beacons", new ArrayList<>(0));
this.beaconBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
@@ -95,105 +86,11 @@ public class BeaconRenderHandler
//=========================//
// level loading/unloading //
//=========================//
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> activeBeamList)
{
// synchronized to prevent two threads from updating the same chunk at the same time
synchronized (this)
{
HashSet<DhBlockPos> allPosSet = new HashSet<>();
// sort new beams
HashMap<DhBlockPos, BeaconBeamDTO> activeBeamByPos = new HashMap<>(activeBeamList.size());
for (int i = 0; i < activeBeamList.size(); i++)
{
BeaconBeamDTO beam = activeBeamList.get(i);
activeBeamByPos.put(beam.blockPos, beam);
allPosSet.add(beam.blockPos);
}
// get existing beams
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos);
HashMap<DhBlockPos, BeaconBeamDTO> existingBeamByPos = new HashMap<>(existingBeamList.size());
for (int i = 0; i < existingBeamList.size(); i++)
{
BeaconBeamDTO beam = existingBeamList.get(i);
existingBeamByPos.put(beam.blockPos, beam);
allPosSet.add(beam.blockPos);
}
for (DhBlockPos beaconPos : allPosSet)
{
if (!chunkPos.contains(beaconPos))
{
// don't update beacons outside the updated chunk
continue;
}
BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos);
BeaconBeamDTO activeBeam = activeBeamByPos.get(beaconPos);
if (existingBeam != null && activeBeam != null)
{
// beam still exists in chunk
if (!existingBeam.color.equals(activeBeam.color))
{
// beam colors were changed
this.beaconBeamRepo.save(activeBeam);
this.updateBeaconColor(activeBeam);
}
}
else if (existingBeam == null && activeBeam != null)
{
// new beam found, add to DB
this.beaconBeamRepo.save(activeBeam);
this.startRenderingBeacon(activeBeam);
}
else if (existingBeam != null && activeBeam == null)
{
// beam no longer exists at position, remove from DB
this.beaconBeamRepo.deleteWithKey(beaconPos);
this.stopRenderingBeaconAtPos(beaconPos);
}
}
}
}
public void loadBeaconBeamsInPos(long pos)
{
// get all beams in pos
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos);
for (int i = 0; i < existingBeamList.size(); i++)
{
BeaconBeamDTO newBeam = existingBeamList.get(i);
this.startRenderingBeacon(newBeam);
}
}
public void unloadBeaconBeamsInPos(long pos)
{
// get all beams in pos
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos);
for (int i = 0; i < existingBeamList.size(); i++)
{
BeaconBeamDTO beam = existingBeamList.get(i);
this.stopRenderingBeaconAtPos(beam.blockPos);
}
}
//=================//
// render handling //
//=================//
private void startRenderingBeacon(BeaconBeamDTO beacon)
public void startRenderingBeacon(BeaconBeamDTO beacon)
{
try
{
@@ -219,7 +116,7 @@ public class BeaconRenderHandler
}
}
private void stopRenderingBeaconAtPos(DhBlockPos beaconPos)
public void stopRenderingBeaconAtPos(DhBlockPos beaconPos)
{
try
{
@@ -245,7 +142,7 @@ public class BeaconRenderHandler
}
}
private void updateBeaconColor(BeaconBeamDTO newBeam)
public void updateBeaconColor(BeaconBeamDTO newBeam)
{
try
{
@@ -20,12 +20,14 @@
package com.seibel.distanthorizons.core.sql.dto;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.network.INetworkObject;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import io.netty.buffer.ByteBuf;
import java.awt.*;
/** handles storing {@link FullDataSourceV2}'s in the database. */
public class BeaconBeamDTO implements IBaseDTO<DhBlockPos>
public class BeaconBeamDTO implements IBaseDTO<DhBlockPos>, INetworkObject
{
public DhBlockPos blockPos;
public Color color;
@@ -51,4 +53,24 @@ public class BeaconBeamDTO implements IBaseDTO<DhBlockPos>
@Override
public DhBlockPos getKey() { return this.blockPos; }
//=========//
// network //
//=========//
@Override
public void encode(ByteBuf out)
{
this.blockPos.encode(out);
out.writeInt(this.color.getRGB());
}
@Override
public void decode(ByteBuf in)
{
this.blockPos = INetworkObject.decodeToInstance(new DhBlockPos(), in);
this.color = new Color(in.readInt());
}
}