Track the players selected slot index with PacketPlayInHeldItemChange,

and allow changing of a players selected slot with
PacketPlayOutHeldItemChange.

Also introduces an event that can be used to change or cancel a player's
selected slot change.

I tried to follow the style and mannerisms of existing code, but what's
up with the Unsafe class? The class is okay, but why are the methods
named as such? Having all the methods named 'a' will be sure to cause
conflict once two methods take the same parameters.
This commit is contained in:
James Puleo 2021-02-22 01:29:46 -05:00
parent 48cd3a8b9a
commit 3f60ffd1ef
8 changed files with 134 additions and 6 deletions

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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));
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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",