ProtocolLib

3M Downloads

1.19.2 Scoreboard Team connection closed

NgLoader opened this issue ยท 0 comments

commented
  • This issue is not solved in a development build

Describe the bug
When you try to send the ScoreboardTeam Packet your connection get closed.
I'm using Bungeecord with a Reserve Proxy.
Before updating from 1.18.2 with ProtocolLib version 4.8.* to 1.19.2 and ProtocolLib version 5.0.* everything works fine.

Details
Everything is working in the main thread.

When I skip every Scoreboard Team packet every other packet will be send fine.
I can't see any error, the console is clean and the player client too (in logs).
The packet is send directly after the PlayerJoinEvent was called.

To Reproduce
Steps to reproduce the behavior:

  1. Create a Team packet
  2. Send the Team packet when the play is joining (PlayerJoinEvent)
  3. Get kicked

Expected behavior
Creating a new Team with the provided data

Screenshots
image

Console
UUID of player NilssMiner99 is ca4b6a24-b282-4a7a-b61b-69bf38f1db14
NilssMiner99[/...:*****] logged in with entity id 52 at ([Lobby]599.0, 14.0, 1540.0)
NilssMiner99 lost connection: Disconnected

Version Info
https://paste.es-intern.de/ilucotisib.kotlin
ProtocolLib v5.0.0-SNAPSHOT-b605

Additional context
https://github.com/NgLoader/NPCSystem

NPCSystem Scoreboard Implementation <-- Full Code

Updated ScoreboardProtocol class ($buildTeamPacket method is creating the error packet)

class ScoreboardProtocol {

	//	ClientboundSetDisplayObjectivePacket
	//	ClientboundSetObjectivePacket
	//	ClientboundSetPlayerTeamPacket
	//	ClientboundSetScorePacket

	private static final ProtocolManager PROTOCOL_MANAGER = ProtocolLibrary.getProtocolManager();

	private static final Class<?> NMS_ENUM_CHAT_COLOR = MinecraftReflection.getMinecraftClass("EnumChatFormat");
	private static final Class<?> NMS_RENDER_TYPE = MinecraftReflection.getMinecraftClass("world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay");

	private static int createTeamOptions(SharedTeam team) {
		int mask = 0;
		if (team.isAllowFirendlyFire()) {
			mask |= 1;
		}
		if (team.isCanSeeFriendlyInvisible()) {
			mask |= 2;
		}
		return mask;
	}

	private static InternalStructure createTeamData(PacketContainer packet, SharedTeam team) {
		Optional<InternalStructure> optional = packet.getOptionalStructures().read(0);
		if (optional.isPresent()) {
			InternalStructure structure = optional.get();
			structure.getChatComponents().write(0, team.displayNameWrapped);
			structure.getChatComponents().write(1, team.prefixWrapped);
			structure.getChatComponents().write(2, team.suffixWrapped);
			structure.getStrings().write(0, team.getNameTagVisiblity().getVisibilityName());
			structure.getStrings().write(1, team.getCollisionRule().getCollisionName());
			structure.getEnumModifier(ChatColor.class, NMS_ENUM_CHAT_COLOR).write(0, team.getColor());
			structure.getIntegers().write(0, createTeamOptions(team));
			return structure;
		}
		return null;
	}

	private static PacketContainer buildTeamPacket(SharedTeam team, TeamMethod method, Set<String> entrys) {
		PacketContainer packet = PROTOCOL_MANAGER.createPacket(PacketType.Play.Server.SCOREBOARD_TEAM);
		packet.getStrings().write(0, team.getName());
		packet.getIntegers().write(0, method.ordinal());
		if (method.hasParameters()) {
			packet.getOptionalStructures().write(0, Optional.ofNullable(createTeamData(packet, team)));
		}
		if (method.hasPlayerList()) {
			packet.getSpecificModifier(Collection.class).write(0, entrys != null ? entrys : team.getEntrys());
		}
		return packet;
	}

	private static PacketContainer buildObjectivePacket(SharedObjective objective, ObjectiveMethod method) {
		PacketContainer packet = PROTOCOL_MANAGER.createPacket(PacketType.Play.Server.SCOREBOARD_OBJECTIVE);
		packet.getStrings().write(0, objective.getName());
		packet.getIntegers().write(0, method.ordinal());
		if (method.hasParameters()) {
			packet.getChatComponents().write(0, objective.titleWrapped);
			packet.getEnumModifier(RenderType.class, NMS_RENDER_TYPE).write(0, objective.getRenderType());
		}
		return packet;
	}

	private static PacketContainer buildObjectiveScorePacket(SharedObjectiveScore score, ScoreboardAction action) {
		PacketContainer packet = PROTOCOL_MANAGER.createPacket(PacketType.Play.Server.SCOREBOARD_SCORE);
		packet.getStrings().write(0, score.getName());
		packet.getScoreboardActions().write(0, action);
		packet.getStrings().write(1, score.getObjective().getName());
		if (action != ScoreboardAction.REMOVE) {
			packet.getIntegers().write(0, score.getScore());
		}
		return packet;
	}

	public static PacketContainer addTeamPacket(SharedTeam team) {
		return buildTeamPacket(team, TeamMethod.ADD, null);
	}

	public static PacketContainer changeTeamPacket(SharedTeam team) {
		return buildTeamPacket(team, TeamMethod.CHANGE, null);
	}

	public static PacketContainer joinTeamPacket(SharedTeam team, Set<String> entrys) {
		return buildTeamPacket(team, TeamMethod.JOIN, entrys);
	}

	public static PacketContainer leaveTeamPacket(SharedTeam team, Set<String> entrys) {
		return buildTeamPacket(team, TeamMethod.LEAVE, entrys);
	}

	public static PacketContainer removeTeamPacket(SharedTeam team) {
		return buildTeamPacket(team, TeamMethod.REMOVE, null);
	}

	public static PacketContainer addObjectivePacket(SharedObjective objective) {
		return buildObjectivePacket(objective, ObjectiveMethod.ADD);
	}

	public static PacketContainer changeObjectivePacket(SharedObjective objective) {
		return buildObjectivePacket(objective, ObjectiveMethod.CHANGE);
	}

	public static PacketContainer removeObjectivePacket(SharedObjective objective) {
		return buildObjectivePacket(objective, ObjectiveMethod.REMOVE);
	}

	public static PacketContainer changeObjectiveScorePacket(SharedObjectiveScore score) {
		return buildObjectiveScorePacket(score, ScoreboardAction.CHANGE);
	}

	public static PacketContainer removeObjectiveScorePacket(SharedObjectiveScore score) {
		return buildObjectiveScorePacket(score, ScoreboardAction.REMOVE);
	}

	public static PacketContainer setObjectiveDisplayPacket(SharedObjective objective, DisplaySlot slot) {
		PacketContainer packet = PROTOCOL_MANAGER.createPacket(PacketType.Play.Server.SCOREBOARD_DISPLAY_OBJECTIVE);
		packet.getStrings().write(0, objective == null ? "" : objective.getName());
		packet.getIntegers().write(0, switch (slot) {
		case PLAYER_LIST -> 0;
		case BELOW_NAME -> 2;
		case SIDEBAR -> 1;
		default -> slot.ordinal(); // 3 - 18: team specific sidebar, indexed as 3 + team color. (1.19.2 DisplaySlot is in the right order)
		});
		return packet;
	}

	private enum ObjectiveMethod {
		ADD,
		REMOVE,
		CHANGE;

		public boolean hasParameters() {
			return switch (this.ordinal()) {
			case 0, 2 -> true;
			default -> false;
			};
		}
	}

	private enum TeamMethod {
		ADD,
		REMOVE,
		CHANGE,
		JOIN,
		LEAVE;

		public boolean hasPlayerList() {
			return switch (this.ordinal()) {
			case 0, 3, 4 -> true;
			default -> false;
			};
		}

		public boolean hasParameters() {
			return switch (this.ordinal()) {
			case 0, 2 -> true;
			default -> false;
			};
		}
	}
}

PS: Great work, love this project