diff --git a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java index c4fd3c515..631767e1d 100644 --- a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java +++ b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java @@ -18,6 +18,7 @@ import us.myles.ViaVersion.api.ViaVersionAPI; import us.myles.ViaVersion.armor.ArmorListener; import us.myles.ViaVersion.commands.ViaVersionCommand; import us.myles.ViaVersion.handlers.ViaVersionInitializer; +import us.myles.ViaVersion.listeners.CommandBlockListener; import us.myles.ViaVersion.util.ReflectionUtil; import java.lang.reflect.Field; @@ -58,6 +59,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { }, this); Bukkit.getPluginManager().registerEvents(new ArmorListener(this), this); + Bukkit.getPluginManager().registerEvents(new CommandBlockListener(this), this); getCommand("viaversion").setExecutor(new ViaVersionCommand(this)); } diff --git a/src/main/java/us/myles/ViaVersion/listeners/CommandBlockListener.java b/src/main/java/us/myles/ViaVersion/listeners/CommandBlockListener.java new file mode 100644 index 000000000..870d6d4f6 --- /dev/null +++ b/src/main/java/us/myles/ViaVersion/listeners/CommandBlockListener.java @@ -0,0 +1,63 @@ +package us.myles.ViaVersion.listeners; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.bukkit.block.Block; +import org.bukkit.block.CommandBlock; +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.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.packets.PacketType; +import us.myles.ViaVersion.util.PacketUtil; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class CommandBlockListener implements Listener { + private final ViaVersionPlugin plugin; + + public CommandBlockListener(ViaVersionPlugin plugin) { + this.plugin = plugin; + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onJoin(final PlayerJoinEvent e) { + if (e.getPlayer().isOp() && plugin.isPorted(e.getPlayer())) { + ByteBuf buf = Unpooled.buffer(); + PacketUtil.writeVarInt(PacketType.PLAY_ENTITY_STATUS.getNewPacketID(), buf); + buf.writeInt(e.getPlayer().getEntityId()); + buf.writeByte(26); + plugin.sendRawPacket(e.getPlayer(), buf); + } + } + + @EventHandler(ignoreCancelled = true) + public void onInteract(PlayerInteractEvent e) { + if (e.getAction() == Action.RIGHT_CLICK_BLOCK && plugin.isPorted(e.getPlayer()) && e.getPlayer().isOp()) { + try { + sendCommandBlockPacket(e.getClickedBlock(), e.getPlayer()); + } catch (NoSuchFieldException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e1) { + e1.printStackTrace(); + } + } + } + + private void sendCommandBlockPacket(Block b, Player player) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException { + if (!(b.getState() instanceof CommandBlock)) + return; + CommandBlock cmd = (CommandBlock) b.getState(); + + Object tileEntityCommand = ReflectionUtil.get(cmd, "commandBlock", ReflectionUtil.nms("TileEntityCommand")); + Object updatePacket = ReflectionUtil.invoke(tileEntityCommand, "getUpdatePacket"); + Object nmsPlayer = ReflectionUtil.invoke(player, "getHandle"); + Object playerConnection = ReflectionUtil.get(nmsPlayer, "playerConnection", ReflectionUtil.nms("PlayerConnection")); + Method sendPacket = playerConnection.getClass().getMethod("sendPacket", ReflectionUtil.nms("Packet")); + sendPacket.invoke(playerConnection, updatePacket); //Let the transformer do the work + } +} diff --git a/src/main/java/us/myles/ViaVersion/metadata/MetaIndex.java b/src/main/java/us/myles/ViaVersion/metadata/MetaIndex.java index 0cc37828b..336afcfd5 100644 --- a/src/main/java/us/myles/ViaVersion/metadata/MetaIndex.java +++ b/src/main/java/us/myles/ViaVersion/metadata/MetaIndex.java @@ -1,6 +1,7 @@ package us.myles.ViaVersion.metadata; import org.bukkit.entity.*; +import org.bukkit.entity.minecart.CommandMinecart; public enum MetaIndex { @@ -105,6 +106,9 @@ public enum MetaIndex { MINECART_BLOCK(Minecart.class, 20, Type.Int, 8, NewType.VarInt), MINECART_BLOCK_Y(Minecart.class, 21, Type.Int, 9, NewType.VarInt), MINECART_SHOWBLOCK(Minecart.class, 22, Type.Byte, 10, NewType.Boolean), + // Command minecart (they are still broken) + MINECART_COMMANDBLOCK_COMMAND(CommandMinecart.class,23,Type.String,11,NewType.String), + MINECART_COMMANDBLOCK_OUTPUT(CommandMinecart.class,24,Type.String,12,NewType.Chat), // furnace cart FURNACECART_ISPOWERED(org.bukkit.entity.minecart.PoweredMinecart.class, 16, Type.Byte, 11, NewType.Boolean), // item drop diff --git a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java index b8070306c..3415e548a 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java @@ -195,6 +195,24 @@ public class IncomingTransformer { e.printStackTrace(); } return; + } else if (name.equals("MC|AutoCmd")) { + ByteBuf in = Unpooled.wrappedBuffer(b); + int x = in.readInt(); + int y = in.readInt(); + int z = in.readInt(); + String command = PacketUtil.readString(in); + boolean flag = in.readBoolean(); + + output.clear(); + PacketUtil.writeVarInt(PacketType.PLAY_PLUGIN_MESSAGE_REQUEST.getPacketID(), output); + PacketUtil.writeString("MC|AdvCdm", output); + output.writeByte(0); + output.writeInt(x); + output.writeInt(y); + output.writeInt(z); + PacketUtil.writeString(command, output); + output.writeBoolean(flag); + return; } output.writeBytes(b); } diff --git a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java index 15a058b6c..3d76e23a5 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java @@ -3,7 +3,6 @@ package us.myles.ViaVersion.transformers; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.ByteBufOutputStream; - import org.bukkit.entity.EntityType; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -11,9 +10,9 @@ import org.json.simple.parser.ParseException; import org.spacehq.mc.protocol.data.game.chunk.Column; import org.spacehq.mc.protocol.util.NetUtil; import org.spacehq.opennbt.NBTIO; +import org.spacehq.opennbt.tag.builtin.ByteTag; import org.spacehq.opennbt.tag.builtin.CompoundTag; import org.spacehq.opennbt.tag.builtin.StringTag; - import us.myles.ViaVersion.CancelException; import us.myles.ViaVersion.ConnectionInfo; import us.myles.ViaVersion.ViaVersionPlugin; @@ -86,10 +85,10 @@ public class OutgoingTransformer { output.writeBytes(input); } if (packet == PacketType.PLAY_EFFECT) { - int effectid = input.readInt(); - if(effectid >= 1000 && effectid < 2000) //Sound effect - throw new CancelException(); - output.writeInt(effectid); + int effectid = input.readInt(); + if (effectid >= 1000 && effectid < 2000) //Sound effect + throw new CancelException(); + output.writeInt(effectid); } if (packet == PacketType.PLAY_ATTACH_ENTITY) { int passenger = input.readInt(); @@ -564,29 +563,43 @@ public class OutgoingTransformer { return; } if (packet == PacketType.PLAY_UPDATE_BLOCK_ENTITY) { - long[] pos = PacketUtil.readBlockPosition(input); - int action = input.readUnsignedByte(); - if(action == 1) { // update spawner - try { - DataInputStream stream = new DataInputStream(new ByteBufInputStream(input)); - CompoundTag tag = (CompoundTag) NBTIO.readTag(stream); - String entity = (String) tag.get("EntityId").getValue(); - CompoundTag spawn = new CompoundTag("SpawnData"); - spawn.put(new StringTag("id", entity)); - tag.put(spawn); - PacketUtil.writeBlockPosition(output, pos[0], pos[1], pos[2]); - output.writeByte(action); - DataOutputStream out = new DataOutputStream(new ByteBufOutputStream(output)); - NBTIO.writeTag(out, tag); - } catch (IOException e) { - e.printStackTrace(); - } - return; - } - PacketUtil.writeBlockPosition(output, pos[0], pos[1], pos[2]); - output.writeByte(action); - output.writeBytes(input, input.readableBytes()); - return; + long[] pos = PacketUtil.readBlockPosition(input); + PacketUtil.writeBlockPosition(output, pos[0], pos[1], pos[2]); + int action = input.readUnsignedByte(); + output.writeByte(action); + if (action == 1) { // update spawner + try { + DataInputStream stream = new DataInputStream(new ByteBufInputStream(input)); + CompoundTag tag = (CompoundTag) NBTIO.readTag(stream); + String entity = (String) tag.get("EntityId").getValue(); + CompoundTag spawn = new CompoundTag("SpawnData"); + spawn.put(new StringTag("id", entity)); + tag.put(spawn); + DataOutputStream out = new DataOutputStream(new ByteBufOutputStream(output)); + NBTIO.writeTag(out, tag); + } catch (IOException e) { + e.printStackTrace(); + } + return; + } + if (action == 2) { //Update commandblock + try { + CompoundTag nbt = readNBT(input); + if (nbt == null) + throw new CancelException(); + //Thanks http://www.minecraftforum.net/forums/minecraft-discussion/redstone-discussion-and/command-blocks/2488148-1-9-nbt-changes-and-additions#TileAllCommandBlocks + nbt.put(new ByteTag("powered", (byte) 0)); + nbt.put(new ByteTag("auto", (byte) 0)); + nbt.put(new ByteTag("conditionMet", (byte) 0)); + writeNBT(output, nbt); + return; + } catch (IOException e) { + e.printStackTrace(); + throw new CancelException(); + } + } + output.writeBytes(input, input.readableBytes()); + return; } if (packet == PacketType.PLAY_CHUNK_DATA) { // We need to catch unloading chunk packets as defined by wiki.vg