Added support for 1.8.x and 1.12.2 clients (#87)

* Added support for 1.12.2 players

* Added support for 1.8.x & fixed code style

* Moved VersionManager inside ScoreboardManager

* Code refactor

* Update src/main/java/net/william278/velocitab/packet/UpdateTeamsPacket.java

Co-authored-by: William <will27528@gmail.com>

* Update src/main/java/net/william278/velocitab/packet/UpdateTeamsPacket.java

Co-authored-by: William <will27528@gmail.com>

* Update src/main/java/net/william278/velocitab/packet/ProtocolAbstractAdapter.java

Co-authored-by: William <will27528@gmail.com>

* Added requested changes

* Code refactoring

---------

Co-authored-by: William <will27528@gmail.com>
This commit is contained in:
AlexDev_ 2023-09-12 16:30:55 +02:00 committed by GitHub
parent 1544e302b2
commit 8d654d6b26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 396 additions and 57 deletions

View File

@ -0,0 +1,89 @@
/*
* This file is part of Velocitab, licensed under the Apache License 2.0.
*
* Copyright (c) William278 <will27528@gmail.com>
* Copyright (c) contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.william278.velocitab.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@SuppressWarnings("DuplicatedCode")
public class Protocol340Adapter extends TeamsPacketAdapter {
public Protocol340Adapter() {
super(Set.of(ProtocolVersion.MINECRAFT_1_12_2));
}
@Override
public void decode(ByteBuf byteBuf, UpdateTeamsPacket updateTeamsPacket) {
updateTeamsPacket.teamName(ProtocolUtils.readString(byteBuf));
UpdateTeamsPacket.UpdateMode mode = UpdateTeamsPacket.UpdateMode.byId(byteBuf.readByte());
if (mode == UpdateTeamsPacket.UpdateMode.REMOVE_TEAM) {
return;
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.UPDATE_INFO) {
updateTeamsPacket.displayName(ProtocolUtils.readString(byteBuf));
updateTeamsPacket.prefix(ProtocolUtils.readString(byteBuf));
updateTeamsPacket.suffix(ProtocolUtils.readString(byteBuf));
updateTeamsPacket.friendlyFlags(UpdateTeamsPacket.FriendlyFlag.fromBitMask(byteBuf.readByte()));
updateTeamsPacket.nameTagVisibility(UpdateTeamsPacket.NameTagVisibility.byId(ProtocolUtils.readString(byteBuf)));
updateTeamsPacket.collisionRule(UpdateTeamsPacket.CollisionRule.byId(ProtocolUtils.readString(byteBuf)));
updateTeamsPacket.color(byteBuf.readByte());
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.ADD_PLAYERS || mode == UpdateTeamsPacket.UpdateMode.REMOVE_PLAYERS) {
int entityCount = ProtocolUtils.readVarInt(byteBuf);
List<String> entities = new ArrayList<>(entityCount);
for (int j = 0; j < entityCount; j++) {
entities.add(ProtocolUtils.readString(byteBuf));
}
updateTeamsPacket.entities(entities);
}
}
@Override
public void encode(ByteBuf byteBuf, UpdateTeamsPacket updateTeamsPacket) {
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.teamName().substring(0, Math.min(updateTeamsPacket.teamName().length(), 16)));
UpdateTeamsPacket.UpdateMode mode = updateTeamsPacket.mode();
byteBuf.writeByte(mode.id());
if (mode == UpdateTeamsPacket.UpdateMode.REMOVE_TEAM) {
return;
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.UPDATE_INFO) {
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.displayName());
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.prefix());
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.suffix());
byteBuf.writeByte(UpdateTeamsPacket.FriendlyFlag.toBitMask(updateTeamsPacket.friendlyFlags()));
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.nameTagVisibility().id());
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.collisionRule().id());
byteBuf.writeByte(updateTeamsPacket.color());
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.ADD_PLAYERS || mode == UpdateTeamsPacket.UpdateMode.REMOVE_PLAYERS) {
List<String> entities = updateTeamsPacket.entities();
ProtocolUtils.writeVarInt(byteBuf, entities != null ? entities.size() : 0);
for (String entity : entities != null ? entities : new ArrayList<String>()) {
ProtocolUtils.writeString(byteBuf, entity);
}
}
}
}

View File

@ -0,0 +1,97 @@
/*
* This file is part of Velocitab, licensed under the Apache License 2.0.
*
* Copyright (c) William278 <will27528@gmail.com>
* Copyright (c) contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.william278.velocitab.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@SuppressWarnings("DuplicatedCode")
public class Protocol403Adapter extends TeamsPacketAdapter {
public Protocol403Adapter() {
super(Set.of(ProtocolVersion.MINECRAFT_1_13_2,
ProtocolVersion.MINECRAFT_1_14_4,
ProtocolVersion.MINECRAFT_1_15_2,
ProtocolVersion.MINECRAFT_1_16_4,
ProtocolVersion.MINECRAFT_1_17_1,
ProtocolVersion.MINECRAFT_1_18_2,
ProtocolVersion.MINECRAFT_1_19_4,
ProtocolVersion.MINECRAFT_1_20
));
}
@Override
public void decode(ByteBuf byteBuf, UpdateTeamsPacket updateTeamsPacket) {
updateTeamsPacket.teamName(ProtocolUtils.readString(byteBuf));
UpdateTeamsPacket.UpdateMode mode = UpdateTeamsPacket.UpdateMode.byId(byteBuf.readByte());
if (mode == UpdateTeamsPacket.UpdateMode.REMOVE_TEAM) {
return;
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.UPDATE_INFO) {
updateTeamsPacket.displayName(ProtocolUtils.readString(byteBuf));
updateTeamsPacket.friendlyFlags(UpdateTeamsPacket.FriendlyFlag.fromBitMask(byteBuf.readByte()));
updateTeamsPacket.nameTagVisibility(UpdateTeamsPacket.NameTagVisibility.byId(ProtocolUtils.readString(byteBuf)));
updateTeamsPacket.collisionRule(UpdateTeamsPacket.CollisionRule.byId(ProtocolUtils.readString(byteBuf)));
updateTeamsPacket.color(byteBuf.readByte());
updateTeamsPacket.prefix(ProtocolUtils.readString(byteBuf));
updateTeamsPacket.suffix(ProtocolUtils.readString(byteBuf));
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.ADD_PLAYERS || mode == UpdateTeamsPacket.UpdateMode.REMOVE_PLAYERS) {
int entityCount = ProtocolUtils.readVarInt(byteBuf);
List<String> entities = new ArrayList<>(entityCount);
for (int j = 0; j < entityCount; j++) {
entities.add(ProtocolUtils.readString(byteBuf));
}
updateTeamsPacket.entities(entities);
}
}
@Override
public void encode(ByteBuf byteBuf, UpdateTeamsPacket updateTeamsPacket) {
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.teamName());
UpdateTeamsPacket.UpdateMode mode = updateTeamsPacket.mode();
byteBuf.writeByte(mode.id());
if (mode == UpdateTeamsPacket.UpdateMode.REMOVE_TEAM) {
return;
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.UPDATE_INFO) {
ProtocolUtils.writeString(byteBuf, getChatString(updateTeamsPacket.displayName()));
byteBuf.writeByte(UpdateTeamsPacket.FriendlyFlag.toBitMask(updateTeamsPacket.friendlyFlags()));
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.nameTagVisibility().id());
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.collisionRule().id());
byteBuf.writeByte(updateTeamsPacket.color());
ProtocolUtils.writeString(byteBuf, getChatString(updateTeamsPacket.prefix()));
ProtocolUtils.writeString(byteBuf, getChatString(updateTeamsPacket.suffix()));
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.ADD_PLAYERS || mode == UpdateTeamsPacket.UpdateMode.REMOVE_PLAYERS) {
List<String> entities = updateTeamsPacket.entities();
ProtocolUtils.writeVarInt(byteBuf, entities != null ? entities.size() : 0);
for (String entity : entities != null ? entities : new ArrayList<String>()) {
ProtocolUtils.writeString(byteBuf, entity);
}
}
}
}

View File

@ -0,0 +1,87 @@
/*
* This file is part of Velocitab, licensed under the Apache License 2.0.
*
* Copyright (c) William278 <will27528@gmail.com>
* Copyright (c) contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.william278.velocitab.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@SuppressWarnings("DuplicatedCode")
public class Protocol48Adapter extends TeamsPacketAdapter {
public Protocol48Adapter() {
super(Set.of(ProtocolVersion.MINECRAFT_1_8));
}
@Override
public void decode(ByteBuf byteBuf, UpdateTeamsPacket updateTeamsPacket) {
updateTeamsPacket.teamName(ProtocolUtils.readString(byteBuf));
UpdateTeamsPacket.UpdateMode mode = UpdateTeamsPacket.UpdateMode.byId(byteBuf.readByte());
if (mode == UpdateTeamsPacket.UpdateMode.REMOVE_TEAM) {
return;
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.UPDATE_INFO) {
updateTeamsPacket.displayName(ProtocolUtils.readString(byteBuf));
updateTeamsPacket.prefix(ProtocolUtils.readString(byteBuf));
updateTeamsPacket.suffix(ProtocolUtils.readString(byteBuf));
updateTeamsPacket.friendlyFlags(UpdateTeamsPacket.FriendlyFlag.fromBitMask(byteBuf.readByte()));
updateTeamsPacket.nameTagVisibility(UpdateTeamsPacket.NameTagVisibility.byId(ProtocolUtils.readString(byteBuf)));
updateTeamsPacket.color(byteBuf.readByte());
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.ADD_PLAYERS || mode == UpdateTeamsPacket.UpdateMode.REMOVE_PLAYERS) {
int entityCount = ProtocolUtils.readVarInt(byteBuf);
List<String> entities = new ArrayList<>(entityCount);
for (int j = 0; j < entityCount; j++) {
entities.add(ProtocolUtils.readString(byteBuf));
}
updateTeamsPacket.entities(entities);
}
}
@Override
public void encode(ByteBuf byteBuf, UpdateTeamsPacket updateTeamsPacket) {
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.teamName().substring(0, Math.min(updateTeamsPacket.teamName().length(), 16)));
UpdateTeamsPacket.UpdateMode mode = updateTeamsPacket.mode();
byteBuf.writeByte(mode.id());
if (mode == UpdateTeamsPacket.UpdateMode.REMOVE_TEAM) {
return;
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.UPDATE_INFO) {
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.displayName());
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.prefix());
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.suffix());
byteBuf.writeByte(UpdateTeamsPacket.FriendlyFlag.toBitMask(updateTeamsPacket.friendlyFlags()));
ProtocolUtils.writeString(byteBuf, updateTeamsPacket.nameTagVisibility().id());
byteBuf.writeByte(updateTeamsPacket.color());
}
if (mode == UpdateTeamsPacket.UpdateMode.CREATE_TEAM || mode == UpdateTeamsPacket.UpdateMode.ADD_PLAYERS || mode == UpdateTeamsPacket.UpdateMode.REMOVE_PLAYERS) {
List<String> entities = updateTeamsPacket.entities();
ProtocolUtils.writeVarInt(byteBuf, entities != null ? entities.size() : 0);
for (String entity : entities != null ? entities : new ArrayList<String>()) {
ProtocolUtils.writeString(byteBuf, entity);
}
}
}
}

View File

@ -19,6 +19,7 @@
package net.william278.velocitab.packet; package net.william278.velocitab.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
@ -38,11 +39,31 @@ public class ScoreboardManager {
private final Velocitab plugin; private final Velocitab plugin;
private final Map<UUID, List<String>> createdTeams; private final Map<UUID, List<String>> createdTeams;
private final Map<UUID, Map<String, String>> roleMappings; private final Map<UUID, Map<String, String>> roleMappings;
private final Set<TeamsPacketAdapter> versions;
public ScoreboardManager(@NotNull Velocitab velocitab) { public ScoreboardManager(@NotNull Velocitab velocitab) {
this.plugin = velocitab; this.plugin = velocitab;
this.createdTeams = new HashMap<>(); this.createdTeams = new HashMap<>();
this.roleMappings = new HashMap<>(); this.roleMappings = new HashMap<>();
this.versions = new HashSet<>();
this.registerVersions();
}
private void registerVersions() {
versions.add(new Protocol403Adapter());
versions.add(new Protocol340Adapter());
versions.add(new Protocol48Adapter());
}
public TeamsPacketAdapter getPacketAdapter(ProtocolVersion protocolVersion) {
return versions.stream()
.filter(version -> version.getProtocolVersions().contains(protocolVersion))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No version found for protocol version " + protocolVersion));
}
public void sendProtocolError(String message) {
plugin.log(Level.ERROR, message);
} }
public void resetCache(@NotNull Player player) { public void resetCache(@NotNull Player player) {
@ -69,7 +90,7 @@ public class ScoreboardManager {
return; return;
} }
if (!createdTeams.getOrDefault(player.getUniqueId(), List.of()).contains(role)) { if (!createdTeams.getOrDefault(player.getUniqueId(), List.of()).contains(role)) {
dispatchPacket(UpdateTeamsPacket.create(role, playerNames), player); dispatchPacket(UpdateTeamsPacket.create(plugin, role, playerNames), player);
createdTeams.computeIfAbsent(player.getUniqueId(), k -> new ArrayList<>()).add(role); createdTeams.computeIfAbsent(player.getUniqueId(), k -> new ArrayList<>()).add(role);
roleMappings.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).put(player.getUsername(), role); roleMappings.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).put(player.getUsername(), role);
} else { } else {
@ -77,8 +98,8 @@ public class ScoreboardManager {
.entrySet().stream() .entrySet().stream()
.filter((entry) -> List.of(playerNames).contains(entry.getKey())) .filter((entry) -> List.of(playerNames).contains(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
.forEach((playerName, oldRole) -> dispatchPacket(UpdateTeamsPacket.removeFromTeam(oldRole, playerName), player)); .forEach((playerName, oldRole) -> dispatchPacket(UpdateTeamsPacket.removeFromTeam(plugin, oldRole, playerName), player));
dispatchPacket(UpdateTeamsPacket.addToTeam(role, playerNames), player); dispatchPacket(UpdateTeamsPacket.addToTeam(plugin, role, playerNames), player);
roleMappings.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).put(player.getUsername(), role); roleMappings.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).put(player.getUsername(), role);
} }
} }
@ -101,8 +122,10 @@ public class ScoreboardManager {
try { try {
packetRegistration = PacketRegistration.of(UpdateTeamsPacket.class) packetRegistration = PacketRegistration.of(UpdateTeamsPacket.class)
.direction(ProtocolUtils.Direction.CLIENTBOUND) .direction(ProtocolUtils.Direction.CLIENTBOUND)
.packetSupplier(UpdateTeamsPacket::new) .packetSupplier(() -> new UpdateTeamsPacket(plugin))
.stateRegistry(StateRegistry.PLAY) .stateRegistry(StateRegistry.PLAY)
.mapping(0x3E, MINECRAFT_1_8, false)
.mapping(0x44, MINECRAFT_1_12_2, false)
.mapping(0x47, MINECRAFT_1_13, false) .mapping(0x47, MINECRAFT_1_13, false)
.mapping(0x4B, MINECRAFT_1_14, false) .mapping(0x4B, MINECRAFT_1_14, false)
.mapping(0x4C, MINECRAFT_1_15, false) .mapping(0x4C, MINECRAFT_1_15, false)
@ -117,7 +140,7 @@ public class ScoreboardManager {
} }
public void unregisterPacket() { public void unregisterPacket() {
if(packetRegistration==null) { if (packetRegistration == null) {
return; return;
} }
try { try {

View File

@ -0,0 +1,48 @@
/*
* This file is part of Velocitab, licensed under the Apache License 2.0.
*
* Copyright (c) William278 <will27528@gmail.com>
* Copyright (c) contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.william278.velocitab.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.text.StringEscapeUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
@Getter
@RequiredArgsConstructor
public abstract class TeamsPacketAdapter {
private final Set<ProtocolVersion> protocolVersions;
public abstract void decode(ByteBuf byteBuf, UpdateTeamsPacket updateTeamsPacket);
public abstract void encode(ByteBuf byteBuf, UpdateTeamsPacket updateTeamsPacket);
@NotNull
protected String getChatString(@NotNull String string) {
return String.format("{\"text\":\"%s\"}", StringEscapeUtils.escapeJson(string));
}
}

View File

@ -26,24 +26,25 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.apache.commons.text.StringEscapeUtils; import net.william278.velocitab.Velocitab;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Getter @Getter
@Setter @Setter
@ToString @ToString
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@Accessors(fluent = true) @Accessors(fluent = true)
public class UpdateTeamsPacket implements MinecraftPacket { public class UpdateTeamsPacket implements MinecraftPacket {
private final Velocitab plugin;
private String teamName; private String teamName;
private UpdateMode mode; private UpdateMode mode;
private String displayName; private String displayName;
@ -55,89 +56,77 @@ public class UpdateTeamsPacket implements MinecraftPacket {
private String suffix; private String suffix;
private List<String> entities; private List<String> entities;
public UpdateTeamsPacket(Velocitab plugin) {
this.plugin = plugin;
}
@NotNull @NotNull
protected static UpdateTeamsPacket create(@NotNull String teamName, @NotNull String... teamMembers) { protected static UpdateTeamsPacket create(@NotNull Velocitab plugin, @NotNull String teamName, @NotNull String... teamMembers) {
return new UpdateTeamsPacket() return new UpdateTeamsPacket(plugin)
.teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName) .teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName)
.mode(UpdateMode.CREATE_TEAM) .mode(UpdateMode.CREATE_TEAM)
.displayName(getChatString(teamName)) .displayName(teamName)
.friendlyFlags(List.of(FriendlyFlag.CAN_HURT_FRIENDLY)) .friendlyFlags(List.of(FriendlyFlag.CAN_HURT_FRIENDLY))
.nameTagVisibility(NameTagVisibility.ALWAYS) .nameTagVisibility(NameTagVisibility.ALWAYS)
.collisionRule(CollisionRule.ALWAYS) .collisionRule(CollisionRule.ALWAYS)
.color(15) .color(15)
.prefix(getChatString("")) .prefix("")
.suffix(getChatString("")) .suffix("")
.entities(Arrays.asList(teamMembers)); .entities(Arrays.asList(teamMembers));
} }
@NotNull @NotNull
protected static UpdateTeamsPacket addToTeam(@NotNull String teamName, @NotNull String... teamMembers) { protected static UpdateTeamsPacket addToTeam(@NotNull Velocitab plugin, @NotNull String teamName, @NotNull String... teamMembers) {
return new UpdateTeamsPacket() return new UpdateTeamsPacket(plugin)
.teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName) .teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName)
.mode(UpdateMode.ADD_PLAYERS) .mode(UpdateMode.ADD_PLAYERS)
.entities(Arrays.asList(teamMembers)); .entities(Arrays.asList(teamMembers));
} }
@NotNull @NotNull
protected static UpdateTeamsPacket removeFromTeam(@NotNull String teamName, @NotNull String... teamMembers) { protected static UpdateTeamsPacket removeFromTeam(@NotNull Velocitab plugin, @NotNull String teamName, @NotNull String... teamMembers) {
return new UpdateTeamsPacket() return new UpdateTeamsPacket(plugin)
.teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName) .teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName)
.mode(UpdateMode.REMOVE_PLAYERS) .mode(UpdateMode.REMOVE_PLAYERS)
.entities(Arrays.asList(teamMembers)); .entities(Arrays.asList(teamMembers));
} }
@NotNull
private static String getChatString(@NotNull String string) {
return "{\"text\":\"" + StringEscapeUtils.escapeJson(string) + "\"}";
}
@Override @Override
public void decode(ByteBuf byteBuf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { public void decode(ByteBuf byteBuf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) {
teamName = ProtocolUtils.readString(byteBuf); Optional<ScoreboardManager> scoreboardManagerOptional = plugin.getScoreboardManager();
mode = UpdateMode.byId(byteBuf.readByte());
if (mode == UpdateMode.REMOVE_TEAM) { if (scoreboardManagerOptional.isEmpty()) {
return; return;
} }
if (mode == UpdateMode.CREATE_TEAM || mode == UpdateMode.UPDATE_INFO) {
displayName = ProtocolUtils.readString(byteBuf); ScoreboardManager scoreboardManager = scoreboardManagerOptional.get();
friendlyFlags = FriendlyFlag.fromBitMask(byteBuf.readByte());
nameTagVisibility = NameTagVisibility.byId(ProtocolUtils.readString(byteBuf)); if (mode == null) {
collisionRule = CollisionRule.byId(ProtocolUtils.readString(byteBuf)); scoreboardManager.sendProtocolError("Something went wrong while decoding a UpdateTeamsPacket" +
color = byteBuf.readByte(); ", if your server is on 1.8.x and you are using ViaVersion," +
prefix = ProtocolUtils.readString(byteBuf); ", please disable 'auto-team' in the config.yml and reload it.");
suffix = ProtocolUtils.readString(byteBuf);
}
if (mode == UpdateMode.CREATE_TEAM || mode == UpdateMode.ADD_PLAYERS || mode == UpdateMode.REMOVE_PLAYERS) {
int entityCount = ProtocolUtils.readVarInt(byteBuf);
entities = new ArrayList<>(entityCount);
for (int j = 0; j < entityCount; j++) {
entities.add(ProtocolUtils.readString(byteBuf));
}
} }
scoreboardManager.getPacketAdapter(protocolVersion).decode(byteBuf, this);
} }
@Override @Override
public void encode(ByteBuf byteBuf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { public void encode(ByteBuf byteBuf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) {
ProtocolUtils.writeString(byteBuf, teamName); Optional<ScoreboardManager> scoreboardManagerOptional = plugin.getScoreboardManager();
byteBuf.writeByte(mode.id());
if (mode == UpdateMode.REMOVE_TEAM) { if (scoreboardManagerOptional.isEmpty()) {
return; return;
} }
if (mode == UpdateMode.CREATE_TEAM || mode == UpdateMode.UPDATE_INFO) {
ProtocolUtils.writeString(byteBuf, displayName); ScoreboardManager scoreboardManager = scoreboardManagerOptional.get();
byteBuf.writeByte(FriendlyFlag.toBitMask(friendlyFlags));
ProtocolUtils.writeString(byteBuf, nameTagVisibility.id()); if (mode == null) {
ProtocolUtils.writeString(byteBuf, collisionRule.id()); scoreboardManager.sendProtocolError("Something went wrong while encoding a UpdateTeamsPacket" +
byteBuf.writeByte(color); ", if your server is on 1.8.x and you are using ViaVersion," +
ProtocolUtils.writeString(byteBuf, prefix); ", please disable 'auto-team' in the config.yml and reload it.");
ProtocolUtils.writeString(byteBuf, suffix);
}
if (mode == UpdateMode.CREATE_TEAM || mode == UpdateMode.ADD_PLAYERS || mode == UpdateMode.REMOVE_PLAYERS) {
ProtocolUtils.writeVarInt(byteBuf, entities != null ? entities.size() : 0);
for (String entity : entities != null ? entities : new ArrayList<String>()) {
ProtocolUtils.writeString(byteBuf, entity);
}
} }
scoreboardManager.getPacketAdapter(protocolVersion).encode(byteBuf, this);
} }
@Override @Override

View File

@ -67,6 +67,7 @@ public class PlayerTabList {
final Player joined = event.getPlayer(); final Player joined = event.getPlayer();
plugin.getScoreboardManager().ifPresent(manager -> manager.resetCache(joined)); plugin.getScoreboardManager().ifPresent(manager -> manager.resetCache(joined));
// Remove the player from the tracking list if they are switching servers // Remove the player from the tracking list if they are switching servers
final RegisteredServer previousServer = event.getPreviousServer(); final RegisteredServer previousServer = event.getPreviousServer();
if (previousServer == null) { if (previousServer == null) {
@ -90,6 +91,8 @@ public class PlayerTabList {
final TabPlayer tabPlayer = plugin.getTabPlayer(joined); final TabPlayer tabPlayer = plugin.getTabPlayer(joined);
players.add(tabPlayer); players.add(tabPlayer);
// Update lists // Update lists
plugin.getServer().getScheduler() plugin.getServer().getScheduler()
.buildTask(plugin, () -> { .buildTask(plugin, () -> {
@ -111,9 +114,12 @@ public class PlayerTabList {
() -> createEntry(player, tabList).thenAccept(tabList::addEntry) () -> createEntry(player, tabList).thenAccept(tabList::addEntry)
); );
addPlayerToTabList(player, tabPlayer); addPlayerToTabList(player, tabPlayer);
player.sendHeaderAndFooter(this); player.sendHeaderAndFooter(this);
} }
plugin.getScoreboardManager().ifPresent(manager -> manager.setRoles(joined, playerRoles)); plugin.getScoreboardManager().ifPresent(manager -> manager.setRoles(joined, playerRoles));
}) })
.delay(500, TimeUnit.MILLISECONDS) .delay(500, TimeUnit.MILLISECONDS)