diff --git a/src/main/java/us/myles/ViaVersion/ConnectionInfo.java b/src/main/java/us/myles/ViaVersion/ConnectionInfo.java index 35615e1d6..964fcd3c5 100644 --- a/src/main/java/us/myles/ViaVersion/ConnectionInfo.java +++ b/src/main/java/us/myles/ViaVersion/ConnectionInfo.java @@ -1,14 +1,16 @@ package us.myles.ViaVersion; import io.netty.buffer.ByteBuf; -import io.netty.channel.*; +import io.netty.channel.ChannelHandler; import io.netty.channel.socket.SocketChannel; +import lombok.Getter; +import lombok.Setter; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import us.myles.ViaVersion.packets.State; -import java.util.UUID; - +@Getter +@Setter public class ConnectionInfo { private final SocketChannel channel; private Object lastPacket; @@ -17,6 +19,7 @@ public class ConnectionInfo { private String openWindow; private int protocol = 0; private int compression = 0; + private int entityID; private boolean active = true; private String username; @@ -24,89 +27,33 @@ public class ConnectionInfo { this.channel = socketChannel; } - public int getProtocol() { - return protocol; - } - - public void setProtocol(int protocol) { - this.protocol = protocol; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - } - - public int getCompression() { - return compression; - } - - public void setCompression(int compression) { - this.compression = compression; - } - - public Object getLastPacket() { - return lastPacket; - } - - public void setLastPacket(Object lastPacket) { - this.lastPacket = lastPacket; - } - - public java.util.UUID getUUID() { - return UUID; - } - - public void setUUID(UUID UUID) { - this.UUID = UUID; - } - public Player getPlayer() { return UUID == null ? null : Bukkit.getPlayer(UUID); } - public SocketChannel getChannel() { - return channel; - } - - public boolean isActive() { - return active; - } - public void setActive(boolean active) { this.active = active; } - public void sendRawPacket(final ByteBuf packet) { + public void sendRawPacket(final ByteBuf packet, boolean currentThread) { final ChannelHandler handler = channel.pipeline().get("encoder"); - channel.eventLoop().submit(new Runnable() { - @Override - public void run() { - channel.pipeline().context(handler).writeAndFlush(packet); - } - }); + if (currentThread) { + channel.pipeline().context(handler).writeAndFlush(packet); + } else { + channel.eventLoop().submit(new Runnable() { + @Override + public void run() { + channel.pipeline().context(handler).writeAndFlush(packet); + } + }); + } } - public String getOpenWindow() { - return openWindow; - } - - public void setOpenWindow(String openWindow) { - this.openWindow = openWindow; + public void sendRawPacket(final ByteBuf packet) { + sendRawPacket(packet, false); } public void closeWindow() { this.openWindow = null; } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } } diff --git a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java index 10151281a..b888fed87 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java @@ -17,6 +17,7 @@ import java.io.IOException; public class IncomingTransformer { private final ConnectionInfo info; + private boolean startedBlocking = false; public IncomingTransformer(ConnectionInfo info) { this.info = info; @@ -87,6 +88,11 @@ public class IncomingTransformer { } if (packet == PacketType.PLAY_PLAYER_DIGGING) { int status = input.readByte() & 0xFF; // unsign + if (status == 5 && startedBlocking) { + // stopped blocking + startedBlocking = false; + sendSecondHandItem(null); + } if (status == 6) { // item swap throw new CancelException(); } @@ -95,6 +101,13 @@ public class IncomingTransformer { output.writeBytes(input); return; } + if (packet == PacketType.PLAY_HELD_ITEM_CHANGE_REQUEST) { + if (startedBlocking) { + // stopped blocking + startedBlocking = false; + sendSecondHandItem(null); + } + } if (packet == PacketType.PLAY_CLICK_WINDOW) { // if placed in new slot, reject :) int windowID = input.readUnsignedByte(); @@ -268,6 +281,7 @@ public class IncomingTransformer { return; } if (packet == PacketType.PLAY_USE_ITEM) { + int hand = PacketUtil.readVarInt(input); output.clear(); PacketUtil.writeVarInt(PacketType.PLAY_PLAYER_BLOCK_PLACEMENT.getPacketID(), output); // Simulate using item :) @@ -275,6 +289,22 @@ public class IncomingTransformer { output.writeByte(255); // write item in hand ItemStack inHand = ViaVersionPlugin.getHandItem(info); + if (inHand != null) { + if (inHand.getType().name().endsWith("SWORD")) { + // blocking? + if (hand == 0) { + if (!startedBlocking) { + startedBlocking = true; + ItemSlotRewriter.ItemStack shield = new ItemSlotRewriter.ItemStack(); + shield.id = 442; + shield.amount = 1; + shield.data = 0; + sendSecondHandItem(shield); + } + throw new CancelException(); + } + } + } try { ItemSlotRewriter.ItemStack item = ItemSlotRewriter.ItemStack.fromBukkit(inHand); ItemSlotRewriter.fixIdsFrom1_9To1_8(item); @@ -296,4 +326,18 @@ public class IncomingTransformer { } output.writeBytes(input); } + + private void sendSecondHandItem(ItemSlotRewriter.ItemStack o) { + ByteBuf buf = info.getChannel().alloc().buffer(); + PacketUtil.writeVarInt(PacketType.PLAY_ENTITY_EQUIPMENT.getNewPacketID(), buf); + PacketUtil.writeVarInt(info.getEntityID(), buf); + PacketUtil.writeVarInt(1, buf); // slot + // write shield + try { + ItemSlotRewriter.writeItemStack(o, buf); + } catch (IOException e) { + e.printStackTrace(); + } + info.sendRawPacket(buf); + } } diff --git a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java index e3dd9e96e..ea52c2086 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java @@ -1,15 +1,12 @@ 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; 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; @@ -26,8 +23,6 @@ import us.myles.ViaVersion.util.EntityUtil; import us.myles.ViaVersion.util.PacketUtil; import us.myles.ViaVersion.util.ReflectionUtil; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.util.*; @@ -566,6 +561,7 @@ public class OutgoingTransformer { if (packet == PacketType.PLAY_JOIN_GAME) { int id = input.readInt(); clientEntityTypes.put(id, EntityType.PLAYER); + info.setEntityID(id); output.writeInt(id); output.writeBytes(input); return; @@ -683,12 +679,12 @@ public class OutgoingTransformer { CompoundTag spawn = new CompoundTag("SpawnData"); spawn.put(new StringTag("id", entity)); tag.put(spawn); - PacketUtil.writeNBT(output,tag); + PacketUtil.writeNBT(output, tag); } else if (tag != null) { // EntityID does not exist CompoundTag spawn = new CompoundTag("SpawnData"); spawn.put(new StringTag("id", "AreaEffectCloud")); //Make spawners show up as empty when no EntityId is given. tag.put(spawn); - PacketUtil.writeNBT(output,spawn); + PacketUtil.writeNBT(output, spawn); } else { //There doesn't exist any NBT tag input.readerIndex(index); output.writeBytes(input, input.readableBytes()); @@ -798,9 +794,31 @@ public class OutgoingTransformer { return; } List list = MetadataRewriter.readMetadata1_8(type, input); + for (MetadataRewriter.Entry entry : list) { + handleMetadata(entityID, entry, type); + } MetadataRewriter.writeMetadata1_9(type, list, output); } + private void handleMetadata(int entityID, MetadataRewriter.Entry entry, EntityType type) { + // This handles old IDs + if (type == EntityType.PLAYER) { + if (entry.getOldID() == 0) { + // Byte + byte data = (byte) entry.getValue(); + if ((data & 0x10) == 0x10) { + ItemSlotRewriter.ItemStack shield = new ItemSlotRewriter.ItemStack(); + shield.id = 442; + shield.amount = 1; + shield.data = 0; + sendSecondHandItem(entityID, shield); + } else { + sendSecondHandItem(entityID, null); + } + } + } + } + private UUID getUUID(int id) { if (uuidMap.containsKey(id)) { @@ -812,4 +830,18 @@ public class OutgoingTransformer { } } + private void sendSecondHandItem(int entityID, ItemSlotRewriter.ItemStack o) { + + ByteBuf buf = info.getChannel().alloc().buffer(); + PacketUtil.writeVarInt(PacketType.PLAY_ENTITY_EQUIPMENT.getNewPacketID(), buf); + PacketUtil.writeVarInt(entityID, buf); + PacketUtil.writeVarInt(1, buf); // slot + // write shield + try { + ItemSlotRewriter.writeItemStack(o, buf); + } catch (IOException e) { + e.printStackTrace(); + } + info.sendRawPacket(buf, true); + } } \ No newline at end of file