ProtocolLib

3M Downloads

Still errors with 1.19.3 supporting version !?

Jeppa opened this issue ยท 14 comments

commented
  • This issue is not solved in a development build

With latest build #607 the bug with "java.lang.IllegalArgumentException: Could not find packet for type PLAYER_INFO" was fixed.
But i still can't use it, as there is the next issue :(

java.lang.IllegalStateException: Unable to set value of field private final java.util.EnumSet net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket.a
at com.comphenix.protocol.reflect.accessors.DefaultFieldAccessor.set(DefaultFieldAccessor.java:42) ~[ProtocolLib(B607__MC1.19.3).jar:?]
at com.comphenix.protocol.reflect.StructureModifier.writeInternal(StructureModifier.java:332) ~[ProtocolLib(B607__MC1.19.3).jar:?]
at com.comphenix.protocol.reflect.StructureModifier.writeSafely(StructureModifier.java:308) ~[ProtocolLib(B607__MC1.19.3).jar:?]
...[Code from my plugin here]...
at org.bukkit.craftbukkit.v1_19_R2.scheduler.CraftTask.run(CraftTask.java:101) ~[paper-1.19.3.jar:git-Paper-319]
at org.bukkit.craftbukkit.v1_19_R2.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:483) ~[paper-1.19.3.jar:git-Paper-319]
at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1473) ~[paper-1.19.3.jar:git-Paper-319]
at net.minecraft.server.dedicated.DedicatedServer.tickChildren(DedicatedServer.java:440) ~[paper-1.19.3.jar:git-Paper-319]
at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1397) ~[paper-1.19.3.jar:git-Paper-319]
at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1173) ~[paper-1.19.3.jar:git-Paper-319]
at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:316) ~[paper-1.19.3.jar:git-Paper-319]
at java.lang.Thread.run(Unknown Source) ~[?:?]
Caused by: java.lang.ClassCastException: Cannot cast java.util.ArrayList to java.util.EnumSet
at java.lang.Class.cast(Unknown Source) ~[?:?]
at com.comphenix.protocol.reflect.accessors.DefaultFieldAccessor.set(DefaultFieldAccessor.java:39) ~[ProtocolLib(B607__MC1.19.3).jar:?]`

This error happens when i call:
PacketContainer.getPlayerInfoDataLists().write(0, Collections.singletonList(playerInfoData))
where playerInfoData is : new PlayerInfoData(wrappedGameprofile, 0, NativeGameMode.fromBukkit(gameMode), WrappedChatComponent.fromText(entityName))

When i try to debug this,
PacketContainer.getPlayerInfoDataLists().getField(0).getType()
tells me it is an EnumSet ...

Is this a bug, or has the API changed somehow ????

commented

I still have the problem, that trying to send a PLAYER_INFO Packet causes out of bounds for me

com.comphenix.protocol.reflect.FieldAccessException: Field index 0 is out of bounds for length 0
at com.comphenix.protocol.reflect.FieldAccessException.fromFormat(FieldAccessException.java:49)
at com.comphenix.protocol.reflect.StructureModifier.write(StructureModifier.java:289)
at me.wasn325.coreapi.core.packets.WrapperPlayServerPlayerInfo.setAction(WrapperPlayServerPlayerInfo.java:27)

The Wrapper is built up like chasertw123's example (only difference: I have getPlayerInfoAction() and not getPlayerInfoActions(), don't know why) and fails at trying to set the action

commented

Or maybe something is wrong here?

WrapperPlayServerPlayerInfo packet = new WrapperPlayServerPlayerInfo();
packet.setAction(EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME);
...
commented

You use WrapperPlayServerPlayerInfo from PacketWrapper?
It seems that the latest changes in ProtocolLib have made it incompatible to that ...

commented

Do you know any alternatives instead?

commented

I was able to get it to work with this:
PacketContainer.getPlayerInfoDataLists().write(1, value)

Not sure that is intended but it works for now.

commented

Thanks, thats what i've just seen in the testcode, too.
But what data must go into field 0 (the EnumSet) then ??

commented

I believe in this case field 0 is the PlayerInfoAction EnumSet. Here is the packet wrapper I wrote for it.

public class WrapperPlayServerPlayerInfo extends AbstractPacket {

    public static final PacketType TYPE = PacketType.Play.Server.PLAYER_INFO;

    public WrapperPlayServerPlayerInfo() {
        super(new PacketContainer(TYPE), TYPE);
        handle.getModifier().writeDefaults();
    }

    public WrapperPlayServerPlayerInfo(PacketContainer packet) {
        super(packet, TYPE);
    }

    public Set<PlayerInfoAction> getAction() {
        return handle.getPlayerInfoActions().read(0);
    }

    public void setAction(Set<PlayerInfoAction> value) {
        handle.getPlayerInfoActions().write(0, value);
    }

    public List<PlayerInfoData> getData() {
        return handle.getPlayerInfoDataLists().read(1);
    }

    public void setData(List<PlayerInfoData> value) {
        handle.getPlayerInfoDataLists().write(1, value);
    }
}
commented

I think that is an error of ProtocolLib because getPlayerInfoDataLists matches all collections and not just lists.

commented

I still don't know if this is a bug, or an API change...
But since we have kinda solution for it, i close this.

commented

getPlayerInfoActions() is needed as Mojang changed it from a single action to a list of actions.

commented
public class WrapperPlayServerPlayerInfo extends AbstractPacket {
	public static final PacketType TYPE = PacketType.Play.Server.PLAYER_INFO;

	public WrapperPlayServerPlayerInfo() {
		super(new PacketContainer(TYPE), TYPE);
		handle.getModifier().writeDefaults();
	}

	public WrapperPlayServerPlayerInfo(PacketContainer packet) {
		super(packet, TYPE);
	}

	public Set<PlayerInfoAction> getAction() {
		return handle.getPlayerInfoActions().read(0);
	}

	public void setAction(Set<PlayerInfoAction> value) {
		handle.getPlayerInfoActions().write(0, value);
	}

	public List<PlayerInfoData> getData() {
		return handle.getPlayerInfoDataLists().read(1);
	}

	public void setData(List<PlayerInfoData> value) {
		handle.getPlayerInfoDataLists().write(1, value);
	}
}

I managed to get it working using this. To construct the list of PlayerActions:
packet.setAction(EnumSet.of(PlayerInfoAction.ADD_PLAYER, PlayerInfoAction.UPDATE_DISPLAY_NAME, PlayerInfoAction.INITIALIZE_CHAT, PlayerInfoAction.UPDATE_LISTED, PlayerInfoAction.UPDATE_GAME_MODE, PlayerInfoAction.UPDATE_LATENCY));

and the big thing that I just spent like 15 hours discovering is that they changed the way PlayerInfo works, since PlayerInfoAction.REMOVE_PLAYER is now deprecated and doesn't work in 1.19.3 I learned that you have to send PacketType.Play.Server.PLAYER_INFO_REMOVE in order to remove the player now. According to the wiki it should be expecting a list of UUIDs to remove, however I haven't been able to get it working so for the time being I'm just directly using NMS:
ServerPlayer sp = ((CraftPlayer)player).getHandle(); sp.connection.send(new ClientboundPlayerInfoRemovePacket(Arrays.asList(player.getUniqueId())));

If anyone is able to get the PLAYER_INFO_REMOVE working please do let me know :)

commented

This works for me (PLAYER_INFO_REMOVE)

`

    PacketContainer packet = new PacketContainer(PacketType.Play.Server.PLAYER_INFO_REMOVE);
    packet.getModifier().writeDefaults();

    packet.getLists(new EquivalentConverter<UUID>() {
        @Override
        public Object getGeneric(UUID uuid) {
            return uuid;
        }

        @Override
        public UUID getSpecific(Object o) {
            return (UUID) o;
        }

        @Override
        public Class<UUID> getSpecificType() {
            return UUID.class;
        }
    }).write(0, listOfPlayerUUIDsToDespawn);  // where listOfPlayerUUIDsToDespawn is a List<UUID>

`

commented

Found a shorter way:

remove.getModifier().withType(List.class).write(0, Arrays.asList(uuid));
protocolManager.sendServerPacket(player, remove);
commented

For all those who are running in problem with the PLAYER_INFO packet you can check an example in the tests or in this code of my API

Also, for the PLAYER_INFO_REMOVE, you can use the shorter way of getting the UUID list PacketContainer#getLists(Converters.passthrough(UUID.class)) as described in #2048
Here's a example

If you're planning to adding backward compatibility you can use a utility class for checking if the version is at least 1.19.3:

public class VersionUtil {

    private static final MinecraftVersion tablistBreakingChange = MinecraftVersion.fromServerVersion("3632-Spigot-d90018e-d67777f (MC: 1.19.3)");

    public static boolean isNewTablist() {
        return ProtocolLibrary.getProtocolManager().getMinecraftVersion().isAtLeast(tablistBreakingChange);
    }
}