diff --git a/phider.iml b/phider.iml new file mode 100644 index 0000000..5cd848e --- /dev/null +++ b/phider.iml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0e08f65 --- /dev/null +++ b/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + com.boydti + phider + 1 + jar + + PlotHider + + + + + src/main/resources + + true + + plugin.yml + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + + + + UTF-8 + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + p2-repo + https://incendo.org/mvn/ + + + dmulloy2-repo + http://repo.dmulloy2.net/nexus/repository/public/ + + + sk89q-repo + http://maven.sk89q.com/artifactory/repo/ + + + + + + org.spigotmc + spigot-api + 1.13.2-R0.1-SNAPSHOT + + + org.bukkit + craftbukkit + 1.13.2-R0.1-SNAPSHOT + + + com.github.intellectualsites.plotsquared + PlotSquared + 4 + + + com.github.intellectualsites.plotsquared + PlotSquared + Bukkit + 4 + + + com.comphenix.protocol + ProtocolLib + 4.4.0 + + + diff --git a/src/com/boydti/phider/FlexibleStorage.java b/src/com/boydti/phider/FlexibleStorage.java deleted file mode 100644 index 3cf9a8b..0000000 --- a/src/com/boydti/phider/FlexibleStorage.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.boydti.phider; - -import java.util.Arrays; - -public class FlexibleStorage { - private final long[] data; - private final int bitsPerEntry; - private final int size; - private final long maxEntryValue; - - public FlexibleStorage(int bitsPerEntry, int size) { - this(bitsPerEntry, new long[roundToNearest(size * bitsPerEntry, 64) / 64]); - } - - public FlexibleStorage(int bitsPerEntry, long[] data) { - if (bitsPerEntry < 1 || bitsPerEntry > 32) { - throw new IllegalArgumentException("BitsPerEntry cannot be outside of accepted range."); - } - - this.bitsPerEntry = bitsPerEntry; - this.data = data; - - this.size = this.data.length * 64 / this.bitsPerEntry; - this.maxEntryValue = (1L << this.bitsPerEntry) - 1; - } - - public long[] getData() { - return this.data; - } - - public int getBitsPerEntry() { - return this.bitsPerEntry; - } - - public int getSize() { - return this.size; - } - - public int get(int index) { - if (index < 0 || index > this.size - 1) { - throw new IndexOutOfBoundsException(); - } - - int bitIndex = index * this.bitsPerEntry; - int startIndex = bitIndex / 64; - int endIndex = ((index + 1) * this.bitsPerEntry - 1) / 64; - int startBitSubIndex = bitIndex % 64; - if (startIndex == endIndex) { - return (int) (this.data[startIndex] >>> startBitSubIndex & this.maxEntryValue); - } else { - int endBitSubIndex = 64 - startBitSubIndex; - return (int) ((this.data[startIndex] >>> startBitSubIndex | this.data[endIndex] << endBitSubIndex) & this.maxEntryValue); - } - } - - public void set(int index, int value) { - if (index < 0 || index > this.size - 1) { - throw new IndexOutOfBoundsException(); - } - - if (value < 0 || value > this.maxEntryValue) { - throw new IllegalArgumentException("Value cannot be outside of accepted range."); - } - - int bitIndex = index * this.bitsPerEntry; - int startIndex = bitIndex / 64; - int endIndex = ((index + 1) * this.bitsPerEntry - 1) / 64; - int startBitSubIndex = bitIndex % 64; - this.data[startIndex] = this.data[startIndex] & ~(this.maxEntryValue << startBitSubIndex) | (value & this.maxEntryValue) << startBitSubIndex; - if (startIndex != endIndex) { - int endBitSubIndex = 64 - startBitSubIndex; - this.data[endIndex] = this.data[endIndex] >>> endBitSubIndex << endBitSubIndex | (value & this.maxEntryValue) >> endBitSubIndex; - } - } - - private static int roundToNearest(int value, int roundTo) { - if (roundTo == 0) { - return 0; - } else if (value == 0) { - return roundTo; - } else { - if (value < 0) { - roundTo *= -1; - } - - int remainder = value % roundTo; - return remainder != 0 ? value + roundTo - remainder : value; - } - } - - @Override - public boolean equals(Object o) { - return this == o - || (o instanceof FlexibleStorage && Arrays.equals(this.data, ((FlexibleStorage) o).data) && this.bitsPerEntry == ((FlexibleStorage) o).bitsPerEntry && this.size == ((FlexibleStorage) o).size && this.maxEntryValue == ((FlexibleStorage) o).maxEntryValue); - } - - @Override - public int hashCode() { - int result = Arrays.hashCode(this.data); - result = 31 * result + this.bitsPerEntry; - result = 31 * result + this.size; - result = 31 * result + (int) this.maxEntryValue; - return result; - } -} diff --git a/src/com/boydti/phider/PacketHandler.java b/src/com/boydti/phider/PacketHandler.java deleted file mode 100644 index 6990135..0000000 --- a/src/com/boydti/phider/PacketHandler.java +++ /dev/null @@ -1,220 +0,0 @@ -package com.boydti.phider; - -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.bukkit.entity.Player; - -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.comphenix.protocol.wrappers.ChunkCoordIntPair; -import com.comphenix.protocol.wrappers.MultiBlockChangeInfo; -import com.intellectualcrafters.plot.PS; -import com.intellectualcrafters.plot.object.Location; -import com.intellectualcrafters.plot.object.Plot; -import com.intellectualcrafters.plot.object.PlotArea; -import com.intellectualcrafters.plot.object.PlotBlock; -import com.intellectualcrafters.plot.object.PlotPlayer; -import com.intellectualcrafters.plot.util.Permissions; -import com.plotsquared.bukkit.util.BukkitUtil; - -public class PacketHandler { - public static ProtocolManager manager; - - public PacketHandler(Main main) { - manager = ProtocolLibrary.getProtocolManager(); - manager.addPacketListener(new PacketAdapter(main, ListenerPriority.NORMAL, PacketType.Play.Server.BLOCK_CHANGE) { - @Override - public void onPacketSending(PacketEvent event) { - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - if (Permissions.hasPermission(pp, "plots.plothider.bypass")) { // Admin bypass - return; - } - String world = pp.getLocation().getWorld(); - if (!PS.get().hasPlotArea(world)) { // Not a plot area - return; - } - PacketContainer packet = event.getPacket(); - StructureModifier positions = packet.getBlockPositionModifier(); - BlockPosition position = positions.read(0); - Location loc = new Location(world, position.getX(), 0, position.getZ()); - Plot plot = loc.getOwnedPlot(); - if (plot != null && (plot.isDenied(pp.getUUID()) || (!plot.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot)))) { - event.setCancelled(true); - } - } - }); - - manager.addPacketListener(new PacketAdapter(main, ListenerPriority.NORMAL, PacketType.Play.Server.MULTI_BLOCK_CHANGE) { - @Override - public void onPacketSending(PacketEvent event) { - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - if (Permissions.hasPermission(pp, "plots.plothider.bypass")) { // Admin bypass - return; - } - String world = pp.getLocation().getWorld(); - if (!PS.get().hasPlotArea(world)) { // Not a plot area - return; - } - PacketContainer packet = event.getPacket(); - StructureModifier chunkArray = packet.getChunkCoordIntPairs(); - ChunkCoordIntPair chunk = chunkArray.read(0); - int cx = chunk.getChunkX(); - int cz = chunk.getChunkZ(); - int bx = cx << 4; - int bz = cz << 4; - Location corner1 = new Location(world, bx, 0, bz); - Location corner2 = new Location(world, bx + 15, 0, bz); - Location corner3 = new Location(world, bx, 0, bz + 15); - Location corner4 = new Location(world, bx + 15, 0, bz + 15); - Plot plot1 = corner1.getOwnedPlot(); - Plot plot2 = corner2.getOwnedPlot(); - Plot plot3 = corner3.getOwnedPlot(); - Plot plot4 = corner4.getOwnedPlot(); - plot1 = (plot1 != null && (plot1.isDenied(pp.getUUID()) || (!plot1.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot1)))) ? plot1 : null; - plot2 = (plot2 != null && (plot2.isDenied(pp.getUUID()) || (!plot2.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot2)))) ? plot2 : null; - plot3 = (plot3 != null && (plot3.isDenied(pp.getUUID()) || (!plot3.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot3)))) ? plot3 : null; - plot4 = (plot4 != null && (plot4.isDenied(pp.getUUID()) || (!plot4.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot4)))) ? plot4 : null; - if (plot1 == null && plot2 == null && plot3 == null && plot4 == null) { // No plots to hide - return; - } - StructureModifier changeArray = packet.getMultiBlockChangeInfoArrays(); - if (plot1 == plot4 && plot1 != null) { // Not allowed to see the entire chunk - event.setCancelled(true); - return; - } - // Hide some of the blocks (but maybe not all) - List changes = new ArrayList<>(Arrays.asList(changeArray.read(0))); - Iterator iter = changes.iterator(); - Plot denied = plot1 != null ? plot1 : plot2 != null ? plot2 : plot3 != null ? plot3 : plot4; - PlotArea area = denied.getArea(); - while (iter.hasNext()) { - MultiBlockChangeInfo change = iter.next(); - int x = change.getAbsoluteX(); - int z = change.getAbsoluteZ(); - Plot current = area.getOwnedPlot(new Location(world, x, 0, z)); - if (current == null) { - continue; - } - if (current == plot1 || current == plot2 || current == plot3 || current == plot4) { - iter.remove(); - } - } - if (changes.size() == 0) { - event.setCancelled(true); - return; - } - changeArray.write(0, changes.toArray(new MultiBlockChangeInfo[changes.size()])); - event.setPacket(packet); - } - }); - - manager.addPacketListener(new PacketAdapter(main, ListenerPriority.NORMAL, PacketType.Play.Server.MAP_CHUNK) { - @Override - public void onPacketSending(PacketEvent event) { - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - if (Permissions.hasPermission(pp, "plots.plothider.bypass")) { // Admin bypass - return; - } - String world = pp.getLocation().getWorld(); - if (!PS.get().hasPlotArea(world)) { // Not a plot area - return; - } - PacketContainer packet = event.getPacket(); - StructureModifier ints = packet.getIntegers(); - StructureModifier byteArray = packet.getByteArrays(); - int cx = ints.read(0); - int cz = ints.read(1); - int bx = cx << 4; - int bz = cz << 4; - Location corner1 = new Location(world, bx, 0, bz); - Location corner2 = new Location(world, bx + 15, 0, bz); - Location corner3 = new Location(world, bx, 0, bz + 15); - Location corner4 = new Location(world, bx + 15, 0, bz + 15); - Plot plot1 = corner1.getOwnedPlot(); - Plot plot2 = corner2.getOwnedPlot(); - Plot plot3 = corner3.getOwnedPlot(); - Plot plot4 = corner4.getOwnedPlot(); - plot1 = (plot1 != null && (plot1.isDenied(pp.getUUID()) || (!plot1.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot1)))) ? plot1 : null; - plot2 = (plot2 != null && (plot2.isDenied(pp.getUUID()) || (!plot2.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot2)))) ? plot2 : null; - plot3 = (plot3 != null && (plot3.isDenied(pp.getUUID()) || (!plot3.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot3)))) ? plot3 : null; - plot4 = (plot4 != null && (plot4.isDenied(pp.getUUID()) || (!plot4.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot4)))) ? plot4 : null; - if (plot1 == null && plot2 == null && plot3 == null && plot4 == null) { // No plots to hide - return; - } - if (plot1 == plot4 && plot1 != null) { // Not allowed to see the entire chunk - byteArray.write(0, new byte[0]); - event.setPacket(packet); - return; - } - // Not allowed to see part of the chunk - Plot denied = plot1 != null ? plot1 : plot2 != null ? plot2 : plot3 != null ? plot3 : plot4; - PlotArea area = denied.getArea(); - PlotBlock AIR = new PlotBlock((short) 0, (byte) 0); - byte[] sections = byteArray.read(0); - int size = sections.length; - try { - byte[] biomes = Arrays.copyOfRange(sections, sections.length - 256, sections.length); - sections = Arrays.copyOfRange(sections, 0, sections.length - 256); - List array = new ArrayList<>(); - while (sections.length > 0) { - if (sections[0] < 0) { - break; - } - BlockStorage storage = new BlockStorage(sections); - array.add(storage); - sections = Arrays.copyOfRange(sections, Math.min(storage.getSize() + storage.getLight().length, sections.length), sections.length); - } - // Trim chunk - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - Location loc = new Location(world, bx + x, 0, bz + z); - Plot current = area.getOwnedPlot(loc); - if (current == null) { - continue; - } - if (current == plot1 || current == plot2 || current == plot3 || current == plot4) { - for (BlockStorage section : array) { - for (int y = 0; y < 16; y++) { - if (section.get(x, y, z).id != 0) { - section.set(x, y, z, AIR); - } - } - } - } - } - } - // Write - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(size); - for (BlockStorage section : array) { - section.write(baos); - } - baos.write(sections); - baos.write(biomes); - byteArray.write(0, baos.toByteArray()); - event.setPacket(packet); - } - - } catch (Throwable e) { - e.printStackTrace(); - } - - - } - }); - } -} diff --git a/src/com/boydti/phider/BlockStorage.java b/src/main/java/com/boydti/phider/BlockStorage.java similarity index 69% rename from src/com/boydti/phider/BlockStorage.java rename to src/main/java/com/boydti/phider/BlockStorage.java index db3d397..ead9e2d 100644 --- a/src/com/boydti/phider/BlockStorage.java +++ b/src/main/java/com/boydti/phider/BlockStorage.java @@ -5,48 +5,43 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.mutable.MutableInt; -import com.intellectualcrafters.plot.object.PlotBlock; - public class BlockStorage { - private static final PlotBlock AIR = new PlotBlock((short) 0, (byte) 0); - + private static final Integer AIR = 0x00; + private int bitsPerEntry; - - private final List states; + + private final List states; private FlexibleStorage storage; private final byte[] light; private final int size; - - public BlockStorage(byte[] in) throws IOException { + + public BlockStorage(byte[] in, boolean sky) { MutableInt mut = new MutableInt(); this.bitsPerEntry = readUnsigned(in, mut); - - this.states = new ArrayList(); - + + this.states = new LinkedList<>(); + int stateCount = readVarInt(in, mut); - + for (int i = 0; i < stateCount; i++) { - this.states.add(readPlotBlock(in, mut)); + this.states.add(readVarInt(in, mut)); } - + int expected = readVarInt(in, mut); this.storage = new FlexibleStorage(this.bitsPerEntry, readLongs(in, mut, expected)); - if (in[mut.intValue()] == 0) { - this.light = Arrays.copyOfRange(in, mut.intValue(), mut.intValue() + 4096); - } else { - this.light = new byte[0]; - } + this.light = Arrays.copyOfRange(in, mut.intValue(), in.length); this.size = mut.intValue(); } - + public byte[] getLight() { return light; } - + public int getSize() { return size; } @@ -56,89 +51,81 @@ public byte[] write() throws IOException { write(out); return out.toByteArray(); } - + public void write(ByteArrayOutputStream out) throws IOException { long[] data = this.storage.getData(); out.write(this.bitsPerEntry); writeVarInt(out, this.states.size()); - for (PlotBlock state : this.states) { - writeBlockState(out, state); + for (int state : this.states) { + writeVarInt(out, state); } writeVarInt(out, data.length); writeLongs(out, data); out.write(light); } - + public int getBitsPerEntry() { return this.bitsPerEntry; } - - public List getStates() { + + public List getStates() { return Collections.unmodifiableList(this.states); } - + public FlexibleStorage getStorage() { return this.storage; } - - public PlotBlock get(int x, int y, int z) { + + public int get(int x, int y, int z) { int id = this.storage.get(index(x, y, z)); - return this.bitsPerEntry <= 8 ? (id >= 0 && id < this.states.size() ? this.states.get(id) : AIR) : rawToState(id); + return this.bitsPerEntry <= 8 ? (id >= 0 && id < this.states.size() ? this.states.get(id) : AIR) : id; } - - public void set(int x, int y, int z, PlotBlock state) { - int id = this.bitsPerEntry <= 8 ? (state.id == 0 ? 0 : this.states.indexOf(state)) : stateToRaw(state); + + public void set(int x, int y, int z, int state) { + int id = this.bitsPerEntry <= 8 ? (state == 0 ? 0 : this.states.indexOf(state)) : state; if (id == -1) { this.states.add(state); if (this.states.size() > 1 << this.bitsPerEntry) { this.bitsPerEntry++; - - List oldStates = this.states; + + List oldStates = this.states; if (this.bitsPerEntry > 8) { - oldStates = new ArrayList(this.states); + oldStates = new ArrayList<>(this.states); this.states.clear(); - this.bitsPerEntry = 13; + this.bitsPerEntry = 14; } - + FlexibleStorage oldStorage = this.storage; this.storage = new FlexibleStorage(this.bitsPerEntry, this.storage.getSize()); for (int index = 0; index < this.storage.getSize(); index++) { - this.storage.set(index, this.bitsPerEntry <= 8 ? oldStorage.get(index) : stateToRaw(oldStates.get(index))); + this.storage.set(index, this.bitsPerEntry <= 8 ? oldStorage.get(index) : oldStates.get(index)); } } - - id = this.bitsPerEntry <= 8 ? this.states.indexOf(state) : stateToRaw(state); + + id = this.bitsPerEntry <= 8 ? this.states.indexOf(state) : state; } this.storage.set(index(x, y, z), id); } - + public boolean isEmpty() { for (int index = 0; index < this.storage.getSize(); index++) { if (this.storage.get(index) != 0) { return false; } } - + return true; } - + private static int index(int x, int y, int z) { return y << 8 | z << 4 | (x); } - - private static PlotBlock rawToState(int raw) { - return new PlotBlock((short) (raw >> 4), (byte) (raw & 0xF)); - } - - private static int stateToRaw(PlotBlock state) { - return (state.id << 4) | (state.data & 0xF); - } - + @Override public boolean equals(Object o) { return o instanceof BlockStorage && this.bitsPerEntry == ((BlockStorage) o).bitsPerEntry && this.states.equals(((BlockStorage) o).states) && this.storage.equals(((BlockStorage) o).storage); } - + @Override public int hashCode() { int result = this.bitsPerEntry; @@ -146,19 +133,19 @@ public int hashCode() { result = 31 * result + this.storage.hashCode(); return result; } - + public byte read(byte[] bytes, MutableInt index) { byte value = bytes[index.intValue()]; index.increment(); return value; } - + public int readUnsigned(byte[] bytes, MutableInt index) { byte value = bytes[index.intValue()]; index.increment(); return value & 0xFF; } - + public long readLong(byte[] bytes, MutableInt index) { long value = 0; for (int i = 0, j = 56; i < 8; i++, j -= 8) { @@ -167,7 +154,7 @@ public long readLong(byte[] bytes, MutableInt index) { index.add(8); return value; } - + public int readVarInt(byte[] bytes, MutableInt index) { int value = 0; int size = 0; @@ -178,48 +165,39 @@ public int readVarInt(byte[] bytes, MutableInt index) { return 1 / 0; } } - + return value | ((b & 0x7F) << (size * 7)); } - - public long[] readLongs(byte[] bytes, MutableInt mut, int length) throws IOException { + + public long[] readLongs(byte[] bytes, MutableInt mut, int length) { if (length < 0) { throw new IllegalArgumentException("Array cannot have length less than 0."); } - + long l[] = new long[length]; for (int index = 0; index < length; index++) { l[index] = readLong(bytes, mut); } - + return l; } - public PlotBlock readPlotBlock(byte[] bytes, MutableInt index) { - int rawId = readVarInt(bytes, index); - return new PlotBlock((short) (rawId >> 4), (byte) (rawId & 0xF)); - } - - public void writeVarInt(ByteArrayOutputStream out, int i) throws IOException { + public void writeVarInt(ByteArrayOutputStream out, int i) { while ((i & ~0x7F) != 0) { out.write((i & 0x7F) | 0x80); i >>>= 7; } - + out.write(i); } - - public void writeBlockState(ByteArrayOutputStream out, PlotBlock blockState) throws IOException { - writeVarInt(out, (blockState.id << 4) | (blockState.data & 0xF)); - } - - public void writeLongs(ByteArrayOutputStream out, long[] l) throws IOException { + + public void writeLongs(ByteArrayOutputStream out, long[] l) { for (int index = 0; index < l.length; index++) { writeLong(out, l[index]); } } - - public void writeLong(ByteArrayOutputStream out, long l) throws IOException { + + public void writeLong(ByteArrayOutputStream out, long l) { out.write((byte) (l >>> 56)); out.write((byte) (l >>> 48)); out.write((byte) (l >>> 40)); diff --git a/src/main/java/com/boydti/phider/FlexibleStorage.java b/src/main/java/com/boydti/phider/FlexibleStorage.java new file mode 100644 index 0000000..55f3c58 --- /dev/null +++ b/src/main/java/com/boydti/phider/FlexibleStorage.java @@ -0,0 +1,101 @@ +package com.boydti.phider; + +import java.util.Arrays; + +public class FlexibleStorage { + private final long[] data; + private final int bitsPerEntry; + private final int size; + private final long maxEntryValue; + + FlexibleStorage(int bitsPerEntry, int size) { + this(bitsPerEntry, new long[roundToNearest(size * bitsPerEntry, 64) / 64]); + } + + FlexibleStorage(int bitsPerEntry, long[] data) { + if ((bitsPerEntry < 1) || (bitsPerEntry > 32)) { + throw new IllegalArgumentException( + "BitsPerEntry cannot be outside of accepted range. " + bitsPerEntry); + } + this.bitsPerEntry = bitsPerEntry; + this.data = data; + + this.size = (this.data.length * 64 / this.bitsPerEntry); + this.maxEntryValue = ((1L << this.bitsPerEntry) - 1L); + } + + private static int roundToNearest(int value, int roundTo) { + if (roundTo == 0) { + return 0; + } + if (value == 0) { + return roundTo; + } + if (value < 0) { + roundTo *= -1; + } + int remainder = value % roundTo; + return remainder != 0 ? value + roundTo - remainder : value; + } + + long[] getData() { + return this.data; + } + + int getSize() { + return this.size; + } + + int get(int index) { + if ((index < 0) || (index > this.size - 1)) { + throw new IndexOutOfBoundsException(); + } + int bitIndex = index * this.bitsPerEntry; + int startIndex = bitIndex / 64; + int endIndex = ((index + 1) * this.bitsPerEntry - 1) / 64; + int startBitSubIndex = bitIndex % 64; + if (startIndex == endIndex) { + return (int) (this.data[startIndex] >>> startBitSubIndex & this.maxEntryValue); + } + int endBitSubIndex = 64 - startBitSubIndex; + return (int) ( + (this.data[startIndex] >>> startBitSubIndex | this.data[endIndex] << endBitSubIndex) + & this.maxEntryValue); + } + + void set(int index, int value) { + if ((index < 0) || (index > this.size - 1)) { + throw new IndexOutOfBoundsException(); + } + if ((value < 0) || (value > this.maxEntryValue)) { + throw new IllegalArgumentException("Value cannot be outside of accepted range."); + } + int bitIndex = index * this.bitsPerEntry; + int startIndex = bitIndex / 64; + int endIndex = ((index + 1) * this.bitsPerEntry - 1) / 64; + int startBitSubIndex = bitIndex % 64; + this.data[startIndex] = + (this.data[startIndex] & ~(this.maxEntryValue << startBitSubIndex) + | (value & this.maxEntryValue) << startBitSubIndex); + if (startIndex != endIndex) { + int endBitSubIndex = 64 - startBitSubIndex; + this.data[endIndex] = (this.data[endIndex] >>> endBitSubIndex << endBitSubIndex + | (value & this.maxEntryValue) >> endBitSubIndex); + } + } + + public boolean equals(Object o) { + return (this == o) || (((o instanceof FlexibleStorage)) && (Arrays + .equals(this.data, ((FlexibleStorage) o).data)) && (this.bitsPerEntry + == ((FlexibleStorage) o).bitsPerEntry) && (this.size == ((FlexibleStorage) o).size) && ( + this.maxEntryValue == ((FlexibleStorage) o).maxEntryValue)); + } + + public int hashCode() { + int result = Arrays.hashCode(this.data); + result = 31 * result + this.bitsPerEntry; + result = 31 * result + this.size; + result = 31 * result + (int) this.maxEntryValue; + return result; + } +} diff --git a/src/com/boydti/phider/Main.java b/src/main/java/com/boydti/phider/Main.java similarity index 54% rename from src/com/boydti/phider/Main.java rename to src/main/java/com/boydti/phider/Main.java index 86bc7c0..acec655 100644 --- a/src/com/boydti/phider/Main.java +++ b/src/main/java/com/boydti/phider/Main.java @@ -1,5 +1,11 @@ package com.boydti.phider; +import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil; +import com.github.intellectualsites.plotsquared.plot.flag.BooleanFlag; +import com.github.intellectualsites.plotsquared.plot.flag.Flags; +import com.github.intellectualsites.plotsquared.plot.object.Plot; +import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; +import com.github.intellectualsites.plotsquared.plot.util.Permissions; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -8,42 +14,32 @@ import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.plugin.java.JavaPlugin; -import com.intellectualcrafters.plot.flag.BooleanFlag; -import com.intellectualcrafters.plot.flag.Flags; -import com.intellectualcrafters.plot.object.Plot; -import com.intellectualcrafters.plot.object.PlotPlayer; -import com.intellectualcrafters.plot.util.Permissions; -import com.plotsquared.bukkit.util.BukkitUtil; - public class Main extends JavaPlugin implements Listener { - + public static BooleanFlag HIDE_FLAG = new BooleanFlag("hide"); - @Override public void onEnable() { new PacketHandler(this); Bukkit.getPluginManager().registerEvents(this, this); Flags.registerFlag(HIDE_FLAG); } - - @EventHandler - public void onTeleport(PlayerTeleportEvent event) { - final Player player = event.getPlayer(); - final PlotPlayer pp = BukkitUtil.getPlayer(player); - if (Permissions.hasPermission(pp, "plots.plothider.bypass")) { // Admin bypass + + @EventHandler public void onTeleport(PlayerTeleportEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + if (Permissions.hasPermission(pp, "plots.plothider.bypass")) { return; } Plot plot = pp.getCurrentPlot(); - if (plot != null && (plot.isDenied(pp.getUUID()) || (!plot.isAdded(pp.getUUID()) && HIDE_FLAG.isTrue(plot)))) { + if ((plot != null) && ((plot.isDenied(pp.getUUID())) || ((!plot.isAdded(pp.getUUID())) + && (HIDE_FLAG.isTrue(plot))))) { Location to = event.getTo(); Location from = event.getFrom(); - if (to.getWorld().equals(from.getWorld()) && to.distanceSquared(from) < 8) { + if ((to.getWorld().equals(from.getWorld())) && (to.distanceSquared(from) < 8.0D)) { event.setTo(player.getLocation()); event.setCancelled(true); player.setVelocity(player.getVelocity()); } } } - - } diff --git a/src/main/java/com/boydti/phider/PacketHandler.java b/src/main/java/com/boydti/phider/PacketHandler.java new file mode 100644 index 0000000..22cb3fc --- /dev/null +++ b/src/main/java/com/boydti/phider/PacketHandler.java @@ -0,0 +1,278 @@ +package com.boydti.phider; + +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.comphenix.protocol.wrappers.ChunkCoordIntPair; +import com.comphenix.protocol.wrappers.MultiBlockChangeInfo; +import com.comphenix.protocol.wrappers.nbt.NbtBase; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil; +import com.github.intellectualsites.plotsquared.plot.PlotSquared; +import com.github.intellectualsites.plotsquared.plot.object.Location; +import com.github.intellectualsites.plotsquared.plot.object.Plot; +import com.github.intellectualsites.plotsquared.plot.object.PlotArea; +import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; +import com.github.intellectualsites.plotsquared.plot.util.Permissions; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; + +public class PacketHandler { + PacketHandler(Main main) { + ProtocolManager manager = ProtocolLibrary.getProtocolManager(); + manager.addPacketListener( + new PacketAdapter(main, ListenerPriority.NORMAL, PacketType.Play.Server.BLOCK_CHANGE) { + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + if (Permissions.hasPermission(pp, "plots.plothider.bypass")) { // Admin bypass + return; + } + String world = pp.getLocation().getWorld(); + if (!PlotSquared.get().hasPlotArea(world)) { // Not a plot area + return; + } + PacketContainer packet = event.getPacket(); + StructureModifier positions = packet.getBlockPositionModifier(); + BlockPosition position = positions.read(0); + Location loc = new Location(world, position.getX(), 0, position.getZ()); + Plot plot = loc.getOwnedPlot(); + if (plot != null && (plot.isDenied(pp.getUUID()) || (!plot.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot)))) { + event.setCancelled(true); + } + } + }); + + manager.addPacketListener(new PacketAdapter(main, ListenerPriority.NORMAL, + PacketType.Play.Server.MULTI_BLOCK_CHANGE) { + @Override + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + if (Permissions.hasPermission(pp, "plots.plothider.bypass")) { // Admin bypass + return; + } + String world = pp.getLocation().getWorld(); + if (!PlotSquared.get().hasPlotArea(world)) { // Not a plot area + return; + } + PacketContainer packet = event.getPacket(); + StructureModifier chunkArray = packet.getChunkCoordIntPairs(); + ChunkCoordIntPair chunk = chunkArray.read(0); + int cx = chunk.getChunkX(); + int cz = chunk.getChunkZ(); + int bx = cx << 4; + int bz = cz << 4; + Location corner1 = new Location(world, bx, 0, bz); + Location corner2 = new Location(world, bx + 15, 0, bz); + Location corner3 = new Location(world, bx, 0, bz + 15); + Location corner4 = new Location(world, bx + 15, 0, bz + 15); + Plot plot1 = corner1.getOwnedPlot(); + Plot plot2 = corner2.getOwnedPlot(); + Plot plot3 = corner3.getOwnedPlot(); + Plot plot4 = corner4.getOwnedPlot(); + plot1 = (plot1 != null && (plot1.isDenied(pp.getUUID()) || (!plot1.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot1)))) ? plot1 : null; + plot2 = (plot2 != null && (plot2.isDenied(pp.getUUID()) || (!plot2.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot2)))) ? plot2 : null; + plot3 = (plot3 != null && (plot3.isDenied(pp.getUUID()) || (!plot3.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot3)))) ? plot3 : null; + plot4 = (plot4 != null && (plot4.isDenied(pp.getUUID()) || (!plot4.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot4)))) ? plot4 : null; + if (plot1 == null && plot2 == null && plot3 == null && plot4 == null) { // No plots to hide + return; + } + StructureModifier changeArray = packet.getMultiBlockChangeInfoArrays(); + if (plot1 == plot4 && plot1 != null) { // Not allowed to see the entire chunk + event.setCancelled(true); + return; + } + // Hide some of the blocks (but maybe not all) + List changes = new ArrayList(Arrays.asList((Object[]) changeArray.read(0))); + Iterator iter = changes.iterator(); + Plot denied = plot1 != null ? plot1 : plot2 != null ? plot2 : plot3 != null ? plot3 : plot4; + PlotArea area = denied.getArea(); + while (iter.hasNext()) { + MultiBlockChangeInfo change = iter.next(); + int x = change.getAbsoluteX(); + int z = change.getAbsoluteZ(); + Plot current = area.getOwnedPlot(new Location(world, x, 0, z)); + if (current == null) { + continue; + } + if (current == plot1 || current == plot2 || current == plot3 || current == plot4) { + iter.remove(); + } + } + if (changes.size() == 0) { + event.setCancelled(true); + return; + } +// changeArray.write(0, changes.toArray(new MultiBlockChangeInfo[changes.size()])); + changeArray.write(0, changes.toArray(new MultiBlockChangeInfo[0])); + event.setPacket(packet); + } + }); + + manager.addPacketListener( + new PacketAdapter(main, ListenerPriority.NORMAL, PacketType.Play.Server.MAP_CHUNK) { + public void onPacketSending(PacketEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + if (Permissions.hasPermission(pp, "plots.plothider.bypass")) { // Admin bypass + return; + } + String world = pp.getLocation().getWorld(); + if (!PlotSquared.get().hasPlotArea(world)) { // Not a plot area + return; + } + PacketContainer packet = event.getPacket(); + StructureModifier ints = packet.getIntegers(); + StructureModifier byteArray = packet.getByteArrays(); + StructureModifier booleans = packet.getBooleans(); + int cx = ints.read(0); + int cz = ints.read(1); + int bx = cx << 4; + int bz = cz << 4; + boolean biomes = booleans.read(0); + Location corner1 = new Location(world, bx, 0, bz); + Location corner2 = new Location(world, bx + 15, 0, bz); + Location corner3 = new Location(world, bx, 0, bz + 15); + Location corner4 = new Location(world, bx + 15, 0, bz + 15); + Plot plot1 = corner1.getOwnedPlot(); + Plot plot2 = corner2.getOwnedPlot(); + Plot plot3 = corner3.getOwnedPlot(); + Plot plot4 = corner4.getOwnedPlot(); + plot1 = (plot1 != null && (plot1.isDenied(pp.getUUID()) || (!plot1.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot1)))) ? plot1 : null; + plot2 = (plot2 != null && (plot2.isDenied(pp.getUUID()) || (!plot2.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot2)))) ? plot2 : null; + plot3 = (plot3 != null && (plot3.isDenied(pp.getUUID()) || (!plot3.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot3)))) ? plot3 : null; + plot4 = (plot4 != null && (plot4.isDenied(pp.getUUID()) || (!plot4.isAdded(pp.getUUID()) && Main.HIDE_FLAG.isTrue(plot4)))) ? plot4 : null; + if (plot1 == null && plot2 == null && plot3 == null && plot4 == null) { // No plots to hide + return; + } + if (plot1 == plot4 && plot1 != null) { // Not allowed to see the entire chunk + byteArray.write(0, new byte[byteArray.read(0).length]); + StructureModifier>> list = packet.getListNbtModifier(); + list.write(0, new ArrayList<>()); + event.setPacket(packet); + return; + } + // Not allowed to see part of the chunk + Plot denied = plot1 != null ? plot1 : plot2 != null ? plot2 : plot3 != null ? plot3 : plot4; + PlotArea area = denied.getArea(); + int AIR = 0; + byte[] sections = byteArray.read(0); + int size = sections.length; + int datasize = sections.length; + List array = new ArrayList<>(); + int layer = 0; + byte[] biomearray; + ByteArrayInputStream buffer; + int bitMask = ints.read(2); + if (biomes) { + buffer = new ByteArrayInputStream(Arrays.copyOfRange(sections, 0, + sections.length - 256 * Integer.bitCount(bitMask))); + biomearray = Arrays.copyOfRange(sections, + sections.length - 256 * Integer.bitCount(bitMask), sections.length); + datasize -= 256 * Integer.bitCount(bitMask); + } else { + buffer = new ByteArrayInputStream(sections); + biomearray = null; + } + + try { + boolean sky = + Bukkit.getWorld(world).getEnvironment() == World.Environment.NORMAL; + + byte[] section; + for (layer = 0; layer < 16; layer++) { + if ((bitMask >> layer & 0x1) == 1) { + int start = datasize - buffer.available(); + + int bitsperBlock = readVarInt(buffer); + + int paletteLength = readVarInt(buffer); + + for (int i = 0; i < paletteLength; i++) { + readVarInt(buffer); + } + + int dataArrayLength = readVarInt(buffer); + + for (int i = 0; i < bitsperBlock * 512; i++) { + readVarInt(buffer); + } + + buffer.skip(sky ? 4096 : 2048); + + int end = datasize - buffer.available(); + + section = Arrays.copyOfRange(sections, start, end); + + BlockStorage storage = new BlockStorage(section, sky); + array.add(storage); + } + } + int z; + for (int x = 0; x < 16; x++) { + for (z = 0; z < 16; z++) { + Location loc = new Location(world, bx + x, 0, bz + z); + Plot current = area.getOwnedPlot(loc); + if (current != null) { + if ((current == plot1) || (current == plot2) || (current + == plot3) || (current == plot4)) { + for (BlockStorage section1 : array) { + for (int y = 0; y < 16; y++) { + if (section1.get(x, y, z) != 0) { + section1.set(x, y, z, AIR); + } + } + } + } + } + } + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(size); + for (BlockStorage section1 : array) { + section1.write(baos); + } + if (biomearray != null) { + baos.write(biomearray); + } + byteArray.write(0, baos.toByteArray()); + + event.setPacket(packet); + } catch (Throwable e) { + e.printStackTrace(); + } + } + }); + } + + private int readVarInt(InputStream stream) throws IOException { + int i = 0; + int j = 0; + + byte b0; + do { + b0 = (byte) stream.read(); + i |= (b0 & 127) << j++ * 7; + if(j > 5) { + throw new RuntimeException("VarInt too big"); + } + } while((b0 & 128) == 128); + + return i; + } +} diff --git a/plugin.yml b/src/main/resources/plugin.yml similarity index 72% rename from plugin.yml rename to src/main/resources/plugin.yml index bccb571..e5d1b3a 100644 --- a/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: PlotHider main: com.boydti.phider.Main -version: 3.4.0 +version: 4.0.0 description: Hide plots from other players -authors: [Empire92] +authors: [Empire92, dordsor21] depend: [PlotSquared,ProtocolLib] \ No newline at end of file