From 7abf31ea821a0bbddb836adb1a63d0fec2ceee4f Mon Sep 17 00:00:00 2001 From: Leonard Kugis Date: Mon, 25 Apr 2022 18:41:24 +0200 Subject: Initial commit --- .../InstancedProtectedCuboidRegion.java | 296 +++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100755 src/main/java/com/encrox/instancedregions/InstancedProtectedCuboidRegion.java (limited to 'src/main/java/com/encrox/instancedregions/InstancedProtectedCuboidRegion.java') diff --git a/src/main/java/com/encrox/instancedregions/InstancedProtectedCuboidRegion.java b/src/main/java/com/encrox/instancedregions/InstancedProtectedCuboidRegion.java new file mode 100755 index 0000000..3271c4d --- /dev/null +++ b/src/main/java/com/encrox/instancedregions/InstancedProtectedCuboidRegion.java @@ -0,0 +1,296 @@ +package com.encrox.instancedregions; + +import java.util.ArrayList; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.WorldType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.plugin.Plugin; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.wrappers.BlockPosition; +import com.encrox.instancedregions.chunkmap.ChunkData; +import com.encrox.instancedregions.chunkmap.ChunkMapManager; +import com.encrox.instancedregions.types.BlockState; +import com.sk89q.worldedit.BlockVector; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; + +public class InstancedProtectedCuboidRegion extends ProtectedCuboidRegion implements Listener { + + private ArrayList players; + private ArrayList blockBreaks, blockPlaces; + private ArrayList changeWhitelist; + private ProtocolManager pmgr; + private PacketAdapter mapAdapter, spawnEntityAdapter, spawnExperienceOrbAdapter, spawnMobAdapter, spawnPlayerAdapter, blockBreakAdapter, blockChangeAdapter, multiBlockChangeAdapter; + private World world; + + public InstancedProtectedCuboidRegion(Plugin plugin, final World world, String id, BlockVector pt1, BlockVector pt2) { + super(id, pt1, pt2); + Bukkit.getPluginManager().registerEvents(this, plugin); + players = new ArrayList(); + blockBreaks = new ArrayList(); + blockPlaces = new ArrayList(); + changeWhitelist = new ArrayList(); + this.world = world; + pmgr = ProtocolLibrary.getProtocolManager(); + //catch chunk data + mapAdapter = new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MAP_CHUNK){ + @Override + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + if(world.equals(player.getWorld()) && players.contains(event.getPlayer())) { + PacketContainer packet = event.getPacket(); + StructureModifier ints = packet.getIntegers(); + StructureModifier byteArray = packet.getByteArrays(); + StructureModifier bools = packet.getBooleans(); + ChunkData chunkData = new ChunkData(); + chunkData.chunkX = ints.read(0); + chunkData.chunkZ = ints.read(1); + chunkData.groundUpContinuous = bools.read(0); + chunkData.primaryBitMask = ints.read(2); + chunkData.data = byteArray.read(0); + chunkData.isOverworld = event.getPlayer().getWorld().getWorldType() == WorldType.NORMAL; + ChunkMapManager cmm = new ChunkMapManager(chunkData); + ArrayList col = new ArrayList(); + col.add(new ProtectedCuboidRegion("current", new BlockVector(chunkData.chunkX<<4, 0, chunkData.chunkZ<<4), new BlockVector((chunkData.chunkX<<4)|15, 256, (chunkData.chunkZ<<4)|15))); + try { + if(getIntersectingRegions(col).isEmpty()) { + PacketContainer unloadPacket = new PacketContainer(PacketType.Play.Server.UNLOAD_CHUNK); + unloadPacket.getIntegers().write(0, chunkData.chunkX).write(1, chunkData.chunkZ); + pmgr.sendServerPacket(player, unloadPacket); + cmm.init(); + for(int y = 0; y<16; y++) { + for(int z = 0; z<16; z++) { + for(int x = 0; x<16; x++) { + try { + cmm.readNextBlock(); + } catch(Exception e1) { + + } + //int blockData = cmm.readNextBlock(); + BlockState blockState = new BlockState(); + //ChunkMapManager.blockDataToState(blockData, blockState); + blockState.id = 0; + blockState.meta = 0; + //blockData = ChunkMapManager.blockStateToData(blockState); + cmm.writeOutputBlock(ChunkMapManager.blockStateToData(blockState)); + } + } + } + cmm.finalizeOutput(); + byteArray.write(0, cmm.createOutput()); + } + } catch(Exception e) { + + } + } + } + }; + //catch entity objects (chests, signs ...) + spawnEntityAdapter = new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.SPAWN_ENTITY){ + @Override + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + if(world.equals(player.getWorld()) && players.contains(event.getPlayer())) { + PacketContainer packet = event.getPacket(); + StructureModifier doubles = packet.getDoubles(); + double x = doubles.read(0); + double y = doubles.read(1); + double z = doubles.read(2); + if(!contains(new Vector(x, y, z))) { + event.setCancelled(true); + } + } + } + }; + //catch experience orbs + spawnExperienceOrbAdapter = new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.SPAWN_ENTITY_EXPERIENCE_ORB){ + @Override + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + if(world.equals(player.getWorld()) && players.contains(event.getPlayer())) { + PacketContainer packet = event.getPacket(); + StructureModifier doubles = packet.getDoubles(); + double x = doubles.read(0); + double y = doubles.read(1); + double z = doubles.read(2); + if(!contains(new Vector(x, y, z))) { + event.setCancelled(true); + } + } + } + }; + //catch mobs + spawnMobAdapter = new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.SPAWN_ENTITY_LIVING){ + @Override + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + if(world.equals(player.getWorld()) && players.contains(event.getPlayer())) { + PacketContainer packet = event.getPacket(); + StructureModifier doubles = packet.getDoubles(); + double x = doubles.read(0); + double y = doubles.read(1); + double z = doubles.read(2); + if(!contains(new Vector(x, y, z))) { + event.setCancelled(true); + } + } + } + }; + //catch players + spawnPlayerAdapter = new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.NAMED_ENTITY_SPAWN){ + @Override + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + if(world.equals(player.getWorld()) && players.contains(event.getPlayer())) { + PacketContainer packet = event.getPacket(); + StructureModifier uuids = packet.getUUIDs(); + UUID uuid = uuids.read(0); + for(int i = 0, size = players.size(); i> 38; + long y = (position >> 26) & 0xFFF; + long z = position << 38 >> 38; + InstancedRegions.logger.info("block break: " + x + ", " + y + ", " + z); + } + } + }; + //catch block changes + blockChangeAdapter = new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.BLOCK_CHANGE){ + @Override + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + if(world.equals(player.getWorld()) && players.contains(event.getPlayer())) { + //InstancedRegions.logger.info("BLOCK_CHANGE");//erst pasten, dann region newen + PacketContainer packet = event.getPacket(); + StructureModifier bps = packet.getBlockPositionModifier(); + BlockPosition bp = bps.read(0); + //InstancedRegions.logger.info("BLOCK_CHANGE at: " + bp.getX() + ", " + bp.getY() + ", " + bp.getZ()); + BlockVector bv = new BlockVector(bp.getX(), bp.getY(), bp.getZ()); + if(!contains(bv)) { + if(changeWhitelist.contains(bv)) { + changeWhitelist.remove(bv); + } else { + event.setCancelled(true); + } + } + } + } + }; + //catch multi block changes + multiBlockChangeAdapter = new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MULTI_BLOCK_CHANGE){ + @Override + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + if(world.equals(player.getWorld()) && players.contains(event.getPlayer())) { + try { + //InstancedRegions.logger.info("MULTI_BLOCK_CHANGE"); + PacketContainer packet = event.getPacket(); + StructureModifier ints = packet.getIntegerArrays(); + int[] coords = ints.read(0); + int chunkX = coords[0]; + int chunkZ = coords[1]; + ArrayList col = new ArrayList(); + col.add(new ProtectedCuboidRegion("current", new BlockVector(chunkX<<4, 0, chunkZ<<4), new BlockVector((chunkX<<4)|15, 256, (chunkZ<<4)|15))); + if(getIntersectingRegions(col).isEmpty()) { + event.setCancelled(true); + } + } catch(Exception e) { + + } + } + } + }; + } + + public void addPlayer(Player player) { + players.add(player); + } + + public void removePlayer(Player player) { + players.remove(player); + } + + public void apply() { + pmgr.addPacketListener(mapAdapter); + pmgr.addPacketListener(spawnEntityAdapter); + pmgr.addPacketListener(spawnExperienceOrbAdapter); + pmgr.addPacketListener(spawnMobAdapter); + pmgr.addPacketListener(spawnPlayerAdapter); + pmgr.addPacketListener(blockBreakAdapter); + pmgr.addPacketListener(blockChangeAdapter); + pmgr.addPacketListener(multiBlockChangeAdapter); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + DereferencedBlock block = new DereferencedBlock(event.getBlock()); + if(players.contains(event.getPlayer()) && contains(block.location.getBlockX(), block.location.getBlockY(), block.location.getBlockZ())) { + blockBreaks.add(block); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) { + DereferencedBlock block = new DereferencedBlock(event.getBlock()); + if(players.contains(event.getPlayer()) && contains(block.location.getBlockX(), block.location.getBlockY(), block.location.getBlockZ())) { + blockPlaces.add(block); + } + } + + public void addToChangeWhitelist(BlockVector bv) { + changeWhitelist.add(bv); + } + + public void dispose() { + DereferencedBlock current; + for(int i = 0, size = blockBreaks.size(); i