diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java index 55580d415..22058c878 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java @@ -2,6 +2,7 @@ package com.seibel.distanthorizons.core.file.fullDatafile; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; +import com.seibel.distanthorizons.core.level.DhClientLevel; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.network.NetworkClient; @@ -25,17 +26,35 @@ public class RemoteFullDataFileHandler extends FullDataFileHandler @Override public CompletableFuture read(DhSectionPos pos) { - // TODO: LOD data file updating is probably incomplete - return super.read(pos).thenCompose((fullDataSource) -> { - CompletableFuture responseFuture = networkClient.sendRequest(new FullDataSourceRequestMessage(pos)) - .exceptionally(throwable -> { - LOGGER.error(throwable); - return null; - }); - responseFuture.thenAccept(response -> LOGGER.info("ChunkResponseMessage "+pos)); + return super.read(pos).thenCompose(fullDataSource -> { + if (fullDataSource == null) + return null; + + if (!fullDataSource.isEmpty()) + return CompletableFuture.completedFuture(fullDataSource); FullDataMetaFile metaFile = this.getLoadOrMakeFile(pos, true); - return onDataFileUpdate(fullDataSource, metaFile, iFullDataSource -> {}, iFullDataSource -> true); + return networkClient.sendRequest(new FullDataSourceRequestMessage(pos)) + .handle((response, throwable) -> { + try + { + if (throwable != null) + throw throwable; + + LOGGER.info("FullDataSourceResponseMessage " + pos); + return response.getFullDataSource(metaFile, pos, level); + } + catch (Exception e) + { + LOGGER.error(e); + return null; + } + catch (Throwable e) + { + LOGGER.error(e.toString()); + return null; + } + }); }); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/FullDataSourceRequestMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/FullDataSourceRequestMessage.java index 3bef7e812..1185f265e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/FullDataSourceRequestMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/FullDataSourceRequestMessage.java @@ -1,10 +1,14 @@ package com.seibel.distanthorizons.core.network.messages; +import com.google.common.collect.MapMaker; +import com.seibel.distanthorizons.core.level.DhClientLevel; import com.seibel.distanthorizons.core.network.protocol.FutureTrackableNetworkMessage; import com.seibel.distanthorizons.core.network.protocol.INetworkObject; import com.seibel.distanthorizons.core.pos.DhSectionPos; import io.netty.buffer.ByteBuf; +import java.util.concurrent.ConcurrentMap; + public class FullDataSourceRequestMessage extends FutureTrackableNetworkMessage { public DhSectionPos dhSectionPos; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/FullDataSourceResponseMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/FullDataSourceResponseMessage.java index a35c09f5d..fb608fa7d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/FullDataSourceResponseMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/FullDataSourceResponseMessage.java @@ -1,16 +1,26 @@ package com.seibel.distanthorizons.core.network.messages; +import com.seibel.distanthorizons.core.dataObjects.fullData.sources.HighDetailIncompleteFullDataSource; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource; +import com.seibel.distanthorizons.core.file.fullDatafile.FullDataMetaFile; 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.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 java.io.ByteArrayOutputStream; import java.io.IOException; public class FullDataSourceResponseMessage extends FutureTrackableNetworkMessage { - public IFullDataSource fullDataSource; - public DhServerLevel level; + private IFullDataSource fullDataSource; + private DhServerLevel level; + + private ByteBufInputStream inputStream; public FullDataSourceResponseMessage() {} public FullDataSourceResponseMessage(IFullDataSource fullDataSource, DhServerLevel level) @@ -22,13 +32,28 @@ public class FullDataSourceResponseMessage extends FutureTrackableNetworkMessage @Override public void encode0(ByteBuf out) throws IOException { - //fullDataSource.writeToStream(new DhDataOutputStream(new ByteBufOutputStream(out)), level); + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) + { + DhDataOutputStream dhOutputStream = new DhDataOutputStream(outputStream); + fullDataSource.writeToStream(dhOutputStream, level); + dhOutputStream.flush(); + + out.writeInt(outputStream.size()); + out.writeBytes(outputStream.toByteArray()); + } } @Override public void decode0(ByteBuf in) { - //DhSectionPos sectionPos = INetworkObject.decode(new DhSectionPos((byte) 0, (byte) 0, (byte) 0), in); - //fullDataSource = HighDetailIncompleteFullDataSource.createEmpty(sectionPos); + inputStream = new ByteBufInputStream(in.readBytes(in.readInt())); + } + + public IFullDataSource getFullDataSource(FullDataMetaFile metaFile, DhSectionPos pos, IDhLevel level) throws IOException, InterruptedException + { + IFullDataSource fullDataSource = HighDetailIncompleteFullDataSource.createEmpty(pos); + fullDataSource.populateFromStream(metaFile, new DhDataInputStream(inputStream), level); + inputStream.close(); + return fullDataSource; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/FutureTrackableNetworkMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/FutureTrackableNetworkMessage.java index dc6596950..362232c59 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/FutureTrackableNetworkMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/FutureTrackableNetworkMessage.java @@ -1,16 +1,17 @@ package com.seibel.distanthorizons.core.network.protocol; import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; public abstract class FutureTrackableNetworkMessage implements INetworkMessage { private static int lastId = 0; public int futureId = lastId++; - public static FutureTrackableNetworkMessage makeResponse(FutureTrackableNetworkMessage requestMessage, FutureTrackableNetworkMessage responseMessage) + public static void sendResponse(ChannelHandlerContext ctx, FutureTrackableNetworkMessage requestMessage, FutureTrackableNetworkMessage responseMessage) { responseMessage.futureId = requestMessage.futureId; - return responseMessage; + ctx.writeAndFlush(responseMessage); } @Override public final void encode(ByteBuf out) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkChannelInitializer.java b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkChannelInitializer.java index f021396b6..856f39d0b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkChannelInitializer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkChannelInitializer.java @@ -21,12 +21,12 @@ public class NetworkChannelInitializer extends ChannelInitializer ChannelPipeline pipeline = socketChannel.pipeline(); // Encoder - pipeline.addLast(new LengthFieldPrepender(Short.BYTES)); + pipeline.addLast(new LengthFieldPrepender(Integer.BYTES)); pipeline.addLast(new MessageEncoder()); pipeline.addLast(new NetworkOutboundExceptionRouter()); // Decoder - pipeline.addLast(new LengthFieldBasedFrameDecoder(Short.MAX_VALUE, 0, Short.BYTES, 0, Short.BYTES)); + pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, Integer.BYTES, 0, Integer.BYTES)); pipeline.addLast(new MessageDecoder()); // Handler diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java index f8e1407ad..71a49e53d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java @@ -90,11 +90,11 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld this.networkServer.registerHandler(FullDataSourceRequestMessage.class, (msg, ctx) -> { if (msg.dhSectionPos == null) { - LOGGER.warn("RequestChunksMessage received with null msg.dhSectionPos"); + LOGGER.warn("FullDataSourceRequestMessage received with null msg.dhSectionPos"); return; } - LOGGER.info("RequestChunksMessage received at pos ({}, {}) with detail level {}", msg.dhSectionPos.sectionX, msg.dhSectionPos.sectionZ, msg.dhSectionPos.sectionDetailLevel); + LOGGER.info("FullDataSourceRequestMessage received at pos ({}, {}) with detail level {}", msg.dhSectionPos.sectionX, msg.dhSectionPos.sectionZ, msg.dhSectionPos.sectionDetailLevel); // hasReceivedChunkRequest should be false somewhere ??? // to avoid sending updates until client says at least something about its state @@ -102,11 +102,11 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld DhServerLevel level = this.getLevel(playersByConnection.get(ctx).serverPlayer.getLevel()); // TODO: Add level to packet - level.serverside.worldGenTick(new DhBlockPos2D(msg.dhSectionPos.sectionX, msg.dhSectionPos.sectionZ)); + //level.serverside.worldGenTick(new DhBlockPos2D(msg.dhSectionPos.sectionX, msg.dhSectionPos.sectionZ)); level.serverside.dataFileHandler.read(msg.dhSectionPos).thenAccept(fullDataSource -> { // Send chunk response message back - ctx.writeAndFlush(FutureTrackableNetworkMessage.makeResponse(msg, new FullDataSourceResponseMessage(fullDataSource, level))); + FutureTrackableNetworkMessage.sendResponse(ctx, msg, new FullDataSourceResponseMessage(fullDataSource, level)); }); }); }