Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons-core
This commit is contained in:
+1
-1
@@ -537,7 +537,7 @@ ij_groovy_wrap_chain_calls_after_dot = false
|
||||
ij_groovy_wrap_long_lines = false
|
||||
|
||||
[{*.har,*.json,*.png.mcmeta,mcmod.info,pack.mcmeta}]
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
ij_json_array_wrapping = split_into_lines
|
||||
ij_json_keep_blank_lines_in_code = 0
|
||||
ij_json_keep_indents_on_empty_lines = false
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+1
-3
@@ -75,9 +75,7 @@ public class ClientPluginChannelApi
|
||||
|
||||
private void onCurrentLevelKeyMessage(CurrentLevelKeyMessage msg)
|
||||
{
|
||||
// prefix@namespace:path
|
||||
// 1-50 characters in total, all parts except namespace can be omitted
|
||||
if (!msg.levelKey.matches("^(?=.{1,50}$)([a-zA-Z0-9-_]+@)?[a-zA-Z0-9-_]+(:[a-zA-Z0-9-_]+)?$"))
|
||||
if (!msg.levelKey.matches(CurrentLevelKeyMessage.VALIDATION_REGEX))
|
||||
{
|
||||
throw new IllegalArgumentException("Server sent invalid level key.");
|
||||
}
|
||||
|
||||
@@ -99,7 +99,12 @@ public class SharedApi
|
||||
{
|
||||
ThreadPoolUtil.shutdownThreadPools();
|
||||
DebugRenderer.clearRenderables();
|
||||
MC_RENDER.clearTargetFrameBuffer();
|
||||
|
||||
if (MC_RENDER != null)
|
||||
{
|
||||
MC_RENDER.clearTargetFrameBuffer();
|
||||
}
|
||||
|
||||
// shouldn't be necessary, but if we missed closing one of the connections this should make sure they're all closed
|
||||
AbstractDhRepo.closeAllConnections();
|
||||
// needs to be closed on world shutdown to clear out un-processed chunks
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
||||
@@ -64,7 +65,7 @@ public class Config
|
||||
public static ConfigCategory client = new ConfigCategory.Builder().set(Client.class).build();
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("ConcatenationWithEmptyString")
|
||||
public static class Client
|
||||
{
|
||||
public static ConfigEntry<Boolean> quickEnableRendering = new ConfigEntry.Builder<Boolean>()
|
||||
@@ -1007,24 +1008,6 @@ public class Config
|
||||
public static class ServerNetworking
|
||||
{
|
||||
public static ConfigUIComment generalSectionNote = new ConfigUIComment();
|
||||
public static ConfigEntry<Boolean> enableServerNetworking = new ConfigEntry.Builder<Boolean>()
|
||||
.setServersideShortName("enableServerNetworking")
|
||||
.set(true)
|
||||
.comment(""
|
||||
+ "WARNING!\n"
|
||||
+ "Server-client networking is not yet fully implemented!\n"
|
||||
+ "Both the server and client must be running the server-side fork with this option enabled\n"
|
||||
+ "for Distant Horizons data to be transceived.\n"
|
||||
+ "\n"
|
||||
+ "If true, the server and client will attempt to communicate to transceive Distant Horizons data.\n"
|
||||
+ "This allows for further distant generation and LOD updates on all clients.\n"
|
||||
+ "\n"
|
||||
+ "This should only be used on trusted servers with trusted players!\n"
|
||||
+ "")
|
||||
.setSide(EConfigEntryRelevantSide.BOTH)
|
||||
.build();
|
||||
|
||||
|
||||
public static ConfigEntry<Boolean> sendLevelKeys = new ConfigEntry.Builder<Boolean>()
|
||||
.setServersideShortName("sendLevelKeys")
|
||||
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
|
||||
@@ -1037,12 +1020,11 @@ public class Config
|
||||
.build();
|
||||
public static ConfigEntry<String> levelKeyPrefix = new ConfigEntry.Builder<String>()
|
||||
.setServersideShortName("levelKeyPrefix")
|
||||
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
|
||||
.set(getDefaultLevelKeyPrefix())
|
||||
.comment(""
|
||||
+ "Prefix of the level keys sent to the clients.\n"
|
||||
+ "Should be set to a unique value for each backend server behind a proxy,\n"
|
||||
+ "or empty if you don't use a proxy.\n"
|
||||
+ "If the mod is running behind a proxy, each backend should use a unique value (an empty string is allowed for one of the servers).\n"
|
||||
+ "This value may be auto-generated if the mod is installed before the first start of the server.\n"
|
||||
+ "")
|
||||
.setSide(EConfigEntryRelevantSide.BOTH)
|
||||
.build();
|
||||
@@ -1756,13 +1738,15 @@ public class Config
|
||||
private static String getDefaultLevelKeyPrefix()
|
||||
{
|
||||
IMinecraftSharedWrapper mcWrapper = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class);
|
||||
if (!mcWrapper.isDedicatedServer() || mcWrapper.isWorldNew())
|
||||
if (mcWrapper.isDedicatedServer())
|
||||
{
|
||||
return "";
|
||||
return mcWrapper.isWorldNew()
|
||||
? "server" + ThreadLocalRandom.current().nextInt(1, 1000)
|
||||
: "";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "server" + ThreadLocalRandom.current().nextInt(1, 1000);
|
||||
return SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getUsername();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+166
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
@@ -129,6 +130,11 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
|
||||
|
||||
this.networkEventSource.registerHandler(FullDataPartialUpdateMessage.class, message ->
|
||||
{
|
||||
if (MC_CLIENT.connectedToReplay())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
FullDataSourceV2DTO dataSourceDto = this.networkState.decodeDataSourceAndReleaseBuffer(message.payload);
|
||||
@@ -138,6 +144,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 +283,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 +368,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);
|
||||
}
|
||||
|
||||
@@ -90,8 +90,10 @@ public class ConfigBasedLogger
|
||||
|
||||
public void log(Level level, String str, Object... param)
|
||||
{
|
||||
Message msg = param.length > 0
|
||||
? this.logger.getMessageFactory().newMessage(str, param)
|
||||
: this.logger.getMessageFactory().newMessage("{}", str);
|
||||
|
||||
Message msg = logger.getMessageFactory().newMessage(str, param);
|
||||
String msgStr = msg.getFormattedMessage();
|
||||
if (mode.levelForFile.isLessSpecificThan(level))
|
||||
{
|
||||
|
||||
+4
-4
@@ -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);
|
||||
|
||||
+43
-26
@@ -2,6 +2,7 @@ package com.seibel.distanthorizons.core.multiplayer.client;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.distanthorizons.core.multiplayer.config.SessionConfig;
|
||||
import com.seibel.distanthorizons.core.network.INetworkObject;
|
||||
@@ -10,12 +11,14 @@ import com.seibel.distanthorizons.core.network.event.internal.CloseInternalEvent
|
||||
import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent;
|
||||
import com.seibel.distanthorizons.core.network.messages.base.CurrentLevelKeyMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.base.SessionConfigMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataSourceResponseMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataSplitMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataPartialUpdateMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataPayload;
|
||||
import com.seibel.distanthorizons.core.network.session.NetworkSession;
|
||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.CompositeByteBuf;
|
||||
@@ -32,6 +35,8 @@ public class ClientNetworkState implements Closeable
|
||||
protected static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(),
|
||||
() -> Config.Client.Advanced.Logging.logNetworkEvent.get());
|
||||
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
|
||||
|
||||
private final ConcurrentMap<Integer, CompositeByteBuf> fullDataBufferById = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.SECONDS)
|
||||
@@ -85,41 +90,53 @@ public class ClientNetworkState implements Closeable
|
||||
}
|
||||
});
|
||||
|
||||
this.networkSession.registerHandler(SessionConfigMessage.class, message ->
|
||||
{
|
||||
this.serverSupportStatus = EServerSupportStatus.FULL;
|
||||
|
||||
LOGGER.info("Connection config has been changed: ["+message.config+"].");
|
||||
this.sessionConfig = message.config;
|
||||
this.configReceived = true;
|
||||
});
|
||||
|
||||
this.networkSession.registerHandler(CloseInternalEvent.class, message ->
|
||||
{
|
||||
this.configReceived = false;
|
||||
});
|
||||
|
||||
this.networkSession.registerHandler(FullDataSplitMessage.class, message ->
|
||||
{
|
||||
if (message.isFirst)
|
||||
{
|
||||
CompositeByteBuf composite = this.fullDataBufferById.remove(message.bufferId);
|
||||
if (composite != null)
|
||||
{
|
||||
composite.release();
|
||||
LOGGER.debug("Released full data buffer ["+message.bufferId+"]: ["+composite+"]");
|
||||
}
|
||||
}
|
||||
|
||||
CompositeByteBuf byteBuffer = this.fullDataBufferById.computeIfAbsent(message.bufferId, bufferId -> ByteBufAllocator.DEFAULT.compositeBuffer());
|
||||
byteBuffer.addComponent(true, message.buffer);
|
||||
LOGGER.debug("Full data buffer ["+message.bufferId+"]: ["+byteBuffer+"].");
|
||||
});
|
||||
|
||||
this.networkSession.registerHandler(FullDataPartialUpdateMessage.class, msg ->
|
||||
{
|
||||
// Dummy handler to prevent unhandled message warnings
|
||||
});
|
||||
|
||||
if (MC_CLIENT.connectedToReplay())
|
||||
{
|
||||
// Prevent handling specific messages because replay server is not interactive.
|
||||
// Level keys are still good because they don't affect anything other than level loading.
|
||||
|
||||
this.networkSession.registerHandler(SessionConfigMessage.class, message -> { });
|
||||
this.networkSession.registerHandler(FullDataSourceResponseMessage.class, message -> { });
|
||||
this.networkSession.registerHandler(FullDataSplitMessage.class, message -> { });
|
||||
}
|
||||
else
|
||||
{
|
||||
this.networkSession.registerHandler(SessionConfigMessage.class, message ->
|
||||
{
|
||||
this.serverSupportStatus = EServerSupportStatus.FULL;
|
||||
|
||||
LOGGER.info("Connection config has been changed: [" + message.config + "].");
|
||||
this.sessionConfig = message.config;
|
||||
this.configReceived = true;
|
||||
});
|
||||
|
||||
this.networkSession.registerHandler(FullDataSplitMessage.class, message ->
|
||||
{
|
||||
if (message.isFirst)
|
||||
{
|
||||
CompositeByteBuf composite = this.fullDataBufferById.remove(message.bufferId);
|
||||
if (composite != null)
|
||||
{
|
||||
composite.release();
|
||||
LOGGER.debug("Released full data buffer [" + message.bufferId + "]: [" + composite + "]");
|
||||
}
|
||||
}
|
||||
|
||||
CompositeByteBuf byteBuffer = this.fullDataBufferById.computeIfAbsent(message.bufferId, bufferId -> ByteBufAllocator.DEFAULT.compositeBuffer());
|
||||
byteBuffer.addComponent(true, message.buffer);
|
||||
LOGGER.debug("Full data buffer [" + message.bufferId + "]: [" + byteBuffer + "].");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -6,6 +6,15 @@ import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class CurrentLevelKeyMessage extends AbstractNetworkMessage
|
||||
{
|
||||
public static final int MAX_LENGTH = 150;
|
||||
|
||||
public static final String PART_ALLOWED_CHARS_REGEX = "a-zA-Z0-9-_";
|
||||
|
||||
// prefix@namespace:path
|
||||
// 1-150 characters in total, all parts except namespace can be omitted
|
||||
public static final String VALIDATION_REGEX = "^(?=.{1,$MAX_LENGTH}$)([$PART_ALLOWED_CHARS_REGEX]+@)?[$PART_ALLOWED_CHARS_REGEX]+(:[$PART_ALLOWED_CHARS_REGEX]+)?$";
|
||||
|
||||
|
||||
public String levelKey;
|
||||
|
||||
|
||||
|
||||
+10
-4
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-107
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -76,6 +76,8 @@ public interface IMinecraftClientWrapper extends IBindable
|
||||
|
||||
UUID getPlayerUUID();
|
||||
|
||||
String getUsername();
|
||||
|
||||
DhBlockPos getPlayerBlockPos();
|
||||
|
||||
DhChunkPos getPlayerChunkPos();
|
||||
|
||||
+19
-1
@@ -19,7 +19,11 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.world;
|
||||
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.network.messages.base.CurrentLevelKeyMessage;
|
||||
import com.seibel.distanthorizons.core.world.EWorldEnvironment;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface IServerLevelWrapper extends ILevelWrapper
|
||||
@@ -33,9 +37,23 @@ public interface IServerLevelWrapper extends ILevelWrapper
|
||||
if (Config.Client.Advanced.Multiplayer.ServerNetworking.sendLevelKeys.get())
|
||||
{
|
||||
String levelKeyPrefix = Config.Client.Advanced.Multiplayer.ServerNetworking.levelKeyPrefix.get();
|
||||
|
||||
if (SharedApi.getEnvironment() == EWorldEnvironment.CLIENT_SERVER)
|
||||
{
|
||||
String cleanWorldFolderName = this.getMcSaveFolder().getParentFile().getName()
|
||||
.replaceAll("[^" + CurrentLevelKeyMessage.PART_ALLOWED_CHARS_REGEX + " ]", "")
|
||||
.replaceAll(" ", "_");
|
||||
levelKeyPrefix += (!levelKeyPrefix.isEmpty() ? "_" : "") + cleanWorldFolderName;
|
||||
}
|
||||
|
||||
if (!levelKeyPrefix.isEmpty())
|
||||
{
|
||||
return levelKeyPrefix + "@" + dimensionName;
|
||||
String mainPart = "@" + dimensionName;
|
||||
|
||||
return levelKeyPrefix.substring(0, Math.min(
|
||||
CurrentLevelKeyMessage.MAX_LENGTH - mainPart.length(),
|
||||
levelKeyPrefix.length()
|
||||
)) + mainPart;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -413,8 +413,7 @@
|
||||
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking": "Server Networking",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.generalSectionNote": " \u25cf General",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableServerNetworking": "Enable Server Networking",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableServerNetworking.@tooltip": "§6Attention:§r this feature is not fully implemented. \n\nIf true Distant Horizons will attempt to communicate with the connected \nserver in order to load LODs outside your vanilla render distance. \n\nNote: This requires DH to be installed on the server in order to function.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.levelKeyPrefix": "Level Key Prefix",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.generationSectionNote": " \u25cf Generation",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.generationRequestRateLimit": "Rate Limit for Generation Requests",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.generationRequestRateLimit.@tooltip": "How many LOD generation requests per second should a client send? \nAlso limits the amount of player's requests allowed to stay in the server's queue.",
|
||||
|
||||
Reference in New Issue
Block a user