diff --git a/README.md b/README.md index 936544b..6778185 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ com.github.Be4rJP Parallel - v1.1.0 + v1.1.1 provided ``` diff --git a/pom.xml b/pom.xml index 2998580..51f69ca 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ be4rjp Parallel - 1.1.0 + 1.1.1 jar Parallel diff --git a/src/main/java/be4rjp/parallel/Config.java b/src/main/java/be4rjp/parallel/Config.java index 396bb72..9b65693 100644 --- a/src/main/java/be4rjp/parallel/Config.java +++ b/src/main/java/be4rjp/parallel/Config.java @@ -11,13 +11,17 @@ public class Config { private static boolean performanceMode = false; private static boolean rewriteLightPacket = true; + + private static boolean showChunkPacketWarning = true; public static WorkType getWorkType() {return workType;} public static boolean isPerformanceMode() {return performanceMode;} public static boolean isRewriteLightPacket() {return rewriteLightPacket;} - + + public static boolean isShowChunkPacketWarning() {return showChunkPacketWarning;} + public static void load(){ File file = new File("plugins/Parallel", "config.yml"); file.getParentFile().mkdirs(); @@ -32,6 +36,7 @@ public static void load(){ if(yml.contains("work-type")) workType = WorkType.valueOf(yml.getString("work-type")); if(yml.contains("performance-mode")) performanceMode = yml.getBoolean("performance-mode"); if(yml.contains("rewrite-light-packet")) rewriteLightPacket = yml.getBoolean("rewrite-light-packet"); + if(yml.contains("show-chunk-packet-warning")) showChunkPacketWarning = yml.getBoolean("show-chunk-packet-warning"); } public enum WorkType{ diff --git a/src/main/java/be4rjp/parallel/EventListener.java b/src/main/java/be4rjp/parallel/EventListener.java index cd30064..b37c197 100644 --- a/src/main/java/be4rjp/parallel/EventListener.java +++ b/src/main/java/be4rjp/parallel/EventListener.java @@ -1,14 +1,18 @@ package be4rjp.parallel; +import be4rjp.parallel.chunk.AsyncChunkCash; import be4rjp.parallel.nms.NMSUtil; import be4rjp.parallel.nms.PacketHandler; import io.netty.channel.Channel; import io.netty.channel.ChannelPipeline; +import org.bukkit.Chunk; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.ChunkLoadEvent; public class EventListener implements Listener { @@ -44,4 +48,13 @@ public void onleave(PlayerQuitEvent event){ e.printStackTrace(); } } + + @EventHandler + public void onChunkLoad(ChunkLoadEvent event){ + World world = event.getWorld(); + Chunk chunk = event.getChunk(); + + AsyncChunkCash asyncChunkCash = AsyncChunkCash.computeIfAbsentWorldAsyncChunkCash(world.getName()); + asyncChunkCash.addLoadedChunk(chunk); + } } diff --git a/src/main/java/be4rjp/parallel/chunk/AsyncChunkCash.java b/src/main/java/be4rjp/parallel/chunk/AsyncChunkCash.java new file mode 100644 index 0000000..20d454e --- /dev/null +++ b/src/main/java/be4rjp/parallel/chunk/AsyncChunkCash.java @@ -0,0 +1,35 @@ +package be4rjp.parallel.chunk; + +import be4rjp.parallel.nms.NMSUtil; +import org.bukkit.Chunk; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class AsyncChunkCash { + + private static final Map worldChunkCashMap = new ConcurrentHashMap<>(); + + public static AsyncChunkCash computeIfAbsentWorldAsyncChunkCash(String worldName){ + return worldChunkCashMap.computeIfAbsent(worldName, k -> new AsyncChunkCash()); + } + + public static AsyncChunkCash getWorldAsyncChunkCash(String worldName){ + return worldChunkCashMap.get(worldName); + } + + private final Map chunkCashMap = new ConcurrentHashMap<>(); + + public void addLoadedChunk(Chunk chunk){ + try { + Object nmsChunk = NMSUtil.getNMSChunk(chunk); + long coordinate = ((long)chunk.getX() << 32) | (chunk.getZ() & 0xFFFFFFFFL); + chunkCashMap.put(coordinate, nmsChunk); + } catch (Exception e) {e.printStackTrace();} + } + + public Object getCashedChunk(int chunkX, int chunkZ){ + return chunkCashMap.get(((long)chunkX << 32) | (chunkZ & 0xFFFFFFFFL)); + } + +} diff --git a/src/main/java/be4rjp/parallel/nms/manager/ChunkPacketManager.java b/src/main/java/be4rjp/parallel/nms/manager/ChunkPacketManager.java index f5fe852..3c13724 100644 --- a/src/main/java/be4rjp/parallel/nms/manager/ChunkPacketManager.java +++ b/src/main/java/be4rjp/parallel/nms/manager/ChunkPacketManager.java @@ -1,7 +1,9 @@ package be4rjp.parallel.nms.manager; import be4rjp.parallel.Config; +import be4rjp.parallel.Parallel; import be4rjp.parallel.ParallelWorld; +import be4rjp.parallel.chunk.AsyncChunkCash; import be4rjp.parallel.nms.NMSUtil; import be4rjp.parallel.nms.PacketHandler; import be4rjp.parallel.util.BlockLocation; @@ -85,7 +87,20 @@ public void run() { } Object nmsWorld = NMSUtil.getNMSWorld(player.getWorld()); - Object nmsChunk = NMSUtil.getNMSChunk(player.getWorld().getChunkAt(chunkX, chunkZ)); + + AsyncChunkCash asyncChunkCash = AsyncChunkCash.getWorldAsyncChunkCash(player.getWorld().getName()); + if(asyncChunkCash == null){ + packetHandler.doWrite(channelHandlerContext, packet, channelPromise); + sendChunkWarnMessage(); + return; + } + + Object nmsChunk = asyncChunkCash.getCashedChunk(chunkX, chunkZ); + if(nmsChunk == null){ + packetHandler.doWrite(channelHandlerContext, packet, channelPromise); + sendChunkWarnMessage(); + return; + } Object newChunk = NMSUtil.createChunk(nmsWorld, loc.get(nmsChunk), d.get(nmsChunk)); @@ -149,8 +164,13 @@ public void run() { parallelWorld.getEditedPacketForChunkMap().put(chunkLocation, newPacket); packetHandler.doWrite(channelHandlerContext, newPacket, channelPromise); }catch (ClosedChannelException e){ + //None }catch (Exception e){ e.printStackTrace(); } } + + public static void sendChunkWarnMessage(){ + if(Config.isShowChunkPacketWarning()) Parallel.getPlugin().getLogger().warning("Attempted to send a packet with an unloaded chunk."); + } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 88c296d..8821f80 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,14 +1,14 @@ - # 動作モードの設定 # NORMAL or ONLY_ONE # ONLY_ONEに設定した場合は全てのプレイヤーに対して同じParallelWorldが使われるようになります work-type: NORMAL - # パフォーマンスモードを使用するかどうかの設定 # このプラグイン以外でブロックの設置が行われる可能性のある場合は false 推奨 performance-mode: false - ## ライトパケットへの介入を行うかどうかの設定 -rewrite-light-packet: true \ No newline at end of file +rewrite-light-packet: true + +# 読み込まれていないチャンクのパケットを送信しようとしたときに警告を表示するかどうかの設定 +show-chunk-packet-warning: true \ No newline at end of file