Still errors with 1.19.3 supporting version !?
Jeppa opened this issue ยท 14 comments
- 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 ????
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
Or maybe something is wrong here?
WrapperPlayServerPlayerInfo packet = new WrapperPlayServerPlayerInfo();
packet.setAction(EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME);
...
You use WrapperPlayServerPlayerInfo from PacketWrapper?
It seems that the latest changes in ProtocolLib have made it incompatible to that ...
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.
Thanks, thats what i've just seen in the testcode, too.
But what data must go into field 0 (the EnumSet) then ??
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);
}
}
I think that is an error of ProtocolLib because getPlayerInfoDataLists matches all collections and not just lists.
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.
getPlayerInfoActions() is needed as Mojang changed it from a single action to a list of actions.
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 :)
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>
`
Found a shorter way:
remove.getModifier().withType(List.class).write(0, Arrays.asList(uuid));
protocolManager.sendServerPacket(player, remove);
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);
}
}