Skip to content

Commit 82430e3

Browse files
authored
Merge pull request #76 from steveb05/fix/equipment-slot-bounds
fix(api): keep every equipment slot inside the array and off old clients
2 parents 9ab4d19 + 093f5fc commit 82430e3

2 files changed

Lines changed: 54 additions & 20 deletions

File tree

api/src/main/java/me/tofaa/entitylib/extras/VersionChecker.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
package me.tofaa.entitylib.extras;
22

33
import com.github.retrooper.packetevents.manager.server.ServerVersion;
4-
import me.tofaa.entitylib.EntityLib;
4+
import me.tofaa.entitylib.utils.VersionUtil;
55

66
public final class VersionChecker {
77

88
private VersionChecker() {}
99

1010

11+
/**
12+
* Throws when the running server is older than the version a feature needs.
13+
*
14+
* @param version the oldest server version the feature works on
15+
* @param message the message of the thrown exception
16+
*/
1117
public static void verifyVersion(ServerVersion version, String message) {
12-
if (!version.isNewerThanOrEquals(EntityLib.getApi().getPacketEvents().getServerManager().getVersion())) {
18+
if (VersionUtil.isOlderThan(version)) {
1319
throw new InvalidVersionException(message);
1420
}
1521
}

api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntityEquipment.java

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.github.retrooper.packetevents.protocol.player.Equipment;
66
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
77
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEquipment;
8+
import me.tofaa.entitylib.EntityLib;
89
import org.jetbrains.annotations.NotNull;
910
import org.jetbrains.annotations.Nullable;
1011

@@ -21,8 +22,7 @@ public class WrapperEntityEquipment {
2122
private final WrapperLivingEntity entity;
2223
private boolean notifyChanges = true;
2324

24-
// 0 = main hand, 1 = offhand, 2 = boots, 3 = leggings, 4 = chestplate, 5 = helmet
25-
private final ItemStack[] equipment = new ItemStack[6];
25+
private final ItemStack[] equipment = new ItemStack[EQUIPMENT_SLOTS.length];
2626

2727
public WrapperEntityEquipment(WrapperLivingEntity entity) {
2828
this.entity = entity;
@@ -41,37 +41,31 @@ public void clearAll() {
4141
}
4242

4343
public void setHelmet(@Nullable ItemStack itemStack) {
44-
equipment[5] = itemStack == null ? ItemStack.EMPTY : itemStack;
45-
refresh();
44+
setItem(EquipmentSlot.HELMET, itemStack);
4645
}
4746

4847
public void setChestplate(@Nullable ItemStack itemStack) {
49-
equipment[4] = itemStack == null ? ItemStack.EMPTY : itemStack;
50-
refresh();
48+
setItem(EquipmentSlot.CHEST_PLATE, itemStack);
5149
}
5250

5351
public void setLeggings(@Nullable ItemStack itemStack) {
54-
equipment[3] = itemStack == null ? ItemStack.EMPTY : itemStack;
55-
refresh();
52+
setItem(EquipmentSlot.LEGGINGS, itemStack);
5653
}
5754

5855
public void setBoots(@Nullable ItemStack itemStack) {
59-
equipment[2] = itemStack == null ? ItemStack.EMPTY : itemStack;
60-
refresh();
56+
setItem(EquipmentSlot.BOOTS, itemStack);
6157
}
6258

6359
public void setMainHand(@Nullable ItemStack itemStack) {
64-
equipment[0] = itemStack == null ? ItemStack.EMPTY : itemStack;
65-
refresh();
60+
setItem(EquipmentSlot.MAIN_HAND, itemStack);
6661
}
6762

6863
public void setOffhand(@Nullable ItemStack itemStack) {
69-
equipment[1] = itemStack == null ? ItemStack.EMPTY : itemStack;
70-
refresh();
64+
setItem(EquipmentSlot.OFF_HAND, itemStack);
7165
}
7266

7367
public void setItem(@NotNull EquipmentSlot slot, @Nullable ItemStack itemStack) {
74-
equipment[slot.ordinal()] = itemStack == null ? ItemStack.EMPTY : itemStack;
68+
equipment[slot.ordinal()] = itemStack == null ? ItemStack.EMPTY : itemStack;
7569
refresh();
7670
}
7771

@@ -108,11 +102,45 @@ public void setItem(@NotNull EquipmentSlot slot, @Nullable ItemStack itemStack)
108102
return getItem(EquipmentSlot.OFF_HAND);
109103
}
110104

105+
/**
106+
* Whether the running server version knows the given equipment slot.
107+
*
108+
* @param slot the slot to check
109+
* @return true when the slot can be sent to a client of the server version
110+
*/
111+
public static boolean isSlotSupported(@NotNull EquipmentSlot slot) {
112+
return isSlotSupported(slot, EntityLib.getApi().getPacketEvents().getServerManager().getVersion());
113+
}
114+
115+
/**
116+
* Whether the given server version knows the given equipment slot.
117+
* A slot travels in the equipment packet as its ordinal, so a slot that the version does not
118+
* have yet has no number a client of that version could map back to it.
119+
*
120+
* @param slot the slot to check
121+
* @param version the server version to check the slot against
122+
* @return true when the slot can be sent to a client of that version
123+
*/
124+
public static boolean isSlotSupported(@NotNull EquipmentSlot slot, @NotNull ServerVersion version) {
125+
switch (slot) {
126+
case OFF_HAND:
127+
return version.isNewerThanOrEquals(ServerVersion.V_1_9);
128+
case BODY:
129+
return version.isNewerThanOrEquals(ServerVersion.V_1_20_5);
130+
case SADDLE:
131+
return version.isNewerThanOrEquals(ServerVersion.V_1_21_5);
132+
default:
133+
return true;
134+
}
135+
}
136+
111137
public WrapperPlayServerEntityEquipment createPacket() {
112-
List<Equipment> equipment = new ArrayList<>();
138+
ServerVersion version = EntityLib.getApi().getPacketEvents().getServerManager().getVersion();
139+
List<Equipment> equipment = new ArrayList<>(this.equipment.length);
113140
for (int i = 0; i < this.equipment.length; i++) {
114-
ItemStack itemStack = this.equipment[i];
115-
equipment.add(new Equipment(EQUIPMENT_SLOTS[i], itemStack));
141+
EquipmentSlot slot = EQUIPMENT_SLOTS[i];
142+
if (!isSlotSupported(slot, version)) continue;
143+
equipment.add(new Equipment(slot, this.equipment[i]));
116144
}
117145
return new WrapperPlayServerEntityEquipment(
118146
entity.getEntityId(),

0 commit comments

Comments
 (0)