diff --git a/src/main/java/com/loohp/limbo/Events/PlayerSelectedSlotChangeEvent.java b/src/main/java/com/loohp/limbo/Events/PlayerSelectedSlotChangeEvent.java new file mode 100644 index 0000000..a1003cf --- /dev/null +++ b/src/main/java/com/loohp/limbo/Events/PlayerSelectedSlotChangeEvent.java @@ -0,0 +1,32 @@ +package com.loohp.limbo.Events; + +import com.loohp.limbo.Player.Player; + +public class PlayerSelectedSlotChangeEvent extends PlayerEvent implements Cancellable { + + private boolean cancel = false; + private byte slot; + + public PlayerSelectedSlotChangeEvent(Player player, byte slot) { + super(player); + this.slot = slot; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancel = cancelled; + } + + @Override + public boolean isCancelled() { + return cancel; + } + + public byte getSlot() { + return slot; + } + + public void setSlot(byte slot) { + this.slot = slot; + } +} diff --git a/src/main/java/com/loohp/limbo/Player/Player.java b/src/main/java/com/loohp/limbo/Player/Player.java index 2fd109e..cd832ea 100644 --- a/src/main/java/com/loohp/limbo/Player/Player.java +++ b/src/main/java/com/loohp/limbo/Player/Player.java @@ -18,6 +18,7 @@ import com.loohp.limbo.Server.Packets.PacketPlayOutChat; import com.loohp.limbo.Server.Packets.PacketPlayOutGameState; import com.loohp.limbo.Server.Packets.PacketPlayOutPositionAndLook; import com.loohp.limbo.Server.Packets.PacketPlayOutRespawn; +import com.loohp.limbo.Server.Packets.PacketPlayOutHeldItemChange; import com.loohp.limbo.Utils.GameMode; import net.md_5.bungee.api.chat.BaseComponent; @@ -32,6 +33,7 @@ public class Player extends LivingEntity implements CommandSender { protected final String username; protected GameMode gamemode; protected DataWatcher watcher; + protected byte selectedSlot; @WatchableField(MetadataIndex = 14, WatchableObjectType = WatchableObjectType.FLOAT) protected float additionalHearts = 0.0F; @@ -56,7 +58,23 @@ public class Player extends LivingEntity implements CommandSender { this.watcher = new DataWatcher(this); this.watcher.update(); } - + + public byte getSelectedSlot() { + return selectedSlot; + } + + public void setSelectedSlot(byte slot) { + if(slot == selectedSlot) + return; + try { + PacketPlayOutHeldItemChange state = new PacketPlayOutHeldItemChange(slot); + clientConnection.sendPacket(state); + } catch (IOException e) { + e.printStackTrace(); + } + this.selectedSlot = slot; + } + public GameMode getGamemode() { return gamemode; } diff --git a/src/main/java/com/loohp/limbo/Player/Unsafe.java b/src/main/java/com/loohp/limbo/Player/Unsafe.java index b6864eb..f51f7c7 100644 --- a/src/main/java/com/loohp/limbo/Player/Unsafe.java +++ b/src/main/java/com/loohp/limbo/Player/Unsafe.java @@ -22,5 +22,10 @@ public class Unsafe { public void a(Player a, Location b) { a.setLocation(b); } - + + @Deprecated + public void a(Player a, byte b) { + a.selectedSlot = b; + } + } diff --git a/src/main/java/com/loohp/limbo/Server/ClientConnection.java b/src/main/java/com/loohp/limbo/Server/ClientConnection.java index 5a57259..89e8690 100644 --- a/src/main/java/com/loohp/limbo/Server/ClientConnection.java +++ b/src/main/java/com/loohp/limbo/Server/ClientConnection.java @@ -23,6 +23,7 @@ import com.loohp.limbo.Events.PlayerLoginEvent; import com.loohp.limbo.Events.PlayerMoveEvent; import com.loohp.limbo.Events.PlayerQuitEvent; import com.loohp.limbo.Events.StatusPingEvent; +import com.loohp.limbo.Events.PlayerSelectedSlotChangeEvent; import com.loohp.limbo.File.ServerProperties; import com.loohp.limbo.Location.Location; import com.loohp.limbo.Player.Player; @@ -58,6 +59,8 @@ import com.loohp.limbo.Server.Packets.PacketStatusInPing; import com.loohp.limbo.Server.Packets.PacketStatusInRequest; import com.loohp.limbo.Server.Packets.PacketStatusOutPong; import com.loohp.limbo.Server.Packets.PacketStatusOutResponse; +import com.loohp.limbo.Server.Packets.PacketPlayInHeldItemChange; +import com.loohp.limbo.Server.Packets.PacketPlayOutHeldItemChange; import com.loohp.limbo.Utils.CustomStringUtils; import com.loohp.limbo.Utils.DataTypeIO; import com.loohp.limbo.Utils.GameMode; @@ -427,6 +430,19 @@ public class ClientConnection extends Thread { } else { player.chat(chat.getMessage()); } + } else if(packetType.equals(PacketPlayInHeldItemChange.class)) { + PacketPlayInHeldItemChange change = new PacketPlayInHeldItemChange(input); + PlayerSelectedSlotChangeEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerSelectedSlotChangeEvent(player, (byte)change.getSlot())); + if(event.isCancelled()) { + PacketPlayOutHeldItemChange cancelPacket = new PacketPlayOutHeldItemChange(player.getSelectedSlot()); + sendPacket(cancelPacket); + } else if(change.getSlot() != event.getSlot()) { + PacketPlayOutHeldItemChange changePacket = new PacketPlayOutHeldItemChange(event.getSlot()); + sendPacket(changePacket); + Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot()); + } else { + Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot()); + } } else { input.skipBytes(size - DataTypeIO.getVarIntLength(packetId)); } diff --git a/src/main/java/com/loohp/limbo/Server/Packets/PacketPlayInHeldItemChange.java b/src/main/java/com/loohp/limbo/Server/Packets/PacketPlayInHeldItemChange.java new file mode 100644 index 0000000..dc414c9 --- /dev/null +++ b/src/main/java/com/loohp/limbo/Server/Packets/PacketPlayInHeldItemChange.java @@ -0,0 +1,21 @@ +package com.loohp.limbo.Server.Packets; + +import java.io.DataInputStream; +import java.io.IOException; + +public class PacketPlayInHeldItemChange extends PacketIn { + + private final short slot; + + public PacketPlayInHeldItemChange(short slot) { + this.slot = slot; + } + + public PacketPlayInHeldItemChange(DataInputStream in) throws IOException { + this(in.readShort()); + } + + public short getSlot() { + return slot; + } +} diff --git a/src/main/java/com/loohp/limbo/Server/Packets/PacketPlayOutHeldItemChange.java b/src/main/java/com/loohp/limbo/Server/Packets/PacketPlayOutHeldItemChange.java new file mode 100644 index 0000000..337ae43 --- /dev/null +++ b/src/main/java/com/loohp/limbo/Server/Packets/PacketPlayOutHeldItemChange.java @@ -0,0 +1,29 @@ +package com.loohp.limbo.Server.Packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class PacketPlayOutHeldItemChange extends PacketOut { + + private final byte slot; + + public PacketPlayOutHeldItemChange(byte slot) { + this.slot = slot; + } + + public byte getSlot() { + return slot; + } + + @Override + public byte[] serializePacket() throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + DataOutputStream output = new DataOutputStream(buffer); + output.writeByte(Packet.getPlayOut().get(getClass())); + output.writeByte(slot); + + return buffer.toByteArray(); + } +} diff --git a/src/main/java/com/loohp/limbo/Unsafe.java b/src/main/java/com/loohp/limbo/Unsafe.java index 28638c4..8317eca 100644 --- a/src/main/java/com/loohp/limbo/Unsafe.java +++ b/src/main/java/com/loohp/limbo/Unsafe.java @@ -28,12 +28,17 @@ public class Unsafe { worldConstructor.setAccessible(false); } catch (Exception e) {e.printStackTrace();} } - + @Deprecated public void setPlayerGameModeSilently(Player player, GameMode mode) { playerUnsafe.a(player, mode); } - + + @Deprecated + public void setSelectedSlotSilently(Player player, byte slot) { + playerUnsafe.a(player, slot); + } + @Deprecated public void setPlayerEntityId(Player player, int entityId) { playerUnsafe.a(player, entityId); diff --git a/src/main/resources/mapping.json b/src/main/resources/mapping.json index ca0afcf..5c2b71f 100644 --- a/src/main/resources/mapping.json +++ b/src/main/resources/mapping.json @@ -18,7 +18,8 @@ "0x12": "PacketPlayInPosition", "0x14": "PacketPlayInRotation", "0x0B": "PacketPlayInPluginMessaging", - "0x06": "PacketPlayInTabComplete" + "0x06": "PacketPlayInTabComplete", + "0x25": "PacketPlayInHeldItemChange" }, "PlayOut": { "PacketPlayOutLogin": "0x24", @@ -41,7 +42,8 @@ "PacketPlayOutEntityDestroy": "0x36", "PacketPlayOutEntityMetadata": "0x44", "PacketPlayOutSpawnEntity": "0x00", - "PacketPlayOutSpawnEntityLiving": "0x02" + "PacketPlayOutSpawnEntityLiving": "0x02", + "PacketPlayOutHeldItemChange": "0x3F" }, "StatusIn": { "0x01": "PacketStatusInPing",