diff --git a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/PortalsCache.java b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/PortalsCache.java index 5b6cbdb..d7d141e 100644 --- a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/PortalsCache.java +++ b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/PortalsCache.java @@ -8,15 +8,16 @@ import com.comphenix.protocol.wrappers.BlockPosition; import com.comphenix.protocol.wrappers.ChunkCoordIntPair; import com.comphenix.protocol.wrappers.MultiBlockChangeInfo; import com.comphenix.protocol.wrappers.WrappedBlockData; -import io.papermc.lib.PaperLib; import me.SuperRonanCraft.BetterRTPAddons.Main; -import me.SuperRonanCraft.BetterRTPAddons.addons.portals.cmds.WrapperPlayServerBlockChange; +import me.SuperRonanCraft.BetterRTPAddons.packets.BlockChangeArray; +import me.SuperRonanCraft.BetterRTPAddons.packets.WrapperPlayServerBlockChange; +import me.SuperRonanCraft.BetterRTPAddons.packets.WrapperPlayServerMultiBlockChange; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; @@ -43,26 +44,39 @@ public class PortalsCache { } Location old_loc1 = portal.loc_1; Location old_loc2 = portal.loc_1; - if (loc2) portal.loc_2 = loc; - else portal.loc_1 = loc; + if (loc2) + portal.loc_2 = loc; + else + portal.loc_1 = loc; if (Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) { ProtocolManager pm = ProtocolLibrary.getProtocolManager(); - WrapperPlayServerBlockChange block = new WrapperPlayServerBlockChange(pm.createPacket(PacketType.Play.Server.BLOCK_CHANGE)); - block.setBlockData(WrappedBlockData.createData(Material.GLOWSTONE)); - block.setLocation(new BlockPosition(loc.toVector())); - block.sendPacket(p); - - } - - if (portal.loc_1 != null && portal.loc_2 != null) { - //if (Math.abs(portal.loc_1.getBlockX() - portal.loc_2.getBlockX()) <= 10) - //if (Math.abs(portal.loc_1.getBlockZ() - portal.loc_2.getBlockZ()) <= 10) - //if (Math.abs(portal.loc_1.getBlockY() - portal.loc_2.getBlockY()) <= 10) { - preview(portal.loc_1, portal.loc_2); - //} - } else { - p.sendMessage((portal.loc_1 == null) + " " + (portal.loc_2 == null)); + if (portal.loc_1 != null && portal.loc_2 != null) { + //if (Math.abs(portal.loc_1.getBlockX() - portal.loc_2.getBlockX()) <= 10) + //if (Math.abs(portal.loc_1.getBlockZ() - portal.loc_2.getBlockZ()) <= 10) + //if (Math.abs(portal.loc_1.getBlockY() - portal.loc_2.getBlockY()) <= 10) { + //preview(portal.loc_1, portal.loc_2); + //} + Location max = portal.loc_1; + Location min = portal.loc_2; + for (int x = Math.max(max.getBlockX(), min.getBlockX()); x >= Math.min(min.getBlockX(), max.getBlockX()); x--) { + for (int y = Math.max(max.getBlockY(), min.getBlockY()); y >= Math.min(min.getBlockY(), max.getBlockY()); y--) { + for (int z = Math.max(max.getBlockZ(), min.getBlockZ()); z >= Math.min(min.getBlockZ(), max.getBlockZ()); z--) { + WrapperPlayServerBlockChange packet = new WrapperPlayServerBlockChange(pm.createPacket(PacketType.Play.Server.BLOCK_CHANGE)); + packet.setBlockData(WrappedBlockData.createData(Material.REDSTONE_BLOCK)); + packet.setLocation(new BlockPosition(new Location(max.getWorld(), x, y, z).toVector())); + packet.sendPacket(p); + //Block block = max.getWorld().getBlockAt(x, y, z); + //block.setType(Material.GLOWSTONE); + } + } + } + } else { + WrapperPlayServerBlockChange packet = new WrapperPlayServerBlockChange(pm.createPacket(PacketType.Play.Server.BLOCK_CHANGE)); + packet.setBlockData(WrappedBlockData.createData(Material.GLOWSTONE)); + packet.setLocation(new BlockPosition(loc.toVector())); + packet.sendPacket(p); + } } } @@ -72,21 +86,24 @@ public class PortalsCache { PacketContainer packet = pm .createPacket(PacketType.Play.Server.MULTI_BLOCK_CHANGE); Chunk chunk = loc1.getChunk(); - ChunkCoordIntPair chunkcoords = new ChunkCoordIntPair(chunk.getX(), - chunk.getZ()); - MultiBlockChangeInfo[] change = new MultiBlockChangeInfo[256]; - + BlockChangeArray change = new BlockChangeArray(256); + WrapperPlayServerMultiBlockChange wrapper = new WrapperPlayServerMultiBlockChange(packet); + //wrapper.setChunk(new ChunkCoordIntPair(chunk.getX(), chunk.getZ())); for (int x = 0; x <= 15; x++) { for(int z = 0; z <= 15; z++) { - change[(16 * x) + z] = new MultiBlockChangeInfo(new Location(loc1.getWorld(), loc1.getX() + x, 100, loc1.getZ() + z), WrappedBlockData.createData(Material.GOLD_BLOCK)); + int index = (16 * x) + z; + BlockChangeArray.BlockChange block = change.getBlockChange(index); + block.setBlockID(WrappedBlockData.createData(Material.GOLD_BLOCK).getType().getId()); + Location loc = loc1.clone(); + loc.setX(loc.getX() + x); + loc.setZ(loc.getZ() + z); + block.setLocation(loc); + change.setBlockChange(index, block); } } - packet.getChunkCoordIntPairs().write(0, chunkcoords); - packet.getMultiBlockChangeInfoArrays().write(0, change); - - + wrapper.setRecordData(change); for (Player player : Bukkit.getOnlinePlayers()) { try { pm.sendServerPacket(player, packet); diff --git a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/LocationFinder.java b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/LocationFinder.java index 3274406..51939c3 100644 --- a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/LocationFinder.java +++ b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/LocationFinder.java @@ -13,11 +13,11 @@ public interface LocationFinder { BlockIterator iter = new BlockIterator(player, range); Block lastBlock = null; while (iter.hasNext()) { - lastBlock = iter.next(); - if (lastBlock.getType() == Material.AIR) { - continue; + Block block = iter.next(); + if (block.getType() != Material.AIR) { + lastBlock = block; + break; } - break; } return lastBlock; } diff --git a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/PortalsCommand_Loc1.java b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/PortalsCommand_Loc1.java index 5a0a59d..dcba1f2 100644 --- a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/PortalsCommand_Loc1.java +++ b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/PortalsCommand_Loc1.java @@ -10,6 +10,7 @@ import me.SuperRonanCraft.BetterRTPAddons.addons.portals.AddonPortals; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -22,8 +23,13 @@ public class PortalsCommand_Loc1 implements PortalsCommands, LocationFinder { @Override public void execute(CommandSender sendi, String label, String[] args, AddonPortals addonPortals) { Player p = (Player) sendi; - Location loc = getTargetBlock(p, 10).getLocation(); - addonPortals.getPortals().setPortal(p, loc, false); - sendi.sendMessage("Location 1 set to this location!"); + Block block = getTargetBlock(p, 10); + if (block != null) { + Location loc = block.getLocation(); + addonPortals.getPortals().setPortal(p, loc, false); + sendi.sendMessage("Location 1 set to this location!"); + } else { + sendi.sendMessage("Please look at a block!"); + } } } diff --git a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/PortalsCommand_Loc2.java b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/PortalsCommand_Loc2.java index 62c477f..eec62ac 100644 --- a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/PortalsCommand_Loc2.java +++ b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/PortalsCommand_Loc2.java @@ -13,8 +13,13 @@ public class PortalsCommand_Loc2 implements PortalsCommands, LocationFinder { @Override public void execute(CommandSender sendi, String label, String[] args, AddonPortals addonPortals) { Player p = (Player) sendi; - Location loc = getTargetBlock(p, 10).getLocation(); - addonPortals.getPortals().setPortal(p, loc, true); - sendi.sendMessage("Location 2 set to this location!"); + Block block = getTargetBlock(p, 10); + if (block != null) { + Location loc = block.getLocation(); + addonPortals.getPortals().setPortal(p, loc, true); + sendi.sendMessage("Location 2 set to this location!"); + } else { + sendi.sendMessage("Please look at a block!"); + } } } diff --git a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/AbstractPacket.java b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/AbstractPacket.java similarity index 97% rename from BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/AbstractPacket.java rename to BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/AbstractPacket.java index a67a4d4..4d2e4cd 100644 --- a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/AbstractPacket.java +++ b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/AbstractPacket.java @@ -1,4 +1,4 @@ -package me.SuperRonanCraft.BetterRTPAddons.addons.portals.cmds; +package me.SuperRonanCraft.BetterRTPAddons.packets; import java.lang.reflect.InvocationTargetException; diff --git a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/BlockChangeArray.java b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/BlockChangeArray.java new file mode 100644 index 0000000..d62e5d2 --- /dev/null +++ b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/BlockChangeArray.java @@ -0,0 +1,259 @@ +package me.SuperRonanCraft.BetterRTPAddons.packets; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import org.bukkit.Location; +import org.bukkit.World; + +/** + * Utility class for creating arrays of block changes. + *
+ * See also {@link Packet34MultiBlockChange}. + * + * @author Kristian + */ +public class BlockChangeArray { + /** + * Represents a single block change. + *
+ * Retrieved by {@link BlockChangeArray#getBlockChange(int)}. + * + * @author Kristian + */ + public class BlockChange { + // Index of the block change entry that we may change + private final int index; + + private BlockChange(int index) { + this.index = index; + } + + /** + * Set the location of the block change. + *
+ * The world and absolute chunk position must be provided. + * @param world - the world the block belongs to. + * @param chunkX - the x position of the origin chunk + * @param chunkZ - the y position of the origin chunk + * @return The location. + */ + public Location getLocation(World world, int chunkX, int chunkZ) { + if (world == null) + throw new IllegalArgumentException("World cannot be NULL."); + return new Location( + world, + (chunkX << 4) + getRelativeX(), + getAbsoluteY(), + (chunkZ << 4) + getRelativeZ() + ); + } + + /** + * Set the relative x-axis position of current block change in the chunk. + * @param relativeX - relative block change location. + * @return This block change, for chaining. + */ + public BlockChange setRelativeX(int relativeX) { + setValue(relativeX, 28, 0xF0000000); + return this; + } + + /** + * Retrieve the relative x-axis position of the current block change. + * @return X-axis position of the block change. + */ + public int getRelativeX() { + return getValue(28, 0xF0000000); + } + + /** + * Set the relative z-axis position of current block change in the chunk. + * @param relativeZ - relative block change location. + * @return This block change, for chaining. + */ + public BlockChange setRelativeZ(int relativeX) { + setValue(relativeX, 24, 0xF000000); + return this; + } + + /** + * Retrieve the relative z-axis position of the current block change. + * @return Z-axis position of the block change. + */ + public byte getRelativeZ() { + return (byte) getValue(24, 0xF000000); + } + + /** + * Set the absolute y-axis position of the current block change. + * @param absoluteY - the absolute y-axis position. + * @return This block change, for chaining. + */ + public BlockChange setAbsoluteY(int absoluteY) { + setValue(absoluteY, 16, 0xFF0000); + return this; + } + + /** + * Retrieve the absolute y-axis position of the current block change. + * @return Y-axis position of the block change. + */ + public int getAbsoluteY() { + return getValue(16, 0xFF0000); + } + + /** + * Set the block ID of the current block change. + * @param blockID - ID that the changed block will have. + * @return This block change, for chaining. + */ + public BlockChange setBlockID(int blockID) { + setValue(blockID, 4, 0xFFF0); + return this; + } + + /** + * Retrieve the block ID of the current block change. + * @return The block ID that the block will change into. + */ + public int getBlockID() { + return getValue(4, 0xFFF0); + } + + /** + * Set the block metadata of the current block change. + * @param metadata - metadata that the changed block will have. + * @return This block change, for chaining. + */ + public BlockChange setMetadata(int metadata) { + setValue(metadata, 0, 0xF); + return this; + } + + /** + * Retrieve the block metadata of the current block change. + * @return The block metadata that the block will change into. + */ + public int getMetadata() { + return getValue(0, 0xF); + } + + /** + * Retrieve the index of the current block change. + * @return Index of the current block change. + */ + public int getIndex() { + return index; + } + + /** + * Retrieve the integer representation of this block change. + * @return Integer representation. + */ + private int asInteger() { + return data[index]; + } + + // Should be inlined + private void setValue(int value, int leftShift, int updateMask) { + data[index] = ((value << leftShift) & updateMask) | (data[index] & ~updateMask); + } + + private int getValue(int rightShift, int updateMask) { + return (data[index] & updateMask) >> rightShift; + } + } + + /** + * Single of a single block change record in bytes. + */ + private static final int RECORD_SIZE = 4; + + /** + * The internally backed array. + */ + private int[] data; + + /** + * Construct a new array of block changes. + * @param blockChanges - the number of blocks that have been changed. + */ + public BlockChangeArray(int blockChanges) { + data = new int[blockChanges]; + } + + /** + * Construct a new block change array from the copy of a given data array. + * @param data - the data array to store internally. + */ + public BlockChangeArray(byte[] input) { + if ((input.length % RECORD_SIZE) != 0) + throw new IllegalArgumentException("The lenght of the input data array should be a multiple of " + RECORD_SIZE + "."); + + IntBuffer source = ByteBuffer.wrap(input).asIntBuffer(); + IntBuffer destination = IntBuffer.allocate(input.length / RECORD_SIZE); + destination.put(source); + + // Get the copied array + data = destination.array(); + } + + /** + * Retrieve a view of the block change entry at the given index. + *
+ * Any modification to this view will be stored in the block change array itself. + * @param index - index of the block change to retrieve. + * @return A view of the block change entry. + */ + public BlockChange getBlockChange(int index) { + if (index < 0 || index >= getSize()) + throw new IllegalArgumentException("Index is out of bounds."); + return new BlockChange(index); + } + + /** + * Set the block change at the specified index to contain the given block. + * @param loc - the location that will be converted. + * @param block - the new content of the block change. + */ + public void setBlockChange(int index, BlockChange change) { + if (change == null) + throw new IllegalArgumentException("Block change cannot be NULL."); + data[index] = change.asInteger(); + } + + /** + * Retrieve the number of block changes. + * @return The number of block changes. + */ + public int getSize() { + return data.length; + } + + /** + * Convert this block change array to a byte array. + * @return The resulting byte array. + */ + public byte[] toByteArray() { + ByteBuffer copy = ByteBuffer.allocate(data.length * RECORD_SIZE); + + // Copy in the integer array + copy.asIntBuffer().put(data); + return copy.array(); + } +} \ No newline at end of file diff --git a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/WrapperPlayServerBlockChange.java b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/WrapperPlayServerBlockChange.java similarity index 96% rename from BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/WrapperPlayServerBlockChange.java rename to BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/WrapperPlayServerBlockChange.java index 9e3efa6..68e8ed0 100644 --- a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/addons/portals/cmds/WrapperPlayServerBlockChange.java +++ b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/WrapperPlayServerBlockChange.java @@ -1,4 +1,4 @@ -package me.SuperRonanCraft.BetterRTPAddons.addons.portals.cmds; +package me.SuperRonanCraft.BetterRTPAddons.packets; import org.bukkit.Location; import org.bukkit.World; diff --git a/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/WrapperPlayServerMultiBlockChange.java b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/WrapperPlayServerMultiBlockChange.java new file mode 100644 index 0000000..fc2d7ba --- /dev/null +++ b/BetterRTPAddons/src/main/java/me/SuperRonanCraft/BetterRTPAddons/packets/WrapperPlayServerMultiBlockChange.java @@ -0,0 +1,159 @@ +package me.SuperRonanCraft.BetterRTPAddons.packets; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.ChunkCoordIntPair; + +/** + * Represents a multi-block change. + *
+ * See also {@link BlockChangeArray} for constructing an array of block changes. + * + * @author Kristian + */ +public class WrapperPlayServerMultiBlockChange extends AbstractPacket { + public static final PacketType TYPE = PacketType.Play.Server.MULTI_BLOCK_CHANGE; + + public WrapperPlayServerMultiBlockChange() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerMultiBlockChange(PacketContainer packet) { + super(packet, TYPE); + } + + /** + * Retrieve the chunk x position. + * @return The chunk x. + */ + public int getChunkX() { + return getChunk().getChunkX(); + } + + /** + * Set the chunk x position. + * @param index - the new position. + */ + public void setChunkX(int index) { + setChunk(new ChunkCoordIntPair(index, getChunkZ())); + } + + /** + * Retrieve the chunk Z position. + * @return The chunk z. + */ + public int getChunkZ() { + return getChunk().getChunkZ(); + } + + /** + * Set the chunk Z position. + * @param index - the new position. + */ + public void setChunkZ(int index) { + setChunk(new ChunkCoordIntPair(getChunkX(), index)); + } + + /** + * Retrieve the chunk that has been altered. + * @return The current chunk + */ + public ChunkCoordIntPair getChunk() { + return handle.getChunkCoordIntPairs().read(0); + } + + /** + * Set chunk that has been altered. + * @param value - new value. + */ + public void setChunk(ChunkCoordIntPair value) { + handle.getChunkCoordIntPairs().write(0, value); + } + + /** + * Retrieve the number of blocks affected. + * @return The current Record count + */ + public short getRecordCount() { + return handle.getIntegers().read(0).shortValue(); + } + + /** + * Set the number of blocks affected. + * @param value - new value. + */ + public void setRecordCount(short value) { + handle.getIntegers().write(0, (int) value); + } + + /** + * Retrieve the record data. + *
+ * Each record is four bytes, containing the following data: + *
Bit mask | + *Width | + *Meaning | + *
---|---|---|
00 00 00 0F | + *4 bits | + *Block metadata | + *
00 00 FF F0 | + *12 bits | + *Block ID | + *
00 FF 00 00 | + *8 bits | + *Y co-ordinate | + *
0F 00 00 00 | + *4 bits | + *Z co-ordinate, relative to chunk | + *
F0 00 00 00 | + *4 bits | + *X co-ordinate, relative to chunk | + *
+ * Each record is four bytes. See {@link #getRecordData()} for more information. + * @param value - new value. + */ + public void setRecordData(byte[] value) { + setRecordCount((short) value.length); + handle.getByteArrays().write(0, value); + } + + /** + * Set the record data using the given helper array. + * @param array - useful helper array. + */ + public void setRecordData(BlockChangeArray array) { + setRecordData(array.toByteArray()); + } + + /** + * Retrieve a copy of the record data as a block change array. + * @return The copied block change array. + */ + public BlockChangeArray getRecordDataArray() { + return new BlockChangeArray(getRecordData()); + } +} \ No newline at end of file