diff --git a/README.md b/README.md index 360f13b..8fbf0c2 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ com.github.Be4rJP Parallel - v1.0.7 + v1.0.8 ``` diff --git a/pom.xml b/pom.xml index f177492..277ea15 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ be4rjp Parallel - 1.0.7 + 1.0.8 jar Parallel diff --git a/src/main/java/be4rjp/parallel/ParallelWorld.java b/src/main/java/be4rjp/parallel/ParallelWorld.java index 9508887..45dcb8b 100644 --- a/src/main/java/be4rjp/parallel/ParallelWorld.java +++ b/src/main/java/be4rjp/parallel/ParallelWorld.java @@ -3,13 +3,8 @@ import be4rjp.parallel.enums.UpdatePacketType; import be4rjp.parallel.nms.NMSUtil; import be4rjp.parallel.nms.manager.MultiBlockChangePacketManager; -import be4rjp.parallel.util.BlockLocation; -import be4rjp.parallel.util.BlockPosition3i; -import be4rjp.parallel.util.ChunkLocation; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; +import be4rjp.parallel.util.*; +import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; @@ -50,17 +45,31 @@ public static synchronized void removeParallelWorld(String uuid){ private final String uuid; - private final Map> chunkBlockMap; + private final Map> chunkBlockMap; + private final Map editedPacketForChunkMap; + private final Map editedPacketForLightMap; private ParallelWorld(String uuid){ this.uuid = uuid; this.chunkBlockMap = new ConcurrentHashMap<>(); + this.editedPacketForChunkMap = new ConcurrentHashMap<>(); + this.editedPacketForLightMap = new ConcurrentHashMap<>(); removeParallelWorld(uuid); worldMap.put(uuid, this); } - - + + + private void addEditedChunk(ChunkPosition chunkPosition, World world){ + ChunkLocation chunkLocation = new ChunkLocation(world, chunkPosition.x << 4, chunkPosition.z << 4); + this.editedPacketForChunkMap.remove(chunkLocation); + this.editedPacketForLightMap.remove(chunkLocation); + } + + public Map getEditedPacketForChunkMap() {return editedPacketForChunkMap;} + + public Map getEditedPacketForLightMap() {return editedPacketForLightMap;} + /** * ブロックを設置します * @param block 設置したいブロック @@ -79,14 +88,16 @@ public void setBlock(Block block, Material material, boolean blockUpdate){ * @param blockUpdate ブロックの変更をプレイヤーに通知するかどうか */ public void setBlock(Block block, BlockData blockData, boolean blockUpdate){ - ChunkLocation chunkLocation = new ChunkLocation(block.getX(), block.getZ()); + ChunkPosition chunkPosition = new ChunkPosition(block.getX(), block.getZ()); + this.addEditedChunk(chunkPosition, block.getWorld()); - Map blockMap = chunkBlockMap.get(chunkLocation); + Map blockMap = chunkBlockMap.get(chunkPosition); if(blockMap == null){ blockMap = new ConcurrentHashMap<>(); - chunkBlockMap.put(chunkLocation, blockMap); + chunkBlockMap.put(chunkPosition, blockMap); } - blockMap.put(BlockLocation.createBlockLocation(block), blockData); + PBlockData pBlockData = blockMap.computeIfAbsent(BlockLocation.createBlockLocation(block), k -> new PBlockData()); + pBlockData.setBlockData(blockData); if(block.getChunk().isLoaded() && blockUpdate) { for(Player player : Bukkit.getServer().getOnlinePlayers()) { @@ -99,6 +110,25 @@ public void setBlock(Block block, BlockData blockData, boolean blockUpdate){ } + /** + * ブロックのライトレベルを設定します + * @param block 設定したいブロック + * @param level 設定したいライトレベル + */ + public void setLightLevel(Block block, int level){ + ChunkPosition chunkPosition = new ChunkPosition(block.getX(), block.getZ()); + this.addEditedChunk(chunkPosition, block.getWorld()); + + Map blockMap = chunkBlockMap.get(chunkPosition); + if(blockMap == null){ + blockMap = new ConcurrentHashMap<>(); + chunkBlockMap.put(chunkPosition, blockMap); + } + PBlockData pBlockData = blockMap.computeIfAbsent(BlockLocation.createBlockLocation(block), k -> new PBlockData()); + pBlockData.setBlockLightLevel(Math.max(level, 15)); + } + + /** * 一気に大量のブロックを設置します。 * @param blockDataMap 置き換えるブロックとブロックデータのマップ @@ -115,14 +145,16 @@ public void setBlocks(Map blockDataMap, @Nullable UpdatePacket BlockData data = entry.getValue(); Location location = block.getLocation(); - ChunkLocation chunkLocation = new ChunkLocation(location.getBlockX(), location.getBlockZ()); + ChunkPosition chunkPosition = new ChunkPosition(location.getBlockX(), location.getBlockZ()); + this.addEditedChunk(chunkPosition, block.getWorld()); - Map blockMap = chunkBlockMap.get(chunkLocation); + Map blockMap = chunkBlockMap.get(chunkPosition); if(blockMap == null){ blockMap = new ConcurrentHashMap<>(); - chunkBlockMap.put(chunkLocation, blockMap); + chunkBlockMap.put(chunkPosition, blockMap); } - blockMap.put(BlockLocation.createBlockLocation(block), data); + PBlockData pBlockData = blockMap.computeIfAbsent(BlockLocation.createBlockLocation(block), k -> new PBlockData()); + pBlockData.setBlockData(data); Set blocks = updateMap.computeIfAbsent(block.getChunk(), k -> new HashSet<>()); blocks.add(block); @@ -160,7 +192,7 @@ public void setBlocks(Map blockDataMap, @Nullable UpdatePacket short[] locations = new short[65535]; int index = 0; for(Block block : blocks){ - short loc = (short) ((block.getX() & 15) << 12 | (block.getZ() & 15) << 8 | block.getY()); + short loc = (short) ((block.getX() & 0xF) << 12 | (block.getZ() & 0xF) << 8 | block.getY()); locations[index] = loc; index++; } @@ -217,7 +249,7 @@ public void setBlocks(Map blockDataMap, @Nullable UpdatePacket * 設置した全てのブロックデータを消去します */ public void removeAll(){ - worldMap.clear(); + chunkBlockMap.clear(); } @@ -235,14 +267,16 @@ public void setBlocks(Map blockDataMap, boolean chunkUpdate){ BlockData data = entry.getValue(); BlockLocation location = BlockLocation.createBlockLocation(block); - ChunkLocation chunkLocation = new ChunkLocation(location.getX(), location.getZ()); + ChunkPosition chunkPosition = new ChunkPosition(location.getX(), location.getZ()); + this.addEditedChunk(chunkPosition, block.getWorld()); - Map blockMap = chunkBlockMap.get(chunkLocation); + Map blockMap = chunkBlockMap.get(chunkPosition); if(blockMap == null){ blockMap = new ConcurrentHashMap<>(); - chunkBlockMap.put(chunkLocation, blockMap); + chunkBlockMap.put(chunkPosition, blockMap); } - blockMap.put(location, data); + PBlockData pBlockData = blockMap.computeIfAbsent(BlockLocation.createBlockLocation(block), k -> new PBlockData()); + pBlockData.setBlockData(data); chunkSet.add(block.getChunk()); } @@ -265,6 +299,32 @@ public void setBlocks(Map blockDataMap, boolean chunkUpdate){ } + /** + * 一気に大量のブロックのライトレベルを設定します。 + * @param lightLevelMap 置き換えるブロックとブロックデータのマップ + */ + public void setLightLevels(Map lightLevelMap){ + Set chunkSet = new HashSet<>(); + + for(Map.Entry entry : lightLevelMap.entrySet()){ + Block block = entry.getKey(); + int level = Math.max(entry.getValue(), 15); + + BlockLocation location = BlockLocation.createBlockLocation(block); + ChunkPosition chunkPosition = new ChunkPosition(location.getX(), location.getZ()); + this.addEditedChunk(chunkPosition, block.getWorld()); + + Map blockMap = chunkBlockMap.get(chunkPosition); + if(blockMap == null){ + blockMap = new ConcurrentHashMap<>(); + chunkBlockMap.put(chunkPosition, blockMap); + } + PBlockData pBlockData = blockMap.computeIfAbsent(BlockLocation.createBlockLocation(block), k -> new PBlockData()); + pBlockData.setBlockLightLevel(level); + + chunkSet.add(block.getChunk()); + } + } @@ -274,19 +334,50 @@ public void setBlocks(Map blockDataMap, boolean chunkUpdate){ */ public void removeBlock(Block block){ BlockLocation location = BlockLocation.createBlockLocation(block); - ChunkLocation chunkLocation = new ChunkLocation(location.getX(), location.getZ()); + ChunkPosition chunkPosition = new ChunkPosition(location.getX(), location.getZ()); + this.addEditedChunk(chunkPosition, block.getWorld()); - Map blockMap = chunkBlockMap.get(chunkLocation); + Map blockMap = chunkBlockMap.get(chunkPosition); if(blockMap == null) return; blockMap.remove(location); } + + + /** + * ブロックデータを取得します + * @param block 取得したいブロック + * @return BlockData 見つからない場合は null を返します + */ + public @Nullable BlockData getBlockData(Block block){ + BlockLocation location = BlockLocation.createBlockLocation(block); + ChunkPosition chunkPosition = new ChunkPosition(location.getX(), location.getZ()); + + Map blockMap = chunkBlockMap.get(chunkPosition); + if(blockMap == null) return null; + return blockMap.get(location).getBlockData(); + } + + + /** + * ライトレベルを取得します + * @param block ライトレベルを取得したいブロック + * @return int(0 ~ 15) 見つからない場合は -1 を返します + */ + public int getBlockLightLevel(Block block){ + BlockLocation location = BlockLocation.createBlockLocation(block); + ChunkPosition chunkPosition = new ChunkPosition(location.getX(), location.getZ()); + + Map blockMap = chunkBlockMap.get(chunkPosition); + if(blockMap == null) return -1; + return blockMap.get(location).getBlockLightLevel(); + } /** * ブロックの編集を行いたい場合は必ずほかのメソッドを使用してください - * @return Map> + * @return Map> */ - public Map> getChunkBlockMap() { + public Map> getChunkBlockMap() { return new ConcurrentHashMap<>(chunkBlockMap); } } diff --git a/src/main/java/be4rjp/parallel/nms/NMSUtil.java b/src/main/java/be4rjp/parallel/nms/NMSUtil.java index d3f7a0c..ede6074 100644 --- a/src/main/java/be4rjp/parallel/nms/NMSUtil.java +++ b/src/main/java/be4rjp/parallel/nms/NMSUtil.java @@ -1,7 +1,7 @@ package be4rjp.parallel.nms; import be4rjp.parallel.util.BlockPosition3i; -import be4rjp.parallel.util.ChunkLocation; +import be4rjp.parallel.util.ChunkPosition; import io.netty.channel.Channel; import org.bukkit.Bukkit; import org.bukkit.Chunk; @@ -215,14 +215,14 @@ public static Object createSectionPosition(int x, int y, int z) } - public static ChunkLocation getChunkLocation(Object chunkCoordIntPair) + public static ChunkPosition getChunkLocation(Object chunkCoordIntPair) throws ClassNotFoundException, SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException { Class ChunkCoordIntPair = NMSUtil.getNMSClass("ChunkCoordIntPair"); int x = ChunkCoordIntPair.getField("x").getInt(chunkCoordIntPair); int z = ChunkCoordIntPair.getField("z").getInt(chunkCoordIntPair); - return new ChunkLocation(x << 4, z << 4); + return new ChunkPosition(x << 4, z << 4); } diff --git a/src/main/java/be4rjp/parallel/nms/PacketHandler.java b/src/main/java/be4rjp/parallel/nms/PacketHandler.java index bb9ce5e..bef267b 100644 --- a/src/main/java/be4rjp/parallel/nms/PacketHandler.java +++ b/src/main/java/be4rjp/parallel/nms/PacketHandler.java @@ -1,9 +1,6 @@ package be4rjp.parallel.nms; import be4rjp.parallel.Parallel; -import be4rjp.parallel.nms.manager.BlockChangePacketManager; -import be4rjp.parallel.nms.manager.ChunkPacketManager; -import be4rjp.parallel.nms.manager.FlyingPacketManager; -import be4rjp.parallel.nms.manager.MultiBlockChangePacketManager; +import be4rjp.parallel.nms.manager.*; import io.netty.channel.*; import org.bukkit.entity.Player; @@ -37,6 +34,12 @@ public void write(ChannelHandlerContext channelHandlerContext, Object packet, Ch manager.runTaskAsynchronously(Parallel.getPlugin()); return; } + + if(packet.getClass().getSimpleName().equalsIgnoreCase("PacketPlayOutLightUpdate")){ + LightUpdatePacketManager manager = new LightUpdatePacketManager(channelHandlerContext, packet, channelPromise, this, player); + manager.runTaskAsynchronously(Parallel.getPlugin()); + return; + } if(packet.getClass().getSimpleName().equalsIgnoreCase("PacketPlayOutBlockChange")){ BlockChangePacketManager manager = new BlockChangePacketManager(channelHandlerContext, packet, channelPromise, this, player); diff --git a/src/main/java/be4rjp/parallel/nms/manager/BlockChangePacketManager.java b/src/main/java/be4rjp/parallel/nms/manager/BlockChangePacketManager.java index 381d861..7ad3d3b 100644 --- a/src/main/java/be4rjp/parallel/nms/manager/BlockChangePacketManager.java +++ b/src/main/java/be4rjp/parallel/nms/manager/BlockChangePacketManager.java @@ -5,7 +5,8 @@ import be4rjp.parallel.nms.PacketHandler; import be4rjp.parallel.util.BlockLocation; import be4rjp.parallel.util.BlockPosition3i; -import be4rjp.parallel.util.ChunkLocation; +import be4rjp.parallel.util.ChunkPosition; +import be4rjp.parallel.util.PBlockData; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import org.bukkit.block.data.BlockData; @@ -55,16 +56,16 @@ public void run() { BlockPosition3i position3i = NMSUtil.getBlockPosition3i(blockPosition); ParallelWorld parallelWorld = ParallelWorld.getParallelWorld(player); - ChunkLocation chunkLocation = new ChunkLocation(position3i.getX(), position3i.getZ()); - Map dataMap = parallelWorld.getChunkBlockMap().get(chunkLocation); + ChunkPosition chunkPosition = new ChunkPosition(position3i.getX(), position3i.getZ()); + Map dataMap = parallelWorld.getChunkBlockMap().get(chunkPosition); if(dataMap == null){ packetHandler.doWrite(channelHandlerContext, packet, channelPromise); return; } - for (Map.Entry entry : dataMap.entrySet()) { + for (Map.Entry entry : dataMap.entrySet()) { BlockLocation location = entry.getKey(); - BlockData blockData = entry.getValue(); - + BlockData blockData = entry.getValue().getBlockData(); + if(blockData == null) continue; if(player.getWorld() != location.getWorld()) continue; if(position3i.getX() == location.getX() && position3i.getY() == location.getY() && position3i.getZ() == location.getZ()){ diff --git a/src/main/java/be4rjp/parallel/nms/manager/ChunkPacketManager.java b/src/main/java/be4rjp/parallel/nms/manager/ChunkPacketManager.java index 651341f..3102ecf 100644 --- a/src/main/java/be4rjp/parallel/nms/manager/ChunkPacketManager.java +++ b/src/main/java/be4rjp/parallel/nms/manager/ChunkPacketManager.java @@ -5,11 +5,11 @@ import be4rjp.parallel.nms.PacketHandler; import be4rjp.parallel.util.BlockLocation; import be4rjp.parallel.util.ChunkLocation; +import be4rjp.parallel.util.ChunkPosition; +import be4rjp.parallel.util.PBlockData; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; @@ -69,12 +69,19 @@ public void run() { int chunkX = (int) a.get(packet); int chunkZ = (int) b.get(packet); - ChunkLocation chunkLocation = new ChunkLocation(chunkX << 4, chunkZ << 4); - Map dataMap = parallelWorld.getChunkBlockMap().get(chunkLocation); + ChunkPosition chunkPosition = new ChunkPosition(chunkX << 4, chunkZ << 4); + Map dataMap = parallelWorld.getChunkBlockMap().get(chunkPosition); if(dataMap == null){ packetHandler.doWrite(channelHandlerContext, packet, channelPromise); return; } + + ChunkLocation chunkLocation = new ChunkLocation(player.getWorld(), chunkPosition.x << 4, chunkPosition.z << 4); + Object editedPacket = parallelWorld.getEditedPacketForChunkMap().get(chunkLocation); + if(editedPacket != null){ + packetHandler.doWrite(channelHandlerContext, editedPacket, channelPromise); + return; + } Object nmsWorld = NMSUtil.getNMSWorld(player.getWorld()); Object nmsChunk = NMSUtil.getNMSChunk(player.getWorld().getChunkAt(chunkX, chunkZ)); @@ -94,10 +101,10 @@ public void run() { for (int ix = 0; ix < 16; ix++) { for (int iy = 0; iy < 16; iy++) { for (int iz = 0; iz < 16; iz++) { - Object iBlockData = NMSUtil.getTypeChunkSection(Array.get(sections, y), (x + ix) & 15, (y + iy) & 15, (z + iz) & 15); + Object iBlockData = NMSUtil.getTypeChunkSection(Array.get(sections, y), (x + ix) & 0xF, (y + iy) & 0xF, (z + iz) & 0xF); BlockData blockData = NMSUtil.getBlockData(iBlockData); Object iBlockData2 = NMSUtil.getIBlockData(blockData.clone()); - NMSUtil.setTypeChunkSection(chunkSection, (x + ix) & 15, (y + iy) & 15, (z + iz) & 15, iBlockData2); + NMSUtil.setTypeChunkSection(chunkSection, (x + ix) & 0xF, (y + iy) & 0xF, (z + iz) & 0xF, iBlockData2); } } } @@ -108,11 +115,12 @@ public void run() { } int count = 0; - for (Map.Entry entry : dataMap.entrySet()) { + for (Map.Entry entry : dataMap.entrySet()) { BlockLocation location = entry.getKey(); - BlockData blockData = entry.getValue(); + BlockData blockData = entry.getValue().getBlockData(); Chunk chunk = location.getChunk(); + if(blockData == null) continue; if(player.getWorld() != location.getWorld()) continue; if (chunk.getX() == chunkX && chunk.getZ() == chunkZ) { @@ -125,7 +133,7 @@ public void run() { cs = NMSUtil.createChunkSection(location.getY() >> 4 << 4); Array.set(newSections, location.getY() >> 4, cs); } - NMSUtil.setTypeChunkSection(cs, location.getX() & 15, location.getY() & 15, location.getZ() & 15, iBlockData); + NMSUtil.setTypeChunkSection(cs, location.getX() & 0xF, location.getY() & 0xF, location.getZ() & 0xF, iBlockData); }catch (ArrayIndexOutOfBoundsException e){/**/} count++; } @@ -137,6 +145,7 @@ public void run() { } Object newPacket = NMSUtil.createPacketPlayOutMapChunk(newChunk, 65535); + parallelWorld.getEditedPacketForChunkMap().put(chunkLocation, newPacket); packetHandler.doWrite(channelHandlerContext, newPacket, channelPromise); }catch (ClosedChannelException e){ }catch (Exception e){ diff --git a/src/main/java/be4rjp/parallel/nms/manager/LightUpdatePacketManager.java b/src/main/java/be4rjp/parallel/nms/manager/LightUpdatePacketManager.java new file mode 100644 index 0000000..c78a241 --- /dev/null +++ b/src/main/java/be4rjp/parallel/nms/manager/LightUpdatePacketManager.java @@ -0,0 +1,217 @@ +package be4rjp.parallel.nms.manager; + +import be4rjp.parallel.ParallelWorld; +import be4rjp.parallel.nms.NMSUtil; +import be4rjp.parallel.nms.PacketHandler; +import be4rjp.parallel.util.*; +import com.google.common.collect.Lists; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class LightUpdatePacketManager extends BukkitRunnable { + + private static Class PacketPlayOutLightUpdate; + private static Class NibbleArray; + + private static Field a; + private static Field b; + private static Field c; + private static Field d; + private static Field e; + private static Field f; + private static Field g; + private static Field h; + private static Field i; + + private static Method methodA; + private static Method methodC; + private static Method asBytes; + + public static boolean VERSION_1_16_R1 = true; + + static { + try { + PacketPlayOutLightUpdate = NMSUtil.getNMSClass("PacketPlayOutLightUpdate"); + NibbleArray = NMSUtil.getNMSClass("NibbleArray"); + + a = PacketPlayOutLightUpdate.getDeclaredField("a"); + b = PacketPlayOutLightUpdate.getDeclaredField("b"); + c = PacketPlayOutLightUpdate.getDeclaredField("c"); + d = PacketPlayOutLightUpdate.getDeclaredField("d"); + e = PacketPlayOutLightUpdate.getDeclaredField("e"); + f = PacketPlayOutLightUpdate.getDeclaredField("f"); + g = PacketPlayOutLightUpdate.getDeclaredField("g"); + h = PacketPlayOutLightUpdate.getDeclaredField("h"); + + a.setAccessible(true); + b.setAccessible(true); + c.setAccessible(true); + d.setAccessible(true); + e.setAccessible(true); + f.setAccessible(true); + g.setAccessible(true); + h.setAccessible(true); + + methodA = NibbleArray.getMethod("a", int.class, int.class, int.class, int.class); + methodC = NibbleArray.getMethod("c"); + asBytes = NibbleArray.getMethod("asBytes"); + + try{ + i = PacketPlayOutLightUpdate.getDeclaredField("i"); + i.setAccessible(true); + }catch (NoSuchFieldException e){ + VERSION_1_16_R1 = false; + } + }catch (ClassNotFoundException e){ + //None + }catch (Exception e){e.printStackTrace();} + } + + + private final ChannelHandlerContext channelHandlerContext; + private final Object packet; + private final ChannelPromise channelPromise; + private final PacketHandler packetHandler; + private final Player player; + + public LightUpdatePacketManager(ChannelHandlerContext channelHandlerContext, Object packet, ChannelPromise channelPromise, PacketHandler packetHandler, Player player){ + this.channelHandlerContext = channelHandlerContext; + this.packet = packet; + this.channelPromise = channelPromise; + this.packetHandler = packetHandler; + this.player = player; + } + + + @Override + public void run() { + try { + ParallelWorld parallelWorld = ParallelWorld.getParallelWorld(player); + + int chunkX = a.getInt(packet); + int chunkZ = b.getInt(packet); + + World world = player.getWorld(); + Object nmsWorld = NMSUtil.getNMSWorld(world); + Object nmsChunk = NMSUtil.getNMSChunk(world.getChunkAt(chunkX, chunkZ)); + if(nmsChunk == null){ + packetHandler.doWrite(channelHandlerContext, packet, channelPromise); + return; + } + + ChunkPosition chunkPosition = new ChunkPosition(chunkX << 4, chunkZ << 4); + Map dataMap = parallelWorld.getChunkBlockMap().get(chunkPosition); + if(dataMap == null){ + packetHandler.doWrite(channelHandlerContext, packet, channelPromise); + return; + } + + ChunkLocation chunkLocation = new ChunkLocation(player.getWorld(), chunkPosition.x << 4, chunkPosition.z << 4); + Object editedPacket = parallelWorld.getEditedPacketForLightMap().get(chunkLocation); + if(editedPacket != null){ + packetHandler.doWrite(channelHandlerContext, editedPacket, channelPromise); + return; + } + + + int varE = 0; + int varC = 0; + List varG = Lists.newArrayList(); + int varF = 0; + int varD = 0; + List varH = Lists.newArrayList(); + + for (int var3 = 0; var3 < 18; ++var3) { + Object var4 = NibbleArray.getConstructor(byte[].class).newInstance((Object) new byte[2048]); + Object var5 = NibbleArray.getConstructor(byte[].class).newInstance((Object) new byte[2048]); + + Set lightLevelInfoSet = new HashSet<>(); + for (Map.Entry entry : dataMap.entrySet()) { + BlockLocation location = entry.getKey(); + int level = entry.getValue().getBlockLightLevel(); + + if(level == -1) continue; + if(world != location.getWorld()) continue; + + if(location.getY() >> 4 != -1 + var3) continue; + + int x = location.getX() - (chunkX << 4); + int z = location.getZ() - (chunkZ << 4); + int y = location.getY() - ((location.getY() >> 4) << 4); + lightLevelInfoSet.add(new LightLevelInfo(x, y, z, level)); + } + + boolean writeSky = false; + boolean writeBlock = false; + for(int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + Block block = world.getBlockAt(x + (chunkX << 4), y + ((var3 - 1) << 4), z + (chunkZ << 4)); + int BLevel = block.getLightFromBlocks(); + int SLevel = block.getLightFromSky(); + if (BLevel != 0) writeBlock = true; + if (SLevel != 0) writeSky = true; + + for (LightLevelInfo lightLevelInfo : lightLevelInfoSet) { + if (lightLevelInfo.x == x && lightLevelInfo.y == y && lightLevelInfo.z == z) { + BLevel = lightLevelInfo.level; + writeBlock = true; + break; + } + } + methodA.invoke(var4, x, y, z, SLevel); + methodA.invoke(var5, x, y, z, BLevel); + } + } + } + + if (writeSky) { + if ((boolean) methodC.invoke(var4)) { + varE |= 1 << var3; + } + else { + varC |= 1 << var3; + varG.add(((byte[]) asBytes.invoke(var4)).clone()); + } + } + if (writeBlock) { + if ((boolean) methodC.invoke(var5)) { + varF |= 1 << var3; + } + else { + varD |= 1 << var3; + varH.add(((byte[]) asBytes.invoke(var5)).clone()); + } + } + } + + Object newPacket = PacketPlayOutLightUpdate.newInstance(); + a.set(newPacket, chunkX); + b.set(newPacket, chunkZ); + g.set(newPacket, varG); + h.set(newPacket, varH); + e.set(newPacket, varE); + c.set(newPacket, varC); + f.set(newPacket, varF); + d.set(newPacket, varD); + + if(VERSION_1_16_R1){ + i.set(newPacket, i.getBoolean(packet)); + } + + parallelWorld.getEditedPacketForLightMap().put(chunkLocation, newPacket); + packetHandler.doWrite(channelHandlerContext, newPacket, channelPromise); + }catch (Exception e){e.printStackTrace();} + } +} diff --git a/src/main/java/be4rjp/parallel/nms/manager/MultiBlockChangePacketManager.java b/src/main/java/be4rjp/parallel/nms/manager/MultiBlockChangePacketManager.java index 58e8e42..d5c75b1 100644 --- a/src/main/java/be4rjp/parallel/nms/manager/MultiBlockChangePacketManager.java +++ b/src/main/java/be4rjp/parallel/nms/manager/MultiBlockChangePacketManager.java @@ -5,7 +5,8 @@ import be4rjp.parallel.nms.PacketHandler; import be4rjp.parallel.util.BlockLocation; import be4rjp.parallel.util.BlockPosition3i; -import be4rjp.parallel.util.ChunkLocation; +import be4rjp.parallel.util.ChunkPosition; +import be4rjp.parallel.util.PBlockData; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import org.bukkit.block.data.BlockData; @@ -77,18 +78,19 @@ public void run() { Object blockDataArray = c.get(packet); BlockPosition3i blockPosition3i = NMSUtil.getBlockPosition3i(a.get(packet)); - ChunkLocation chunkLocation = new ChunkLocation(blockPosition3i.getX() << 4, blockPosition3i.getZ() << 4); - Map dataMap = parallelWorld.getChunkBlockMap().get(chunkLocation); + ChunkPosition chunkPosition = new ChunkPosition(blockPosition3i.getX() << 4, blockPosition3i.getZ() << 4); + Map dataMap = parallelWorld.getChunkBlockMap().get(chunkPosition); if(dataMap == null){ packetHandler.doWrite(channelHandlerContext, packet, channelPromise); return; } for (int index = 0; index < locArray.length; index++) { - for (Map.Entry entry : dataMap.entrySet()) { + for (Map.Entry entry : dataMap.entrySet()) { BlockLocation location = entry.getKey(); - BlockData blockData = entry.getValue(); + BlockData blockData = entry.getValue().getBlockData(); + if(blockData == null) continue; if(player.getWorld() != location.getWorld()) continue; if((location.getY() >> 4) != blockPosition3i.getY()) continue; @@ -108,22 +110,23 @@ public void run() { } else { Object multiBlockChangeInfoArray = b.get(packet); - ChunkLocation chunkLocation = NMSUtil.getChunkLocation(a.get(packet)); - Map dataMap = parallelWorld.getChunkBlockMap().get(chunkLocation); + ChunkPosition chunkPosition = NMSUtil.getChunkLocation(a.get(packet)); + Map dataMap = parallelWorld.getChunkBlockMap().get(chunkPosition); if(dataMap == null){ packetHandler.doWrite(channelHandlerContext, packet, channelPromise); return; } for (int index = 0; index < Array.getLength(multiBlockChangeInfoArray); index++) { - for (Map.Entry entry : dataMap.entrySet()) { + for (Map.Entry entry : dataMap.entrySet()) { BlockLocation location = entry.getKey(); - BlockData blockData = entry.getValue(); + BlockData blockData = entry.getValue().getBlockData(); + if(blockData == null) continue; if(player.getWorld() != location.getWorld()) continue; Object originalInfo = Array.get(multiBlockChangeInfoArray, index); - short loc = (short) ((location.getX() & 15) << 12 | (location.getZ() & 15) << 8 | location.getY()); + short loc = (short) ((location.getX() & 0xF) << 12 | (location.getZ() & 0xF) << 8 | location.getY()); short b = (short) MultiBlockChangeInfo.getMethod("b").invoke(originalInfo); if (loc == b) { diff --git a/src/main/java/be4rjp/parallel/structure/ParallelStructure.java b/src/main/java/be4rjp/parallel/structure/ParallelStructure.java index 102cd7b..68bfe7d 100644 --- a/src/main/java/be4rjp/parallel/structure/ParallelStructure.java +++ b/src/main/java/be4rjp/parallel/structure/ParallelStructure.java @@ -4,6 +4,7 @@ import be4rjp.parallel.ParallelWorld; import be4rjp.parallel.enums.UpdatePacketType; import be4rjp.parallel.nms.NMSUtil; +import be4rjp.parallel.util.BlockPosition3i; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -100,15 +101,26 @@ public void setStructureData(String uuid, StructureData structureData){ Map blockDataMap = new HashMap<>(); Set blocks = new HashSet<>(); - for(Map.Entry entry : structureData.getBlockDataMap().entrySet()){ - Block block = getBaseLocation().add(entry.getKey()).getBlock(); + for(Map.Entry entry : structureData.getBlockDataMap().entrySet()){ + BlockPosition3i relative = entry.getKey(); + Block block = getBaseLocation().add(relative.getX(), relative.getY(), relative.getZ()).getBlock(); blockDataMap.put(block, entry.getValue()); blocks.add(block); } + + Map blockLightLevelMap = new HashMap<>(); + for(Map.Entry entry : structureData.getBlockLightLevelMap().entrySet()){ + BlockPosition3i relative = entry.getKey(); + Block block = getBaseLocation().add(relative.getX(), relative.getY(), relative.getZ()).getBlock(); + blockLightLevelMap.put(block, entry.getValue()); + blocks.add(block); + } + dataMap.put(uuid, blocks); ParallelWorld parallelWorld = ParallelWorld.getParallelWorld(uuid); parallelWorld.setBlocks(blockDataMap, UpdatePacketType.MULTI_BLOCK_CHANGE); + parallelWorld.setLightLevels(blockLightLevelMap); } diff --git a/src/main/java/be4rjp/parallel/structure/StructureData.java b/src/main/java/be4rjp/parallel/structure/StructureData.java index fdf6204..a86db76 100644 --- a/src/main/java/be4rjp/parallel/structure/StructureData.java +++ b/src/main/java/be4rjp/parallel/structure/StructureData.java @@ -2,12 +2,12 @@ import be4rjp.parallel.Parallel; import be4rjp.parallel.nms.NMSUtil; +import be4rjp.parallel.util.BlockPosition3i; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.util.Vector; import java.io.File; import java.io.IOException; @@ -66,15 +66,17 @@ public static void loadAllStructureData() { private final String name; - private final Map blockDataMap = new HashMap<>(); + private final Map blockDataMap = new HashMap<>(); + private final Map blockLightLevelMap = new HashMap<>(); public StructureData(String name){ this.name = name; structureDataMap.put(name, this); } - public Map getBlockDataMap() {return blockDataMap;} + public Map getBlockDataMap() {return blockDataMap;} + public Map getBlockLightLevelMap() {return blockLightLevelMap;} /** * ブロックの状態を記録 @@ -83,10 +85,12 @@ public StructureData(String name){ */ public void setBlockData(Location baseLocation, List blocks){ for(Block block : blocks) { - Vector relative = new Vector(block.getX() - baseLocation.getBlockX(), block.getY() - baseLocation.getBlockY(), block.getZ() - baseLocation.getBlockZ()); + BlockPosition3i relative = new BlockPosition3i(block.getX() - baseLocation.getBlockX(), block.getY() - baseLocation.getBlockY(), block.getZ() - baseLocation.getBlockZ()); BlockData blockData = block.getBlockData(); + int blockLightLevel = block.getLightFromBlocks(); this.blockDataMap.put(relative, blockData); + this.blockLightLevelMap.put(relative, blockLightLevel); } } @@ -109,8 +113,8 @@ public void loadData(){ int x = Integer.parseInt(args[0]); int y = Integer.parseInt(args[1]); int z = Integer.parseInt(args[2]); - - Vector relative = new Vector(x, y, z); + + BlockPosition3i relative = new BlockPosition3i(x, y, z); int id = Integer.parseInt(args[3]); try { Object iBlockData = NMSUtil.getByCombinedId(id); @@ -121,6 +125,23 @@ public void loadData(){ e.printStackTrace(); } } + + if(yml.contains("block-lights")) { + lines = yml.getStringList("block-lights"); + //x, y, z, lightLevel + for (String line : lines) { + line = line.replace(" ", ""); + String[] args = line.split(","); + + int x = Integer.parseInt(args[0]); + int y = Integer.parseInt(args[1]); + int z = Integer.parseInt(args[2]); + + BlockPosition3i relative = new BlockPosition3i(x, y, z); + int lightLevel = Integer.parseInt(args[3]); + this.blockLightLevelMap.put(relative, lightLevel); + } + } } @@ -132,14 +153,14 @@ public void saveData(){ FileConfiguration yml = new YamlConfiguration(); List lines = new ArrayList<>(); - for(Map.Entry entry : this.blockDataMap.entrySet()){ - Vector relative = entry.getKey(); + for(Map.Entry entry : this.blockDataMap.entrySet()){ + BlockPosition3i relative = entry.getKey(); try { Object iBlockData = NMSUtil.getIBlockData(entry.getValue()); int id = NMSUtil.getCombinedId(iBlockData); - String line = relative.getBlockX() + ", " + relative.getBlockY() + ", " + relative.getBlockZ() + ", " + id; + String line = relative.getX() + ", " + relative.getY() + ", " + relative.getZ() + ", " + id; lines.add(line); } catch (Exception e) { e.printStackTrace(); @@ -147,6 +168,17 @@ public void saveData(){ } yml.set("blocks", lines); + List lines2 = new ArrayList<>(); + for(Map.Entry entry : this.blockLightLevelMap.entrySet()){ + BlockPosition3i relative = entry.getKey(); + int lightLevel = entry.getValue(); + + String line = relative.getX() + ", " + relative.getY() + ", " + relative.getZ() + ", " + lightLevel; + lines2.add(line); + } + yml.set("block-lights", lines2); + + try { yml.save(file); } catch (IOException e) { diff --git a/src/main/java/be4rjp/parallel/util/ChunkLocation.java b/src/main/java/be4rjp/parallel/util/ChunkLocation.java index dd1deb5..54fd436 100644 --- a/src/main/java/be4rjp/parallel/util/ChunkLocation.java +++ b/src/main/java/be4rjp/parallel/util/ChunkLocation.java @@ -1,27 +1,29 @@ package be4rjp.parallel.util; -import java.util.Objects; - -public class ChunkLocation { +import org.bukkit.World; - public final int x; - public final int z; +import java.util.Objects; - public ChunkLocation(int blockX, int blockZ){ - this.x = blockX >> 4; - this.z = blockZ >> 4; +public class ChunkLocation extends ChunkPosition{ + + public final World world; + + public ChunkLocation(World world, int blockX, int blockZ) { + super(blockX, blockZ); + this.world = world; } - + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; ChunkLocation that = (ChunkLocation) o; - return x == that.x && z == that.z; + return Objects.equals(world, that.world); } - + @Override public int hashCode() { - return Objects.hash(x, z); + return Objects.hash(super.hashCode(), world); } } diff --git a/src/main/java/be4rjp/parallel/util/ChunkPosition.java b/src/main/java/be4rjp/parallel/util/ChunkPosition.java new file mode 100644 index 0000000..a607e7e --- /dev/null +++ b/src/main/java/be4rjp/parallel/util/ChunkPosition.java @@ -0,0 +1,27 @@ +package be4rjp.parallel.util; + +import java.util.Objects; + +public class ChunkPosition { + + public final int x; + public final int z; + + public ChunkPosition(int blockX, int blockZ){ + this.x = blockX >> 4; + this.z = blockZ >> 4; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ChunkPosition that = (ChunkPosition) o; + return x == that.x && z == that.z; + } + + @Override + public int hashCode() { + return Objects.hash(x, z); + } +} diff --git a/src/main/java/be4rjp/parallel/util/LightLevelInfo.java b/src/main/java/be4rjp/parallel/util/LightLevelInfo.java new file mode 100644 index 0000000..f367aa0 --- /dev/null +++ b/src/main/java/be4rjp/parallel/util/LightLevelInfo.java @@ -0,0 +1,15 @@ +package be4rjp.parallel.util; + +public class LightLevelInfo { + public final int x; + public final int y; + public final int z; + public final int level; + + public LightLevelInfo(int x, int y, int z, int level){ + this.x = x; + this.y = y; + this.z = z; + this.level = level; + } +} diff --git a/src/main/java/be4rjp/parallel/util/PBlockData.java b/src/main/java/be4rjp/parallel/util/PBlockData.java new file mode 100644 index 0000000..9ca4ce8 --- /dev/null +++ b/src/main/java/be4rjp/parallel/util/PBlockData.java @@ -0,0 +1,33 @@ +package be4rjp.parallel.util; + +import org.bukkit.block.data.BlockData; + +public class PBlockData { + + private BlockData blockData = null; + + private int blockLightLevel = -1; + + public PBlockData(BlockData blockData, int blockLightLevel){ + this.blockData = blockData; + this.blockLightLevel = blockLightLevel; + } + + public PBlockData(BlockData blockData){ + this.blockData = blockData; + } + + public PBlockData(int blockLightLevel){ + this.blockLightLevel = blockLightLevel; + } + + public PBlockData(){} + + public BlockData getBlockData() {return blockData;} + + public void setBlockData(BlockData blockData) {this.blockData = blockData;} + + public int getBlockLightLevel() {return blockLightLevel;} + + public void setBlockLightLevel(int lightLevel) {this.blockLightLevel = lightLevel;} +}