Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 034ec7d656 | |||
| fb5e15a2f1 | |||
| 674fc30e77 | |||
| a05bd307f9 | |||
| d78a50ce49 | |||
| 013eab9268 | |||
| 435cbde238 | |||
| d7040bad13 | |||
| a588070ce1 |
@@ -40,6 +40,7 @@ public enum EDhApiLoggerMode
|
|||||||
LOG_DEBUG_TO_CHAT_AND_FILE(Level.DEBUG, Level.DEBUG),
|
LOG_DEBUG_TO_CHAT_AND_FILE(Level.DEBUG, Level.DEBUG),
|
||||||
LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.WARN),
|
LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.WARN),
|
||||||
LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.ERROR),
|
LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.ERROR),
|
||||||
|
LOG_ERROR_TO_CHAT_AND_WARNING_TO_FILE(Level.ERROR, Level.WARN),
|
||||||
;
|
;
|
||||||
|
|
||||||
public final Level levelForFile;
|
public final Level levelForFile;
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ public final class ModInfo
|
|||||||
public static final String DEDICATED_SERVER_INITIAL_PATH = "dedicated_server_initial";
|
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. */
|
/** Incremented every time any packets are added, changed or removed, with a few exceptions. */
|
||||||
public static final int PROTOCOL_VERSION = 11;
|
public static final int PROTOCOL_VERSION = 12;
|
||||||
public static final String WRAPPER_PACKET_PATH = "message";
|
public static final String WRAPPER_PACKET_PATH = "message";
|
||||||
|
|
||||||
/** The internal mod name */
|
/** The internal mod name */
|
||||||
public static final String NAME = "DistantHorizons";
|
public static final String NAME = "DistantHorizons";
|
||||||
/** Human-readable version of NAME */
|
/** Human-readable version of NAME */
|
||||||
public static final String READABLE_NAME = "Distant Horizons";
|
public static final String READABLE_NAME = "Distant Horizons";
|
||||||
public static final String VERSION = "2.3.3-b";
|
public static final String VERSION = "2.3.5-b-dev";
|
||||||
/** Returns true if the current build is an unstable developer build, false otherwise. */
|
/** Returns true if the current build is an unstable developer build, false otherwise. */
|
||||||
public static final boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
|
public static final boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
|
||||||
|
|
||||||
|
|||||||
+10
-3
@@ -75,7 +75,12 @@ public class ClientPluginChannelApi
|
|||||||
|
|
||||||
private void onLevelInitMessage(LevelInitMessage msg)
|
private void onLevelInitMessage(LevelInitMessage msg)
|
||||||
{
|
{
|
||||||
if (!msg.levelKey.matches(LevelInitMessage.VALIDATION_REGEX))
|
if (!msg.serverKey.matches(LevelInitMessage.SERVER_KEY_REGEX))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Server sent invalid server key.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!msg.levelKey.matches(LevelInitMessage.LEVEL_KEY_REGEX))
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Server sent invalid level key.");
|
throw new IllegalArgumentException("Server sent invalid level key.");
|
||||||
}
|
}
|
||||||
@@ -105,10 +110,12 @@ public class ClientPluginChannelApi
|
|||||||
this.levelUnloadHandler.accept(clientLevel);
|
this.levelUnloadHandler.accept(clientLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingKeyedClientLevel == null || !existingKeyedClientLevel.getServerLevelKey().equals(msg.levelKey))
|
if (existingKeyedClientLevel == null
|
||||||
|
|| !existingKeyedClientLevel.getServerKey().equals(msg.serverKey)
|
||||||
|
|| !existingKeyedClientLevel.getServerLevelKey().equals(msg.levelKey))
|
||||||
{
|
{
|
||||||
LOGGER.info("Loading level with key: [" + msg.levelKey + "].");
|
LOGGER.info("Loading level with key: [" + msg.levelKey + "].");
|
||||||
IServerKeyedClientLevel keyedLevel = KEYED_CLIENT_LEVEL_MANAGER.setServerKeyedLevel(clientLevel, msg.levelKey);
|
IServerKeyedClientLevel keyedLevel = KEYED_CLIENT_LEVEL_MANAGER.setServerKeyedLevel(clientLevel, msg.serverKey, msg.levelKey);
|
||||||
this.levelLoadHandler.accept(keyedLevel);
|
this.levelLoadHandler.accept(keyedLevel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1520,7 +1520,7 @@ public class Config
|
|||||||
|
|
||||||
public static ConfigEntry<EDhApiLoggerMode> logNetworkEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
public static ConfigEntry<EDhApiLoggerMode> logNetworkEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||||
.setChatCommandName("logging.logNetworkEvent")
|
.setChatCommandName("logging.logNetworkEvent")
|
||||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
|
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_WARNING_TO_FILE)
|
||||||
.comment(""
|
.comment(""
|
||||||
+ "If enabled, the mod will log information about network operations. \n"
|
+ "If enabled, the mod will log information about network operations. \n"
|
||||||
+ "This can be useful for debugging.")
|
+ "This can be useful for debugging.")
|
||||||
@@ -1599,6 +1599,28 @@ public class Config
|
|||||||
+ "")
|
+ "")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static ConfigEntry<Integer> serverId = new ConfigEntry.Builder<Integer>()
|
||||||
|
.set(new Random().nextInt())
|
||||||
|
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
|
||||||
|
.comment(""
|
||||||
|
+ "DO NOT CHANGE UNLESS YOU KNOW WHAT YOU'RE DOING.\n"
|
||||||
|
+ "Autogenerated ID used to prevent multiple independent servers from accidentally\n"
|
||||||
|
+ "writing over each other's LODs when the same serverKey is set on both.\n"
|
||||||
|
+ "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static ConfigEntry<String> serverKey = new ConfigEntry.Builder<String>()
|
||||||
|
.setChatCommandName("levelKeys.serverKey")
|
||||||
|
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
|
||||||
|
.set("")
|
||||||
|
.comment(""
|
||||||
|
+ "Custom server key used which can be used to always reuse the same LOD data folder,\n"
|
||||||
|
+ "for cases when the server doesn't have a static IP for some reason.\n"
|
||||||
|
+ "If this value is empty, the client itself decides which folder name to use.\n"
|
||||||
|
+ "Requires rejoining the server to apply after changing.\n"
|
||||||
|
+ "")
|
||||||
|
.build();
|
||||||
|
|
||||||
public static ConfigEntry<String> levelKeyPrefix = new ConfigEntry.Builder<String>()
|
public static ConfigEntry<String> levelKeyPrefix = new ConfigEntry.Builder<String>()
|
||||||
.setChatCommandName("levelKeys.prefix")
|
.setChatCommandName("levelKeys.prefix")
|
||||||
.set("")
|
.set("")
|
||||||
|
|||||||
+13
-6
@@ -81,13 +81,20 @@ public class ClientOnlySaveStructure implements ISaveStructure
|
|||||||
{
|
{
|
||||||
IServerKeyedClientLevel keyedClientLevel = (IServerKeyedClientLevel) newLevelWrapper;
|
IServerKeyedClientLevel keyedClientLevel = (IServerKeyedClientLevel) newLevelWrapper;
|
||||||
LOGGER.info("Loading level [" + newLevelWrapper.getDhIdentifier() + "] with key: [" + keyedClientLevel.getServerLevelKey() + "].");
|
LOGGER.info("Loading level [" + newLevelWrapper.getDhIdentifier() + "] with key: [" + keyedClientLevel.getServerLevelKey() + "].");
|
||||||
// This world was identified by the server directly, so we can know for sure which folder to use.
|
|
||||||
saveFolder = getSaveFolderByLevelId(keyedClientLevel.getServerLevelKey());
|
String serverKey = keyedClientLevel.getServerKey();
|
||||||
|
if (serverKey.isEmpty())
|
||||||
|
{
|
||||||
|
serverKey = getServerFolderName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This world was identified by the server directly, so we can know for sure which folder to use.
|
||||||
|
saveFolder = getSaveFolderByLevelId(serverKey, keyedClientLevel.getServerLevelKey());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// get the default folder
|
// get the default folder
|
||||||
saveFolder = getSaveFolderByLevelId(levelWrapper.getDhIdentifier());
|
saveFolder = getSaveFolderByLevelId(getServerFolderName(), levelWrapper.getDhIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow API users to override the save folder
|
// Allow API users to override the save folder
|
||||||
@@ -116,7 +123,7 @@ public class ClientOnlySaveStructure implements ISaveStructure
|
|||||||
return this.getSaveFolder(levelWrapper);
|
return this.getSaveFolder(levelWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSaveFolderByLevelId(levelWrapper.getDimensionType().getName());
|
return getSaveFolderByLevelId(getServerFolderName(), levelWrapper.getDimensionType().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -173,11 +180,11 @@ public class ClientOnlySaveStructure implements ISaveStructure
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static File getSaveFolderByLevelId(String dimensionName)
|
private static File getSaveFolderByLevelId(String folderName, String dimensionName)
|
||||||
{
|
{
|
||||||
String path = MC_SHARED.getInstallationDirectory().getPath() + File.separatorChar
|
String path = MC_SHARED.getInstallationDirectory().getPath() + File.separatorChar
|
||||||
+ SERVER_DATA_FOLDER_NAME + File.separatorChar
|
+ SERVER_DATA_FOLDER_NAME + File.separatorChar
|
||||||
+ getServerFolderName() + File.separatorChar
|
+ folderName + File.separatorChar
|
||||||
+ dimensionName.replaceAll(":", "@@");
|
+ dimensionName.replaceAll(":", "@@");
|
||||||
|
|
||||||
return new File(path);
|
return new File(path);
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ public class SelfUpdater
|
|||||||
}
|
}
|
||||||
if (!ModrinthGetter.mcVersions.contains(mcVersion))
|
if (!ModrinthGetter.mcVersions.contains(mcVersion))
|
||||||
{
|
{
|
||||||
LOGGER.warn("Minecraft version ["+ mcVersion +"] is not findable on Modrinth, only findable versions are ["+ StringUtil.join(",", ModrinthGetter.mcVersions) +"]");
|
LOGGER.warn("Minecraft version ["+ mcVersion +"] is not findable on Modrinth, only findable versions are ["+ StringUtil.join(", ", ModrinthGetter.mcVersions) +"]");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-20
@@ -261,29 +261,27 @@ public abstract class AbstractDhServerLevel extends AbstractDhLevel implements I
|
|||||||
}
|
}
|
||||||
|
|
||||||
LodUtil.assertTrue(this.beaconBeamRepo != null, "beaconBeamRepo should not be null");
|
LodUtil.assertTrue(this.beaconBeamRepo != null, "beaconBeamRepo should not be null");
|
||||||
try (FullDataPayload payload = new FullDataPayload(data, this.beaconBeamRepo.getAllBeamsForPos(data.getPos())))
|
FullDataPayload payload = new FullDataPayload(data, this.beaconBeamRepo.getAllBeamsForPos(data.getPos()));
|
||||||
|
for (ServerPlayerState serverPlayerState : this.serverPlayerStateManager.getReadyPlayers())
|
||||||
{
|
{
|
||||||
for (ServerPlayerState serverPlayerState : this.serverPlayerStateManager.getReadyPlayers())
|
if (serverPlayerState.getServerPlayer().getLevel() != this.serverLevelWrapper)
|
||||||
{
|
{
|
||||||
if (serverPlayerState.getServerPlayer().getLevel() != this.serverLevelWrapper)
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverPlayerState.sessionConfig.isRealTimeUpdatesEnabled())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3d playerPosition = serverPlayerState.getServerPlayer().getPosition();
|
||||||
|
int distanceFromPlayer = DhSectionPos.getChebyshevSignedBlockDistance(data.getPos(), new DhBlockPos2D((int) playerPosition.x, (int) playerPosition.z)) / 16;
|
||||||
|
if (distanceFromPlayer <= serverPlayerState.sessionConfig.getMaxUpdateDistanceRadius())
|
||||||
|
{
|
||||||
|
serverPlayerState.fullDataPayloadSender.sendInChunks(payload, () ->
|
||||||
{
|
{
|
||||||
continue;
|
serverPlayerState.networkSession.sendMessage(new FullDataPartialUpdateMessage(this.serverLevelWrapper, payload));
|
||||||
}
|
});
|
||||||
|
|
||||||
if (!serverPlayerState.sessionConfig.isRealTimeUpdatesEnabled())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3d playerPosition = serverPlayerState.getServerPlayer().getPosition();
|
|
||||||
int distanceFromPlayer = DhSectionPos.getChebyshevSignedBlockDistance(data.getPos(), new DhBlockPos2D((int) playerPosition.x, (int) playerPosition.z)) / 16;
|
|
||||||
if (distanceFromPlayer <= serverPlayerState.sessionConfig.getMaxUpdateDistanceRadius())
|
|
||||||
{
|
|
||||||
serverPlayerState.fullDataPayloadSender.sendInChunks(payload, () ->
|
|
||||||
{
|
|
||||||
serverPlayerState.networkSession.sendMessage(new FullDataPartialUpdateMessage(this.serverLevelWrapper, payload));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try(FullDataSourceV2DTO dataSourceDto = this.networkState.fullDataPayloadReceiver.decodeDataSourceAndReleaseBuffer(message.payload))
|
try (FullDataSourceV2DTO dataSourceDto = this.networkState.fullDataPayloadReceiver.decodeDataSource(message.payload))
|
||||||
{
|
{
|
||||||
boolean isSameLevel = message.isSameLevelAs(this.levelWrapper);
|
boolean isSameLevel = message.isSameLevelAs(this.levelWrapper);
|
||||||
NETWORK_LOGGER.debug("Buffer {} isSameLevel: {}", message.payload.dtoBufferId, isSameLevel);
|
NETWORK_LOGGER.debug("Buffer {} isSameLevel: {}", message.payload.dtoBufferId, isSameLevel);
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ public interface IKeyedClientLevelManager extends IBindable
|
|||||||
{
|
{
|
||||||
IServerKeyedClientLevel getServerKeyedLevel();
|
IServerKeyedClientLevel getServerKeyedLevel();
|
||||||
/** Called when a client level is wrapped by a ServerEnhancedClientLevel, for integration into mod internals. */
|
/** Called when a client level is wrapped by a ServerEnhancedClientLevel, for integration into mod internals. */
|
||||||
IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String levelKey);
|
IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String serverKey, String levelKey);
|
||||||
|
|
||||||
void clearKeyedLevel();
|
void clearKeyedLevel();
|
||||||
boolean isEnabled();
|
boolean isEnabled();
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapp
|
|||||||
/** Enhances a {@link IClientLevelWrapper} with server provided level information. */
|
/** Enhances a {@link IClientLevelWrapper} with server provided level information. */
|
||||||
public interface IServerKeyedClientLevel extends IClientLevelWrapper
|
public interface IServerKeyedClientLevel extends IClientLevelWrapper
|
||||||
{
|
{
|
||||||
|
/** Returns the folder name the server wants the player to use. */
|
||||||
|
String getServerKey();
|
||||||
|
|
||||||
/** Returns the level key, which is used to select the correct folder on the client. */
|
/** Returns the level key, which is used to select the correct folder on the client. */
|
||||||
String getServerLevelKey();
|
String getServerLevelKey();
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -256,7 +256,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
|||||||
|
|
||||||
if (response.payload != null)
|
if (response.payload != null)
|
||||||
{
|
{
|
||||||
FullDataSourceV2DTO dataSourceDto = this.networkState.fullDataPayloadReceiver.decodeDataSourceAndReleaseBuffer(response.payload);
|
FullDataSourceV2DTO dataSourceDto = this.networkState.fullDataPayloadReceiver.decodeDataSource(response.payload);
|
||||||
|
|
||||||
// set application flags based on the received detail level,
|
// set application flags based on the received detail level,
|
||||||
// this is needed so the data sources propagate correctly
|
// this is needed so the data sources propagate correctly
|
||||||
|
|||||||
+3
-10
@@ -9,18 +9,17 @@ import com.seibel.distanthorizons.core.network.messages.fullData.FullDataSplitMe
|
|||||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufAllocator;
|
import io.netty.buffer.Unpooled;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see FullDataSplitMessage
|
* @see FullDataSplitMessage
|
||||||
*/
|
*/
|
||||||
public class FullDataPayload implements INetworkObject, AutoCloseable
|
public class FullDataPayload implements INetworkObject
|
||||||
{
|
{
|
||||||
private static final AtomicInteger lastBufferId = new AtomicInteger();
|
private static final AtomicInteger lastBufferId = new AtomicInteger();
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ public class FullDataPayload implements INetworkObject, AutoCloseable
|
|||||||
EDhApiDataCompressionMode compressionMode = Config.Common.LodBuilding.dataCompression.get();
|
EDhApiDataCompressionMode compressionMode = Config.Common.LodBuilding.dataCompression.get();
|
||||||
try (FullDataSourceV2DTO dataSourceDto = FullDataSourceV2DTO.CreateFromDataSource(fullDataSource, compressionMode))
|
try (FullDataSourceV2DTO dataSourceDto = FullDataSourceV2DTO.CreateFromDataSource(fullDataSource, compressionMode))
|
||||||
{
|
{
|
||||||
this.dtoBuffer = ByteBufAllocator.DEFAULT.buffer();
|
this.dtoBuffer = Unpooled.buffer();
|
||||||
dataSourceDto.encode(this.dtoBuffer);
|
dataSourceDto.encode(this.dtoBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,12 +84,6 @@ public class FullDataPayload implements INetworkObject, AutoCloseable
|
|||||||
// base overrides //
|
// base overrides //
|
||||||
//================//
|
//================//
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close()
|
|
||||||
{
|
|
||||||
this.dtoBuffer.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
|||||||
+4
-18
@@ -9,8 +9,8 @@ import com.seibel.distanthorizons.core.network.INetworkObject;
|
|||||||
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataSplitMessage;
|
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataSplitMessage;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import io.netty.buffer.ByteBufAllocator;
|
|
||||||
import io.netty.buffer.CompositeByteBuf;
|
import io.netty.buffer.CompositeByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -24,15 +24,7 @@ public class FullDataPayloadReceiver implements AutoCloseable
|
|||||||
|
|
||||||
private final ConcurrentMap<Integer, CompositeByteBuf> buffersById = CacheBuilder.newBuilder()
|
private final ConcurrentMap<Integer, CompositeByteBuf> buffersById = CacheBuilder.newBuilder()
|
||||||
.expireAfterAccess(10, TimeUnit.SECONDS)
|
.expireAfterAccess(10, TimeUnit.SECONDS)
|
||||||
.removalListener((RemovalNotification<Integer, CompositeByteBuf> notification) ->
|
.<Integer, CompositeByteBuf>build().asMap();
|
||||||
{
|
|
||||||
// If an entry was replaced without removing, the buffer has to be released manually
|
|
||||||
if (notification.getCause() != RemovalCause.REPLACED)
|
|
||||||
{
|
|
||||||
Objects.requireNonNull(notification.getValue()).release();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build().asMap();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
@@ -46,13 +38,7 @@ public class FullDataPayloadReceiver implements AutoCloseable
|
|||||||
{
|
{
|
||||||
if (message.isFirst)
|
if (message.isFirst)
|
||||||
{
|
{
|
||||||
if (composite != null)
|
composite = Unpooled.compositeBuffer();
|
||||||
{
|
|
||||||
composite.release();
|
|
||||||
LOGGER.debug("Released existing full data buffer [" + message.bufferId + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
composite = ByteBufAllocator.DEFAULT.compositeBuffer();
|
|
||||||
LOGGER.debug("Created new full data buffer [" + message.bufferId + "]: [" + composite + "]");
|
LOGGER.debug("Created new full data buffer [" + message.bufferId + "]: [" + composite + "]");
|
||||||
}
|
}
|
||||||
else if (composite == null)
|
else if (composite == null)
|
||||||
@@ -67,7 +53,7 @@ public class FullDataPayloadReceiver implements AutoCloseable
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public FullDataSourceV2DTO decodeDataSourceAndReleaseBuffer(FullDataPayload payload)
|
public FullDataSourceV2DTO decodeDataSource(FullDataPayload payload)
|
||||||
{
|
{
|
||||||
CompositeByteBuf compositeByteBuffer = this.buffersById.get(payload.dtoBufferId);
|
CompositeByteBuf compositeByteBuffer = this.buffersById.get(payload.dtoBufferId);
|
||||||
LodUtil.assertTrue(compositeByteBuffer != null);
|
LodUtil.assertTrue(compositeByteBuffer != null);
|
||||||
|
|||||||
+2
-19
@@ -38,12 +38,6 @@ public class FullDataPayloadSender implements AutoCloseable
|
|||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
this.tickTimerTask.cancel();
|
this.tickTimerTask.cancel();
|
||||||
|
|
||||||
PendingTransfer pendingTransfer;
|
|
||||||
while ((pendingTransfer = this.transferQueue.poll()) != null)
|
|
||||||
{
|
|
||||||
pendingTransfer.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -78,36 +72,25 @@ public class FullDataPayloadSender implements AutoCloseable
|
|||||||
if (pendingTransfer.buffer.readableBytes() == 0)
|
if (pendingTransfer.buffer.readableBytes() == 0)
|
||||||
{
|
{
|
||||||
pendingTransfer.sendFinalMessage.run();
|
pendingTransfer.sendFinalMessage.run();
|
||||||
pendingTransfer.close();
|
|
||||||
this.transferQueue.poll();
|
this.transferQueue.poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class PendingTransfer implements AutoCloseable
|
private static class PendingTransfer
|
||||||
{
|
{
|
||||||
public final int bufferId;
|
public final int bufferId;
|
||||||
public final ByteBuf buffer;
|
public final ByteBuf buffer;
|
||||||
public final Runnable sendFinalMessage;
|
public final Runnable sendFinalMessage;
|
||||||
private final AtomicBoolean isClosed = new AtomicBoolean();
|
|
||||||
|
|
||||||
private PendingTransfer(FullDataPayload payload, Runnable sendFinalMessage)
|
private PendingTransfer(FullDataPayload payload, Runnable sendFinalMessage)
|
||||||
{
|
{
|
||||||
this.bufferId = payload.dtoBufferId;
|
this.bufferId = payload.dtoBufferId;
|
||||||
this.buffer = payload.dtoBuffer.retainedDuplicate().readerIndex(0);
|
this.buffer = payload.dtoBuffer.duplicate().readerIndex(0);
|
||||||
this.sendFinalMessage = sendFinalMessage;
|
this.sendFinalMessage = sendFinalMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close()
|
|
||||||
{
|
|
||||||
if (this.isClosed.compareAndSet(false, true))
|
|
||||||
{
|
|
||||||
this.buffer.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-20
@@ -119,16 +119,14 @@ public class FullDataSourceRequestHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send the found data source to client
|
// send the found data source to client
|
||||||
try (FullDataPayload payload = new FullDataPayload(fullDataSource, this.getAllBeamsForPos(message.sectionPos)))
|
FullDataPayload payload = new FullDataPayload(fullDataSource, this.getAllBeamsForPos(message.sectionPos));
|
||||||
|
fullDataSource.close();
|
||||||
|
|
||||||
|
serverPlayerState.fullDataPayloadSender.sendInChunks(payload, () ->
|
||||||
{
|
{
|
||||||
fullDataSource.close();
|
message.sendResponse(new FullDataSourceResponseMessage(payload));
|
||||||
|
rateLimiterSet.syncOnLoginRateLimiter.release();
|
||||||
serverPlayerState.fullDataPayloadSender.sendInChunks(payload, () ->
|
});
|
||||||
{
|
|
||||||
message.sendResponse(new FullDataSourceResponseMessage(payload));
|
|
||||||
rateLimiterSet.syncOnLoginRateLimiter.release();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -245,19 +243,17 @@ public class FullDataSourceRequestHandler
|
|||||||
}
|
}
|
||||||
CompletableFuture.runAsync(() ->
|
CompletableFuture.runAsync(() ->
|
||||||
{
|
{
|
||||||
try (FullDataPayload payload = new FullDataPayload(requestGroup.fullDataSource, this.getAllBeamsForPos(entry.getKey())))
|
FullDataPayload payload = new FullDataPayload(requestGroup.fullDataSource, this.getAllBeamsForPos(entry.getKey()));
|
||||||
|
requestGroup.fullDataSource.close();
|
||||||
|
|
||||||
|
for (DataSourceRequestGroup.RequestData requestData : requestGroup.requestMessages.values())
|
||||||
{
|
{
|
||||||
requestGroup.fullDataSource.close();
|
this.requestGroupsByFutureId.remove(requestData.futureId());
|
||||||
|
|
||||||
for (DataSourceRequestGroup.RequestData requestData : requestGroup.requestMessages.values())
|
requestData.serverPlayerState.fullDataPayloadSender.sendInChunks(payload, () -> {
|
||||||
{
|
requestData.message.sendResponse(new FullDataSourceResponseMessage(payload));
|
||||||
this.requestGroupsByFutureId.remove(requestData.futureId());
|
requestData.rateLimiterSet.generationRequestRateLimiter.release();
|
||||||
|
});
|
||||||
requestData.serverPlayerState.fullDataPayloadSender.sendInChunks(payload, () -> {
|
|
||||||
requestData.message.sendResponse(new FullDataSourceResponseMessage(payload));
|
|
||||||
requestData.rateLimiterSet.generationRequestRateLimiter.release();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, executor);
|
}, executor);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -27,6 +27,10 @@ public class ServerPlayerState implements Closeable
|
|||||||
private final SessionConfig.AnyChangeListener configAnyChangeListener = new SessionConfig.AnyChangeListener(this::sendConfigMessage);
|
private final SessionConfig.AnyChangeListener configAnyChangeListener = new SessionConfig.AnyChangeListener(this::sendConfigMessage);
|
||||||
|
|
||||||
|
|
||||||
|
private final String serverKeyWithoutId = Config.Server.serverKey.get();
|
||||||
|
private final String serverKey = (this.serverKeyWithoutId.isEmpty() ? "" : Config.Server.serverId.get() + "_" + this.serverKeyWithoutId.trim())
|
||||||
|
.replaceAll("[^" + LevelInitMessage.PART_ALLOWED_CHARS_REGEX + " ]", "")
|
||||||
|
.replaceAll(" ", "_");
|
||||||
private String lastLevelKey = "";
|
private String lastLevelKey = "";
|
||||||
|
|
||||||
|
|
||||||
@@ -89,7 +93,7 @@ public class ServerPlayerState implements Closeable
|
|||||||
if (!levelKey.equals(this.lastLevelKey))
|
if (!levelKey.equals(this.lastLevelKey))
|
||||||
{
|
{
|
||||||
this.lastLevelKey = levelKey;
|
this.lastLevelKey = levelKey;
|
||||||
this.networkSession.sendMessage(new LevelInitMessage(levelKey));
|
this.networkSession.sendMessage(new LevelInitMessage(this.serverKey, levelKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -10,12 +10,18 @@ public class LevelInitMessage extends AbstractNetworkMessage
|
|||||||
|
|
||||||
public static final String PART_ALLOWED_CHARS_REGEX = "a-zA-Z0-9-_";
|
public static final String PART_ALLOWED_CHARS_REGEX = "a-zA-Z0-9-_";
|
||||||
|
|
||||||
|
// A plain string of characters
|
||||||
|
// 1-150 characters in total
|
||||||
|
public static final String SERVER_KEY_REGEX = String.format("^(?=.{1,%s}$)[%s]+$",
|
||||||
|
MAX_LENGTH, PART_ALLOWED_CHARS_REGEX);
|
||||||
|
|
||||||
// prefix@namespace:path
|
// prefix@namespace:path
|
||||||
// 1-150 characters in total, all parts except namespace can be omitted
|
// 1-150 characters in total, all parts except namespace can be omitted
|
||||||
public static final String VALIDATION_REGEX = String.format("^(?=.{1,%s}$)([%s]+@)?[%s]+(:[%s]+)?$",
|
public static final String LEVEL_KEY_REGEX = String.format("^(?=.{1,%s}$)([%s]+@)?[%s]+(:[%s]+)?$",
|
||||||
MAX_LENGTH, PART_ALLOWED_CHARS_REGEX, PART_ALLOWED_CHARS_REGEX, PART_ALLOWED_CHARS_REGEX);
|
MAX_LENGTH, PART_ALLOWED_CHARS_REGEX, PART_ALLOWED_CHARS_REGEX, PART_ALLOWED_CHARS_REGEX);
|
||||||
|
|
||||||
|
|
||||||
|
public String serverKey;
|
||||||
public String levelKey;
|
public String levelKey;
|
||||||
public long serverTime;
|
public long serverTime;
|
||||||
|
|
||||||
@@ -26,8 +32,9 @@ public class LevelInitMessage extends AbstractNetworkMessage
|
|||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
public LevelInitMessage() { }
|
public LevelInitMessage() { }
|
||||||
public LevelInitMessage(String levelKey)
|
public LevelInitMessage(String serverKey, String levelKey)
|
||||||
{
|
{
|
||||||
|
this.serverKey = serverKey;
|
||||||
this.levelKey = levelKey;
|
this.levelKey = levelKey;
|
||||||
this.serverTime = System.currentTimeMillis();
|
this.serverTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
@@ -41,6 +48,7 @@ public class LevelInitMessage extends AbstractNetworkMessage
|
|||||||
@Override
|
@Override
|
||||||
public void encode(ByteBuf out)
|
public void encode(ByteBuf out)
|
||||||
{
|
{
|
||||||
|
this.writeString(this.serverKey, out);
|
||||||
this.writeString(this.levelKey, out);
|
this.writeString(this.levelKey, out);
|
||||||
out.writeLong(this.serverTime);
|
out.writeLong(this.serverTime);
|
||||||
}
|
}
|
||||||
@@ -48,6 +56,7 @@ public class LevelInitMessage extends AbstractNetworkMessage
|
|||||||
@Override
|
@Override
|
||||||
public void decode(ByteBuf in)
|
public void decode(ByteBuf in)
|
||||||
{
|
{
|
||||||
|
this.serverKey = this.readString(in);
|
||||||
this.levelKey = this.readString(in);
|
this.levelKey = this.readString(in);
|
||||||
this.serverTime = in.readLong();
|
this.serverTime = in.readLong();
|
||||||
}
|
}
|
||||||
@@ -62,6 +71,7 @@ public class LevelInitMessage extends AbstractNetworkMessage
|
|||||||
public MoreObjects.ToStringHelper toStringHelper()
|
public MoreObjects.ToStringHelper toStringHelper()
|
||||||
{
|
{
|
||||||
return super.toStringHelper()
|
return super.toStringHelper()
|
||||||
|
.add("serverKey", this.serverKey)
|
||||||
.add("levelKey", this.levelKey)
|
.add("levelKey", this.levelKey)
|
||||||
.add("serverTime", this.serverTime);
|
.add("serverTime", this.serverTime);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-14
@@ -22,8 +22,8 @@ package com.seibel.distanthorizons.core.network.messages.fullData;
|
|||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.seibel.distanthorizons.core.multiplayer.fullData.FullDataPayload;
|
import com.seibel.distanthorizons.core.multiplayer.fullData.FullDataPayload;
|
||||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||||
import com.seibel.distanthorizons.core.util.TimerUtil;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
|
|
||||||
@@ -34,16 +34,10 @@ import java.util.Timer;
|
|||||||
*/
|
*/
|
||||||
public class FullDataSplitMessage extends AbstractNetworkMessage
|
public class FullDataSplitMessage extends AbstractNetworkMessage
|
||||||
{
|
{
|
||||||
private static final long BUFFER_RELEASE_DELAY_MS = 5000L;
|
|
||||||
|
|
||||||
public int bufferId;
|
public int bufferId;
|
||||||
public ByteBuf buffer;
|
public ByteBuf buffer;
|
||||||
public boolean isFirst;
|
public boolean isFirst;
|
||||||
|
|
||||||
// Reference counting is unreliable here for some reason so this is a "fix"
|
|
||||||
private static final Timer bufferReleaseTimer = TimerUtil.CreateTimer("FullDataBufferCleanupTimer");
|
|
||||||
private boolean releaseScheduled = false;
|
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
// constructors //
|
// constructors //
|
||||||
@@ -72,12 +66,6 @@ public class FullDataSplitMessage extends AbstractNetworkMessage
|
|||||||
out.writeBytes(this.buffer.readerIndex(0));
|
out.writeBytes(this.buffer.readerIndex(0));
|
||||||
|
|
||||||
out.writeBoolean(this.isFirst);
|
out.writeBoolean(this.isFirst);
|
||||||
|
|
||||||
if (!this.releaseScheduled)
|
|
||||||
{
|
|
||||||
bufferReleaseTimer.schedule(TimerUtil.createTimerTask(this.buffer::release), BUFFER_RELEASE_DELAY_MS);
|
|
||||||
this.releaseScheduled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,7 +74,7 @@ public class FullDataSplitMessage extends AbstractNetworkMessage
|
|||||||
this.bufferId = in.readInt();
|
this.bufferId = in.readInt();
|
||||||
|
|
||||||
int bufferSize = in.readInt();
|
int bufferSize = in.readInt();
|
||||||
this.buffer = in.readBytes(bufferSize);
|
this.buffer = Unpooled.copiedBuffer(in.readSlice(bufferSize));
|
||||||
|
|
||||||
this.isFirst = in.readBoolean();
|
this.isFirst = in.readBoolean();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public abstract class AbstractDhServerWorld<TDhServerLevel extends AbstractDhSer
|
|||||||
public void addPlayer(IServerPlayerWrapper serverPlayer)
|
public void addPlayer(IServerPlayerWrapper serverPlayer)
|
||||||
{
|
{
|
||||||
ServerPlayerState playerState = this.serverPlayerStateManager.registerJoinedPlayer(serverPlayer);
|
ServerPlayerState playerState = this.serverPlayerStateManager.registerJoinedPlayer(serverPlayer);
|
||||||
this.getLevel(serverPlayer.getLevel()).addPlayer(serverPlayer);
|
((TDhServerLevel) this.getOrLoadServerLevel(serverPlayer.getLevel())).addPlayer(serverPlayer);
|
||||||
|
|
||||||
Iterator<TDhServerLevel> it = this.dhLevelByLevelWrapper.values().stream().distinct().iterator();
|
Iterator<TDhServerLevel> it = this.dhLevelByLevelWrapper.values().stream().distinct().iterator();
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
|
|||||||
@@ -1022,6 +1022,8 @@
|
|||||||
"File: Info, Chat: Warning",
|
"File: Info, Chat: Warning",
|
||||||
"distanthorizons.config.enum.EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE":
|
"distanthorizons.config.enum.EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE":
|
||||||
"File: Info, Chat: Error",
|
"File: Info, Chat: Error",
|
||||||
|
"distanthorizons.config.enum.EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_WARNING_TO_FILE":
|
||||||
|
"File: Warning, Chat: Error",
|
||||||
|
|
||||||
"distanthorizons.config.enum.EDhApiGpuUploadMethod.AUTO":
|
"distanthorizons.config.enum.EDhApiGpuUploadMethod.AUTO":
|
||||||
"Auto",
|
"Auto",
|
||||||
|
|||||||
Reference in New Issue
Block a user