Incomplete
This commit is contained in:
+2
-1
@@ -35,7 +35,8 @@ public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<
|
||||
|
||||
public AbstractPresetConfigEventHandler()
|
||||
{
|
||||
configGui.addOnScreenChangeListener(() -> this.onConfigUiClosed());
|
||||
if (configGui != null)
|
||||
configGui.addOnScreenChangeListener(() -> this.onConfigUiClosed());
|
||||
}
|
||||
|
||||
|
||||
|
||||
+23
@@ -10,6 +10,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.FullDataMetaFile;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
@@ -23,6 +24,7 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import java.io.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* This data source contains every datapoint over its given {@link DhSectionPos}.
|
||||
@@ -368,6 +370,27 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
|
||||
}
|
||||
}
|
||||
|
||||
public void splitIntoChunkSizedAccessors(Consumer<ChunkSizedFullDataAccessor> consumer)
|
||||
{
|
||||
LodUtil.assertTrue(sectionPos.sectionDetailLevel == DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, "Data source detail level must be at block detail level.");
|
||||
|
||||
sectionPos.forEachChildAtLevel(LodUtil.CHUNK_DETAIL_LEVEL, childPos -> {
|
||||
ChunkSizedFullDataAccessor accessor = new ChunkSizedFullDataAccessor(new DhChunkPos(childPos.sectionX, childPos.sectionZ));
|
||||
|
||||
int detailLevelDifference = sectionPos.sectionDetailLevel - childPos.sectionDetailLevel;
|
||||
int childRelativeX = childPos.sectionX - sectionPos.sectionX * BitShiftUtil.powerOfTwo(detailLevelDifference);
|
||||
int childRelativeZ = childPos.sectionZ - sectionPos.sectionZ * BitShiftUtil.powerOfTwo(detailLevelDifference);
|
||||
|
||||
subView(
|
||||
LodUtil.CHUNK_WIDTH,
|
||||
childRelativeX * LodUtil.CHUNK_WIDTH,
|
||||
childRelativeZ * LodUtil.CHUNK_WIDTH
|
||||
).shadowCopyTo(accessor);
|
||||
|
||||
consumer.accept(accessor);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
|
||||
-2
@@ -82,8 +82,6 @@ public class ChunkToLodBuilder implements AutoCloseable
|
||||
}
|
||||
else if (MC != null && !MC.playerExists())
|
||||
{
|
||||
// TODO handle server side properly
|
||||
|
||||
// MC hasn't finished loading (or is currently unloaded)
|
||||
|
||||
// can be uncommented if tasks aren't being cleared correctly
|
||||
|
||||
+1
-15
@@ -195,21 +195,7 @@ public class WorldRemoteGenerationQueue implements IWorldGenerationQueue, IDebug
|
||||
if (chunkDataConsumer == null)
|
||||
return entry.future.cancel(false);
|
||||
|
||||
sectionPos.forEachChildAtLevel(LodUtil.CHUNK_DETAIL_LEVEL, childPos -> {
|
||||
ChunkSizedFullDataAccessor accessor = new ChunkSizedFullDataAccessor(new DhChunkPos(childPos.sectionX, childPos.sectionZ));
|
||||
|
||||
int detailLevelDifference = sectionPos.sectionDetailLevel - childPos.sectionDetailLevel;
|
||||
int childRelativeX = childPos.sectionX - sectionPos.sectionX * BitShiftUtil.powerOfTwo(detailLevelDifference);
|
||||
int childRelativeZ = childPos.sectionZ - sectionPos.sectionZ * BitShiftUtil.powerOfTwo(detailLevelDifference);
|
||||
|
||||
fullDataSource.subView(
|
||||
LodUtil.CHUNK_WIDTH,
|
||||
childRelativeX * LodUtil.CHUNK_WIDTH,
|
||||
childRelativeZ * LodUtil.CHUNK_WIDTH
|
||||
).shadowCopyTo(accessor);
|
||||
|
||||
chunkDataConsumer.accept(accessor);
|
||||
});
|
||||
fullDataSource.splitIntoChunkSizedAccessors(chunkDataConsumer);
|
||||
}
|
||||
catch (ChannelException | RateLimitedException e)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.seibel.distanthorizons.core.level;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.RemoteFullDataFileHandler;
|
||||
@@ -8,22 +9,30 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.generation.WorldRemoteGenerationQueue;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.multiplayer.ClientNetworkState;
|
||||
import com.seibel.distanthorizons.core.network.NetworkClient;
|
||||
import com.seibel.distanthorizons.core.network.ScopedNetworkEventSource;
|
||||
import com.seibel.distanthorizons.core.network.messages.FullDataSourceRequestMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.FullDataSourceUpdateMessage;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/** The level used when connected to a server */
|
||||
@@ -47,6 +56,8 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel
|
||||
|
||||
@CheckForNull
|
||||
private final ClientNetworkState networkState;
|
||||
@Nullable
|
||||
private final ScopedNetworkEventSource<NetworkClient> eventSource;
|
||||
public final WorldGenModule worldGenModule;
|
||||
|
||||
|
||||
@@ -63,12 +74,41 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel
|
||||
|
||||
this.networkState = networkState;
|
||||
this.worldGenModule = new WorldGenModule(dataFileHandler, this);
|
||||
if (networkState != null)
|
||||
{
|
||||
this.eventSource = new ScopedNetworkEventSource<>(networkState.getClient());
|
||||
this.registerNetworkHandlers();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.eventSource = null;
|
||||
}
|
||||
|
||||
clientside = new ClientLevelModule(this);
|
||||
clientside.startRenderer();
|
||||
LOGGER.info("Started DHLevel for " + this.levelWrapper + " with saves at " + this.saveStructure);
|
||||
}
|
||||
|
||||
private void registerNetworkHandlers()
|
||||
{
|
||||
assert this.eventSource != null;
|
||||
|
||||
this.eventSource.registerHandler(FullDataSourceUpdateMessage.class, msg ->
|
||||
{
|
||||
try
|
||||
{
|
||||
CompleteFullDataSource fullDataSource = msg.getFullDataSource(this);
|
||||
if (fullDataSource == null) return;
|
||||
|
||||
fullDataSource.splitIntoChunkSizedAccessors(this::saveWrites);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Error while updating full data source", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//==============//
|
||||
// tick methods //
|
||||
//==============//
|
||||
|
||||
@@ -25,7 +25,7 @@ public abstract class DhLevel implements IDhLevel
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChunkAsync(IChunkWrapper chunk)
|
||||
public CompletableFuture<ChunkSizedFullDataAccessor> updateChunkAsync(IChunkWrapper chunk)
|
||||
{
|
||||
CompletableFuture<ChunkSizedFullDataAccessor> future = this.chunkToLodBuilder.tryGenerateData(chunk);
|
||||
if (future != null)
|
||||
@@ -44,6 +44,7 @@ public abstract class DhLevel implements IDhLevel
|
||||
new DhApiChunkModifiedEvent.EventParam(this.getLevelWrapper(), chunk.getChunkPos().x, chunk.getChunkPos().z));
|
||||
});
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedF
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataMetaFile;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider;
|
||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.multiplayer.ServerPlayerState;
|
||||
@@ -15,10 +16,12 @@ import com.seibel.distanthorizons.core.network.NetworkServer;
|
||||
import com.seibel.distanthorizons.core.network.exceptions.RateLimitedException;
|
||||
import com.seibel.distanthorizons.core.network.messages.*;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
@@ -26,9 +29,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
@@ -40,7 +41,7 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
private final RemotePlayerConnectionHandler remotePlayerConnectionHandler;
|
||||
private final ScopedNetworkEventSource<NetworkServer> eventSource;
|
||||
|
||||
private final ConcurrentLinkedQueue<IServerPlayerWrapper> worldGenLoopingQueue = new ConcurrentLinkedQueue<>();
|
||||
private final LinkedBlockingQueue<IServerPlayerWrapper> worldGenLoopingQueue = new LinkedBlockingQueue<>();
|
||||
private final ConcurrentMap<DhSectionPos, IncompleteDataSourceEntry> incompleteDataSources = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<Long, IncompleteDataSourceEntry> fullDataRequests = new ConcurrentHashMap<>();
|
||||
private final AppliedConfigState<Integer> rateLimitConfig = new AppliedConfigState<>(Config.Client.Advanced.Multiplayer.serverNetworkingRateLimit);
|
||||
@@ -66,12 +67,16 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
// TODO implement transparent message handling restriction by level
|
||||
// workaround:
|
||||
// ServerPlayerState serverPlayerState = remotePlayerConnectionHandler.getConnectedPlayer(msg);
|
||||
// if (serverPlayerState == null) return;
|
||||
//
|
||||
// if (serverPlayerState.serverPlayer.getLevel() != this.serverLevelWrapper)
|
||||
// return;
|
||||
|
||||
this.eventSource.registerHandler(FullDataSourceRequestMessage.class, msg ->
|
||||
{
|
||||
ServerPlayerState serverPlayerState = remotePlayerConnectionHandler.getConnectedPlayer(msg);
|
||||
if (serverPlayerState == null) return;
|
||||
|
||||
if (serverPlayerState.serverPlayer.getLevel() != this.serverLevelWrapper)
|
||||
return;
|
||||
|
||||
@@ -106,6 +111,8 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
|
||||
this.eventSource.registerHandler(GenTaskPriorityRequestMessage.class, msg -> {
|
||||
ServerPlayerState serverPlayerState = remotePlayerConnectionHandler.getConnectedPlayer(msg);
|
||||
if (serverPlayerState == null) return;
|
||||
|
||||
if (serverPlayerState.serverPlayer.getLevel() != this.serverLevelWrapper)
|
||||
return;
|
||||
|
||||
@@ -120,7 +127,9 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
if (entry == null) return;
|
||||
FullDataSourceRequestMessage requestMessage = entry.requestMessages.remove(msg.futureId);
|
||||
|
||||
remotePlayerConnectionHandler.getConnectedPlayer(msg).pendingFullDataRequests.decrementAndGet();
|
||||
ServerPlayerState serverPlayerState = remotePlayerConnectionHandler.getConnectedPlayer(msg);
|
||||
if (serverPlayerState != null)
|
||||
serverPlayerState.pendingFullDataRequests.decrementAndGet();
|
||||
|
||||
entry.requestCollectionSemaphore.acquireUninterruptibly(Short.MAX_VALUE);
|
||||
if (entry.requestMessages.isEmpty())
|
||||
@@ -135,18 +144,12 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
|
||||
public void addPlayer(IServerPlayerWrapper serverPlayer)
|
||||
{
|
||||
synchronized (worldGenLoopingQueue)
|
||||
{
|
||||
this.worldGenLoopingQueue.add(serverPlayer);
|
||||
}
|
||||
this.worldGenLoopingQueue.add(serverPlayer);
|
||||
}
|
||||
|
||||
public void removePlayer(IServerPlayerWrapper serverPlayer)
|
||||
{
|
||||
synchronized (worldGenLoopingQueue)
|
||||
{
|
||||
this.worldGenLoopingQueue.remove(serverPlayer);
|
||||
}
|
||||
boolean ignored = this.worldGenLoopingQueue.remove(serverPlayer);
|
||||
}
|
||||
|
||||
public void serverTick()
|
||||
@@ -189,6 +192,42 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ChunkSizedFullDataAccessor> updateChunkAsync(IChunkWrapper chunk)
|
||||
{
|
||||
DhSectionPos sectionPos = new DhSectionPos(chunk.getChunkPos()).convertToDetailLevel(DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
|
||||
FullDataMetaFile metaFile = this.serverside.dataFileHandler.getFileIfExist(sectionPos);
|
||||
int prevChecksum = metaFile != null ? metaFile.baseMetaData.checksum : 0;
|
||||
|
||||
CompletableFuture<ChunkSizedFullDataAccessor> future = super.updateChunkAsync(chunk);
|
||||
if (future == null)
|
||||
return null;
|
||||
|
||||
future.thenRun(() ->
|
||||
{
|
||||
if (metaFile == null || metaFile.baseMetaData.checksum == prevChecksum)
|
||||
return;
|
||||
|
||||
this.serverside.dataFileHandler.read(sectionPos).thenAccept(fullDataSource ->
|
||||
{
|
||||
if (!(fullDataSource instanceof CompleteFullDataSource))
|
||||
return;
|
||||
CompleteFullDataSource completeSource = (CompleteFullDataSource) fullDataSource;
|
||||
|
||||
for (IServerPlayerWrapper serverPlayer : worldGenLoopingQueue)
|
||||
{
|
||||
ServerPlayerState serverPlayerState = remotePlayerConnectionHandler.getPlayer(serverPlayer);
|
||||
if (serverPlayerState == null) continue;
|
||||
|
||||
if (chunk.getChunkPos().distance(new DhChunkPos(serverPlayer.getPosition())) <= serverPlayerState.config.renderDistance)
|
||||
serverPlayerState.channelContext.writeAndFlush(new FullDataSourceUpdateMessage(completeSource, this));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveWrites(ChunkSizedFullDataAccessor data)
|
||||
{
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.seibel.distanthorizons.core.level;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider;
|
||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -20,7 +22,8 @@ public interface IDhLevel extends AutoCloseable
|
||||
*/
|
||||
ILevelWrapper getLevelWrapper();
|
||||
|
||||
void updateChunkAsync(IChunkWrapper chunk);
|
||||
@Nullable
|
||||
CompletableFuture<ChunkSizedFullDataAccessor> updateChunkAsync(IChunkWrapper chunk);
|
||||
|
||||
IFullDataSourceProvider getFileHandler();
|
||||
|
||||
|
||||
+2
-2
@@ -2,7 +2,6 @@ package com.seibel.distanthorizons.core.multiplayer;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.network.IClientRequestHandler;
|
||||
import com.seibel.distanthorizons.core.network.ScopedNetworkEventSource;
|
||||
import com.seibel.distanthorizons.core.network.NetworkClient;
|
||||
import com.seibel.distanthorizons.core.network.messages.AckMessage;
|
||||
@@ -10,6 +9,7 @@ import com.seibel.distanthorizons.core.network.messages.HelloMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.PlayerUUIDMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.RemotePlayerConfigMessage;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.UUID;
|
||||
@@ -26,7 +26,7 @@ public class ClientNetworkState implements Closeable
|
||||
* Returns the client used by this instance. <p>
|
||||
* If you need to subscribe to any packet events, create an instance of {@link ScopedNetworkEventSource} using the returned instance.
|
||||
*/
|
||||
public IClientRequestHandler getClient() { return this.client; }
|
||||
public NetworkClient getClient() { return this.client; }
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
|
||||
+3
@@ -10,6 +10,7 @@ import com.seibel.distanthorizons.core.network.messages.PlayerUUIDMessage;
|
||||
import com.seibel.distanthorizons.core.network.protocol.NetworkMessage;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.HashMap;
|
||||
@@ -69,11 +70,13 @@ public class RemotePlayerConnectionHandler implements Closeable
|
||||
return playersByConnection.values();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ServerPlayerState getConnectedPlayer(NetworkMessage msg)
|
||||
{
|
||||
return playersByConnection.get(msg.getChannelContext());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ServerPlayerState getPlayer(IServerPlayerWrapper serverPlayer)
|
||||
{
|
||||
return playersByUUID.get(serverPlayer.getUUID());
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.network;
|
||||
|
||||
import com.seibel.distanthorizons.core.network.protocol.FutureTrackableNetworkMessage;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface IClientRequestHandler
|
||||
{
|
||||
/** Indicates whether the client is initialized and not started connecting yet. */
|
||||
boolean isInitialState();
|
||||
/** Indicates whether the client is closed(-ing) and should not be used. */
|
||||
boolean isClosed();
|
||||
/** Indicates whether the connection is established and first message is sent. */
|
||||
boolean isReady();
|
||||
|
||||
/** Sends a new request. */
|
||||
<TResponse extends FutureTrackableNetworkMessage> CompletableFuture<TResponse> sendRequest(FutureTrackableNetworkMessage msg);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class NetworkClient extends NetworkEventSource implements IClientRequestHandler, AutoCloseable
|
||||
public class NetworkClient extends NetworkEventSource implements AutoCloseable
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ import com.google.common.collect.Table;
|
||||
import com.google.common.collect.Tables;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.network.messages.CancelMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.CloseEvent;
|
||||
import com.seibel.distanthorizons.core.network.messages.ExceptionMessage;
|
||||
import com.seibel.distanthorizons.core.network.protocol.FutureTrackableNetworkMessage;
|
||||
import com.seibel.distanthorizons.core.network.protocol.MessageRegistry;
|
||||
import com.seibel.distanthorizons.core.network.protocol.NetworkMessage;
|
||||
import io.netty.channel.ChannelException;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
@@ -75,7 +77,13 @@ public abstract class NetworkEventSource
|
||||
|
||||
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation)
|
||||
{
|
||||
this.handlers.computeIfAbsent(handlerClass, missingHandlerClass -> new HashSet<>())
|
||||
this.handlers.computeIfAbsent(handlerClass, missingHandlerClass ->
|
||||
{
|
||||
// Will throw if the handler class is not found
|
||||
if (handlerClass != CloseEvent.class)
|
||||
MessageRegistry.INSTANCE.getMessageId(handlerClass);
|
||||
return new HashSet<>();
|
||||
})
|
||||
.add((Consumer<NetworkMessage>) handlerImplementation);
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -71,5 +71,9 @@ public class FullDataSourceResponseMessage extends FutureTrackableNetworkMessage
|
||||
{
|
||||
return fullDataSourceLoader.loadData(pos, new DhDataInputStream(inputStream), level);
|
||||
}
|
||||
finally
|
||||
{
|
||||
dataBuffer.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.seibel.distanthorizons.core.network.messages;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.loader.AbstractFullDataSourceLoader;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.loader.CompleteFullDataSourceLoader;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource;
|
||||
import com.seibel.distanthorizons.core.level.DhServerLevel;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.network.protocol.FutureTrackableNetworkMessage;
|
||||
import com.seibel.distanthorizons.core.network.protocol.INetworkObject;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream;
|
||||
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataOutputStream;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class FullDataSourceUpdateMessage extends FutureTrackableNetworkMessage
|
||||
{
|
||||
private CompleteFullDataSource fullDataSource;
|
||||
private DhServerLevel level;
|
||||
|
||||
private int levelHashCode;
|
||||
private DhSectionPos sectionPos;
|
||||
private CompleteFullDataSourceLoader fullDataSourceLoader;
|
||||
private ByteBuf dataBuffer;
|
||||
|
||||
public FullDataSourceUpdateMessage() {}
|
||||
public FullDataSourceUpdateMessage(CompleteFullDataSource fullDataSource, DhServerLevel level)
|
||||
{
|
||||
this.fullDataSource = fullDataSource;
|
||||
this.level = level;
|
||||
|
||||
// TODO Multiverse support
|
||||
this.levelHashCode = level.getLevelWrapper().getDimensionType().getDimensionName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode0(ByteBuf out) throws IOException
|
||||
{
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream())
|
||||
{
|
||||
DhDataOutputStream dhOutputStream = new DhDataOutputStream(outputStream);
|
||||
fullDataSource.writeToStream(dhOutputStream, level);
|
||||
dhOutputStream.flush();
|
||||
|
||||
out.writeInt(levelHashCode);
|
||||
fullDataSource.getSectionPos().encode(out);
|
||||
out.writeByte(fullDataSource.getBinaryDataFormatVersion());
|
||||
out.writeInt(outputStream.size());
|
||||
out.writeBytes(outputStream.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode0(ByteBuf in)
|
||||
{
|
||||
levelHashCode = in.readInt();
|
||||
sectionPos = INetworkObject.decodeStatic(DhSectionPos.zero(), in);
|
||||
byte dataVersion = in.readByte();
|
||||
this.fullDataSourceLoader = (CompleteFullDataSourceLoader) AbstractFullDataSourceLoader.getLoader(CompleteFullDataSource.TYPE_ID, dataVersion);
|
||||
this.dataBuffer = in.readBytes(in.readInt());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CompleteFullDataSource getFullDataSource(IDhLevel level) throws IOException, InterruptedException
|
||||
{
|
||||
// TODO Multiverse support
|
||||
if (levelHashCode != level.getLevelWrapper().getDimensionType().getDimensionName().hashCode())
|
||||
return null;
|
||||
|
||||
try (ByteBufInputStream inputStream = new ByteBufInputStream(dataBuffer))
|
||||
{
|
||||
return fullDataSourceLoader.loadData(sectionPos, new DhDataInputStream(inputStream), level);
|
||||
}
|
||||
finally
|
||||
{
|
||||
dataBuffer.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -35,9 +35,10 @@ public class MessageRegistry
|
||||
this.registerMessage(PlayerUUIDMessage.class, PlayerUUIDMessage::new);
|
||||
this.registerMessage(RemotePlayerConfigMessage.class, RemotePlayerConfigMessage::new);
|
||||
|
||||
// Full data requests
|
||||
// Full data requests & updates
|
||||
this.registerMessage(FullDataSourceRequestMessage.class, FullDataSourceRequestMessage::new);
|
||||
this.registerMessage(FullDataSourceResponseMessage.class, FullDataSourceResponseMessage::new);
|
||||
this.registerMessage(FullDataSourceUpdateMessage.class, FullDataSourceUpdateMessage::new);
|
||||
|
||||
// Generation task prioritization
|
||||
this.registerMessage(GenTaskPriorityRequestMessage.class, GenTaskPriorityRequestMessage::new);
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.pos;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class DhChunkPos
|
||||
@@ -48,6 +50,10 @@ public class DhChunkPos
|
||||
// >> 4 is the Same as div 16
|
||||
this(blockPos.x >> 4, blockPos.z >> 4);
|
||||
}
|
||||
public DhChunkPos(Vec3d pos)
|
||||
{
|
||||
this(((int)pos.x) >> 4, ((int)pos.z) >> 4);
|
||||
}
|
||||
public DhChunkPos(long packed) { this(getX(packed), getZ(packed)); }
|
||||
|
||||
|
||||
@@ -72,6 +78,11 @@ public class DhChunkPos
|
||||
|
||||
public long getLong() { return toLong(x, z); }
|
||||
|
||||
public double distance(DhChunkPos other)
|
||||
{
|
||||
return Math.sqrt(Math.pow(x - other.x, 2) + Math.pow(z - other.z, 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user