Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 107 additions & 14 deletions api/src/main/java/me/tofaa/entitylib/meta/types/PlayerMeta.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package me.tofaa.entitylib.meta.types;

import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.manager.server.VersionComparison;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.meta.Metadata;
import org.jetbrains.annotations.Nullable;

public class PlayerMeta extends LivingEntityMeta {
public class PlayerMeta extends LivingEntityMeta {

public static final byte OFFSET = LivingEntityMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public static final byte MAX_OFFSET = OFFSET + 6;

private static final byte AVATAR_MAIN_HAND_INDEX = OFFSET;
private static final byte AVATAR_SKIN_LAYERS_INDEX = (byte) (OFFSET + 1);

private static final byte PLAYER_ADDITIONAL_HEARTS_INDEX = (byte) (OFFSET + 2);
private static final byte PLAYER_SCORE_INDEX = (byte) (OFFSET + 3);
private static final byte PLAYER_LEFT_SHOULDER_INDEX = (byte) (OFFSET + 4);
private static final byte PLAYER_RIGHT_SHOULDER_INDEX = (byte) (OFFSET + 5);

private final static byte CAPE_BIT = 0x01;
private final static byte JACKET_BIT = 0x02;
Expand All @@ -25,123 +34,207 @@ public PlayerMeta(int entityId, Metadata metadata) {
}

public float getAdditionalHearts() {
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return super.metadata.getIndex(PLAYER_ADDITIONAL_HEARTS_INDEX, 0F);
}
return super.metadata.getIndex(OFFSET, 0F);
}

public void setAdditionalHearts(float value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.FLOAT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
super.metadata.setIndex(PLAYER_ADDITIONAL_HEARTS_INDEX, EntityDataTypes.FLOAT, value);
} else {
super.metadata.setIndex(OFFSET, EntityDataTypes.FLOAT, value);
}
}

public int getScore() {
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return super.metadata.getIndex(PLAYER_SCORE_INDEX, 0);
}
return super.metadata.getIndex(offset(OFFSET,1), 0);
}

public void setScore(int value) {
super.metadata.setIndex(offset(OFFSET,1), EntityDataTypes.INT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
super.metadata.setIndex(PLAYER_SCORE_INDEX, EntityDataTypes.INT, value);
} else {
super.metadata.setIndex(offset(OFFSET,1), EntityDataTypes.INT, value);
}
}

public boolean isCapeEnabled() {
isVersionNewer(ServerVersion.V_1_9);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return getMaskBit(AVATAR_SKIN_LAYERS_INDEX, CAPE_BIT);
}
return getMaskBit(offset(OFFSET,2), CAPE_BIT);
}

public void setCapeEnabled(boolean value) {
isVersionNewer(ServerVersion.V_1_9);
setMaskBit(offset(OFFSET,2), CAPE_BIT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
setMaskBit(AVATAR_SKIN_LAYERS_INDEX, CAPE_BIT, value);
} else {
setMaskBit(offset(OFFSET,2), CAPE_BIT, value);
}
}

public boolean isJacketEnabled() {
isVersionNewer(ServerVersion.V_1_9);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return getMaskBit(AVATAR_SKIN_LAYERS_INDEX, JACKET_BIT);
}
return getMaskBit(offset(OFFSET,2), JACKET_BIT);
}

public void setJacketEnabled(boolean value) {
isVersionNewer(ServerVersion.V_1_9);
setMaskBit(offset(OFFSET,2), JACKET_BIT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
setMaskBit(AVATAR_SKIN_LAYERS_INDEX, JACKET_BIT, value);
} else {
setMaskBit(offset(OFFSET,2), JACKET_BIT, value);
}
}

public boolean isLeftSleeveEnabled() {
isVersionNewer(ServerVersion.V_1_9);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return getMaskBit(AVATAR_SKIN_LAYERS_INDEX, LEFT_SLEEVE_BIT);
}
return getMaskBit(offset(OFFSET,2), LEFT_SLEEVE_BIT);
}

public void setLeftSleeveEnabled(boolean value) {
isVersionNewer(ServerVersion.V_1_9);
setMaskBit(offset(OFFSET,2), LEFT_SLEEVE_BIT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
setMaskBit(AVATAR_SKIN_LAYERS_INDEX, LEFT_SLEEVE_BIT, value);
} else {
setMaskBit(offset(OFFSET,2), LEFT_SLEEVE_BIT, value);
}
}

public boolean isRightSleeveEnabled() {
isVersionNewer(ServerVersion.V_1_9);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return getMaskBit(AVATAR_SKIN_LAYERS_INDEX, RIGHT_SLEEVE_BIT);
}
return getMaskBit(offset(OFFSET,2), RIGHT_SLEEVE_BIT);
}

public void setRightSleeveEnabled(boolean value) {
isVersionNewer(ServerVersion.V_1_9);
setMaskBit(offset(OFFSET,2), RIGHT_SLEEVE_BIT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
setMaskBit(AVATAR_SKIN_LAYERS_INDEX, RIGHT_SLEEVE_BIT, value);
} else {
setMaskBit(offset(OFFSET,2), RIGHT_SLEEVE_BIT, value);
}
}

public boolean isLeftLegEnabled() {
isVersionNewer(ServerVersion.V_1_9);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return getMaskBit(AVATAR_SKIN_LAYERS_INDEX, LEFT_LEG_BIT);
}
return getMaskBit(offset(OFFSET,2), LEFT_LEG_BIT);
}

public void setLeftLegEnabled(boolean value) {
isVersionNewer(ServerVersion.V_1_9);
setMaskBit(offset(OFFSET,2), LEFT_LEG_BIT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
setMaskBit(AVATAR_SKIN_LAYERS_INDEX, LEFT_LEG_BIT, value);
} else {
setMaskBit(offset(OFFSET,2), LEFT_LEG_BIT, value);
}
}

public boolean isRightLegEnabled() {
isVersionNewer(ServerVersion.V_1_9);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return getMaskBit(AVATAR_SKIN_LAYERS_INDEX, RIGHT_LEG_BIT);
}
return getMaskBit(offset(OFFSET,2), RIGHT_LEG_BIT);
}

public void setRightLegEnabled(boolean value) {
isVersionNewer(ServerVersion.V_1_9);
setMaskBit(offset(OFFSET,2), RIGHT_LEG_BIT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
setMaskBit(AVATAR_SKIN_LAYERS_INDEX, RIGHT_LEG_BIT, value);
} else {
setMaskBit(offset(OFFSET,2), RIGHT_LEG_BIT, value);
}
}

public boolean isHatEnabled() {
isVersionNewer(ServerVersion.V_1_9);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return getMaskBit(AVATAR_SKIN_LAYERS_INDEX, HAT_BIT);
}
return getMaskBit(offset(OFFSET,2), HAT_BIT);
}

public void setHatEnabled(boolean value) {
isVersionNewer(ServerVersion.V_1_9);
setMaskBit(offset(OFFSET,2), HAT_BIT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
setMaskBit(AVATAR_SKIN_LAYERS_INDEX, HAT_BIT, value);
} else {
setMaskBit(offset(OFFSET,2), HAT_BIT, value);
}
}

public boolean isRightHandMain() {
if (EntityLib.getApi().getPacketEvents().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_9)) {
return true;
}
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return super.metadata.getIndex(AVATAR_MAIN_HAND_INDEX, (byte) 1) == (byte) 1;
}
return super.metadata.getIndex(offset(OFFSET,3), (byte) 1) == (byte) 1;
}

public void setRightHandMain(boolean value) {
if (EntityLib.getApi().getPacketEvents().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_9)) {
return;
}
super.metadata.setIndex(offset(OFFSET,3), EntityDataTypes.BYTE, (byte) (value ? 1 : 0));
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
super.metadata.setIndex(AVATAR_MAIN_HAND_INDEX, EntityDataTypes.BYTE, (byte) (value ? 1 : 0));
} else {
super.metadata.setIndex(offset(OFFSET,3), EntityDataTypes.BYTE, (byte) (value ? 1 : 0));
}
}

public @Nullable NBTCompound getLeftShoulderData() {
isVersionNewer(ServerVersion.V_1_11);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return super.metadata.getIndex(PLAYER_LEFT_SHOULDER_INDEX, null);
}
return super.metadata.getIndex(offset(OFFSET,4), null);
}

public void setLeftShoulderData(@Nullable NBTCompound value) {
if (value == null) value = new NBTCompound();
super.metadata.setIndex(offset(OFFSET,4), EntityDataTypes.NBT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
super.metadata.setIndex(PLAYER_LEFT_SHOULDER_INDEX, EntityDataTypes.NBT, value);
} else {
super.metadata.setIndex(offset(OFFSET,4), EntityDataTypes.NBT, value);
}
}
Comment on lines 214 to 221
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing version check in setter.

The getter getLeftShoulderData() has isVersionNewer(ServerVersion.V_1_11) at line 207, but the setter is missing this guard. This could cause invalid metadata to be set on servers older than V_1_11.

Proposed fix
 public void setLeftShoulderData(`@Nullable` NBTCompound value) {
+    isVersionNewer(ServerVersion.V_1_11);
     if (value == null) value = new NBTCompound();
     if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
🤖 Prompt for AI Agents
In `@api/src/main/java/me/tofaa/entitylib/meta/types/PlayerMeta.java` around lines
214 - 221, The setter setLeftShoulderData is missing the same version guard used
by getLeftShoulderData; add an early check using
isVersionNewer(ServerVersion.V_1_11) at the top of setLeftShoulderData and skip
(return) when the server version is older than V_1_11 so metadata isn't written
on unsupported versions, keeping the existing logic that chooses between
PLAYER_LEFT_SHOULDER_INDEX and offset(OFFSET,4) intact.


public @Nullable NBTCompound getRightShoulderData() {
isVersionNewer(ServerVersion.V_1_11);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
return super.metadata.getIndex(PLAYER_RIGHT_SHOULDER_INDEX, null);
}
return super.metadata.getIndex(offset(OFFSET,5), null);
}

public void setRightShoulderData(@Nullable NBTCompound value) {
if (value == null) value = new NBTCompound();
super.metadata.setIndex(offset(OFFSET,5), EntityDataTypes.NBT, value);
if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
super.metadata.setIndex(PLAYER_RIGHT_SHOULDER_INDEX, EntityDataTypes.NBT, value);
} else {
super.metadata.setIndex(offset(OFFSET,5), EntityDataTypes.NBT, value);
}
}
Comment on lines 231 to 238
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing version check in setter.

Same issue as setLeftShoulderData — the getter at line 224 has isVersionNewer(ServerVersion.V_1_11), but the setter is missing this guard.

Proposed fix
 public void setRightShoulderData(`@Nullable` NBTCompound value) {
+    isVersionNewer(ServerVersion.V_1_11);
     if (value == null) value = new NBTCompound();
     if (isVersion(ServerVersion.V_1_21_10, VersionComparison.NEWER_THAN_OR_EQUALS)) {
🤖 Prompt for AI Agents
In `@api/src/main/java/me/tofaa/entitylib/meta/types/PlayerMeta.java` around lines
231 - 238, The setter setRightShoulderData is missing the same version guard
used in the getter; update setRightShoulderData to check
isVersionNewer(ServerVersion.V_1_11) (like setLeftShoulderData does) and only
use PLAYER_RIGHT_SHOULDER_INDEX when that check passes, otherwise fall back to
using offset(OFFSET, 5) as before; keep the NBTCompound defaulting logic and the
super.metadata.setIndex(EntityDataTypes.NBT, value) calls intact.


}
Loading