1
0

Current tablist

Signed-off-by: Lixfel <agga-games@gmx.de>
Dieser Commit ist enthalten in:
Lixfel 2022-06-17 20:43:36 +02:00
Ursprung 9703e9ea33
Commit 598dfcd8a0
4 geänderte Dateien mit 125 neuen und 33 gelöschten Zeilen

Datei anzeigen

@ -19,27 +19,37 @@
package de.steamwar.bungeecore.tablist;
import de.steamwar.bungeecore.sql.SteamwarUser;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import net.md_5.bungee.ServerConnection;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.packet.Team;
import java.util.ArrayList;
import java.util.List;
public class TablistListener extends MessageToMessageDecoder<PacketWrapper> {
//private boolean teamSent = false;
private final ProxiedPlayer player;
private final ServerConnection connection;
public TablistListener(ServerConnection connection) {
public TablistListener(ProxiedPlayer player, ServerConnection connection) {
this.player = player;
this.connection = connection;
player.unsafe().sendPacket(TablistManager.teamPacket);
}
@Override
protected void decode(ChannelHandlerContext ctx, PacketWrapper packetWrapper, List<Object> out) {
//Team
if(!connection.isObsolete()) {
DefinedPacket packet = packetWrapper.packet;
@ -48,17 +58,45 @@ public class TablistListener extends MessageToMessageDecoder<PacketWrapper> {
return;
} else if(packet instanceof PlayerListItem) {
PlayerListItem list = (PlayerListItem) packet;
if(list.getAction() == PlayerListItem.Action.UPDATE_LATENCY || list.getAction() == PlayerListItem.Action.ADD_PLAYER) {
PlayerListItem.Action action = list.getAction();
if(action == PlayerListItem.Action.UPDATE_DISPLAY_NAME || action == PlayerListItem.Action.UPDATE_LATENCY) {
packetWrapper.trySingleRelease();
return;
}
if(action == PlayerListItem.Action.UPDATE_GAMEMODE) {
for (PlayerListItem.Item item : list.getItems()) {
item.setPing(1);
//item.setUsername("AAA");
//item.setDisplayName(ComponentSerializer.toString(TextComponent.fromLegacyText("")));
ProxiedPlayer p = ProxyServer.getInstance().getPlayer(item.getUuid());
if(p != null && p != player && item.getGamemode() == 3) {
item.setGamemode(1);
}
}
}else if(action != PlayerListItem.Action.REMOVE_PLAYER) {
List<String> npcs = new ArrayList<>();
for (PlayerListItem.Item item : list.getItems()) {
ProxiedPlayer p = ProxyServer.getInstance().getPlayer(item.getUuid());
if(p == null) {
item.setPing(1000);
item.setDisplayName(ComponentSerializer.toString(TextComponent.fromLegacyText("")));
npcs.add(item.getUsername());
} else {
item.setPing(1);
item.setDisplayName(ComponentSerializer.toString(TextComponent.fromLegacyText(SteamwarUser.get(p.getUniqueId()).getUserGroup().getColorCode() + p.getName())));
if(p != player && item.getGamemode() == 3) {
item.setGamemode(1);
}
}
}
if(!npcs.isEmpty()) {
Team teamPacket = new Team(TablistManager.TAB_TEAM);
teamPacket.setMode((byte) 3);
teamPacket.setPlayers(npcs.toArray(new String[0]));
player.unsafe().sendPacket(teamPacket);
}
}
}
}
out.add(packetWrapper);
}
}

Datei anzeigen

@ -21,8 +21,11 @@ package de.steamwar.bungeecore.tablist;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.listeners.BasicListener;
import de.steamwar.bungeecore.sql.SteamwarUser;
import de.steamwar.messages.ChatSender;
import net.md_5.bungee.ServerConnection;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
@ -34,20 +37,31 @@ import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.netty.PipelineUtils;
import net.md_5.bungee.protocol.PlayerPublicKey;
import net.md_5.bungee.protocol.Property;
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.packet.Team;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class TablistManager extends BasicListener {
public static final String TAB_TEAM = "»SW-Tab";
private static final Property[] GRAY = new Property[]{new Property("textures", Base64.getEncoder().encodeToString(("{\"textures\":{\"SKIN\":{\"url\":\"https://steamwar.de/gray.png\"}}}").getBytes(StandardCharsets.UTF_8)))};
private static final Property[] LIGHT_GRAY = new Property[]{new Property("textures", Base64.getEncoder().encodeToString(("{\"textures\":{\"SKIN\":{\"url\":\"https://steamwar.de/lightgray.png\"}}}").getBytes(StandardCharsets.UTF_8)))};
private static final UUID[] uuids = IntStream.range(0, 80).mapToObj(i -> UUID.randomUUID()).toArray(UUID[]::new);
private static final String[] names = IntStream.range(0, 80).mapToObj(i -> " »SW« " + i).toArray(String[]::new);
public static final Team teamPacket = new Team(TAB_TEAM, (byte) 0, ComponentSerializer.toString(TextComponent.fromLegacyText("")), ComponentSerializer.toString(TextComponent.fromLegacyText("")), ComponentSerializer.toString(TextComponent.fromLegacyText("")), "never", "never", 21, (byte)0x00, names); // new String[]{}
private final Map<ProxiedPlayer, Tablist> tablists = new HashMap<>();
private int seconds = 0;
public TablistManager() {
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), this::updateTablist, 1, 1, TimeUnit.SECONDS);
ProxyServer.getInstance().getPlayers().forEach(player -> tablists.put(player, new Tablist(player)));
@ -63,7 +77,7 @@ public class TablistManager extends BasicListener {
@EventHandler
public void onServerConnection(ServerSwitchEvent event) {
ServerConnection server = (ServerConnection) event.getPlayer().getServer();
server.getCh().getHandle().pipeline().addBefore(PipelineUtils.BOSS_HANDLER, "steamwar-tablist", new TablistListener(server));
server.getCh().getHandle().pipeline().addBefore(PipelineUtils.BOSS_HANDLER, "steamwar-tablist", new TablistListener(event.getPlayer(), server));
}
@EventHandler
@ -83,12 +97,13 @@ public class TablistManager extends BasicListener {
private void updateTablist() {
synchronized (tablists) {
tablists.forEach((player, tablist) -> tablist.update());
seconds++;
}
}
private static class Tablist {
private class Tablist {
private final ProxiedPlayer player;
private PlayerListItem.Item[] shown = new PlayerListItem.Item[0];
private int shown = 0;
private Tablist(ProxiedPlayer player) {
this.player = player;
@ -98,34 +113,63 @@ public class TablistManager extends BasicListener {
if(player.getServer() == null)
return;
//TODO header & footer
PlayerListItem removePacket = removePacket();
player.unsafe().sendPacket(new PlayerListHeaderFooter(
ComponentSerializer.toString(header(ChatSender.of(player))),
ComponentSerializer.toString(ChatSender.of(player).parse(false, "TABLIST_FOOTER", player.getServer().getInfo().getName(), ping(), ProxyServer.getInstance().getPlayers().size()))
));
PlayerListItem addPacket = new PlayerListItem();
addPacket.setAction(PlayerListItem.Action.ADD_PLAYER);
shown = ProxyServer.getInstance().getServers().entrySet().stream().filter(entry -> entry.getValue() != player.getServer().getInfo()).sorted((e1, e2) -> e1.getKey().compareToIgnoreCase(e2.getKey())).flatMap(entry -> Stream.concat(Stream.of(construct("", "gray"), construct("§7§l" + entry.getKey(), "lightgray")), entry.getValue().getPlayers().stream().map(this::construct))).toArray(PlayerListItem.Item[]::new);
for(int i = 0; i < shown.length; i++) {
shown[i].setUsername("»SW« " + i);
PlayerListItem.Item[] items = ProxyServer.getInstance().getServers().entrySet().stream().filter(entry -> entry.getValue() != player.getServer().getInfo()).sorted((e1, e2) -> e1.getKey().compareToIgnoreCase(e2.getKey())).flatMap(entry -> Stream.concat(Stream.of(construct("", false), construct("§7§l" + entry.getKey(), true)), entry.getValue().getPlayers().stream().map(this::construct))).toArray(PlayerListItem.Item[]::new);
if(items.length > 80) {
items = Arrays.copyOf(items, 80);
}
addPacket.setItems(shown);
for(int i = 0; i < items.length; i++) {
items[i].setUuid(uuids[i]);
items[i].setUsername(names[i]);
}
addPacket.setItems(items);
player.unsafe().sendPacket(removePacket);
if(shown > items.length)
player.unsafe().sendPacket(removePacket(items.length));
shown = items.length;
player.unsafe().sendPacket(addPacket);
//TODO Set direct displaynames for onserver personel (and update correctly)
//TODO Add direct onserver not shown
}
private PlayerListItem.Item construct(String displayName, String color) {
UUID uuid = UUID.randomUUID();
return construct(uuid, null, new Property[]{createSkin(uuid, "»SW«", color)}, null, 1, 1000, displayName);
private BaseComponent[] header(ChatSender p){
int phase = (seconds % 16) / 3;
switch(phase){
case 0:
return p.parse(false, "TABLIST_PHASE_1");
case 1:
return p.parse(false, "TABLIST_PHASE_2");
default:
return p.parse(false, "TABLIST_PHASE_DEFAULT");
}
}
private Property createSkin(UUID uuid, String username, String color) {
// \"timestamp\":0,\"profileId\":\"" + uuid.toString().replace("-", "") + "\",\"profileName\":\"" + username + "\",
return new Property("textures", Base64.getEncoder().encodeToString(("{\"textures\":{\"SKIN\":{\"url\":\"https://steamwar.de/" + color + ".png\"}}}").getBytes(StandardCharsets.UTF_8)));
private String ping() {
int ping = player.getPing();
if(ping < 50){
return "§a" + ping;
}else if(ping < 150){
return "§e" + ping;
}else{
return "§c" + ping;
}
}
private PlayerListItem.Item construct(String displayName, boolean lightgray) {
// TODO lightgray ? LIGHT_GRAY : GRAY
return construct(null, null, new Property[]{}, null, 1, 1000, displayName);
}
private PlayerListItem.Item construct(ProxiedPlayer player) {
return construct(player.getUniqueId(), null, ((InitialHandler)player.getPendingConnection()).getLoginProfile().getProperties(), ((InitialHandler)player.getPendingConnection()).getLoginRequest().getPublicKey(), 1, 1000, player.getDisplayName());
return construct(player.getUniqueId(), null, ((InitialHandler)player.getPendingConnection()).getLoginProfile().getProperties(), ((InitialHandler)player.getPendingConnection()).getLoginRequest().getPublicKey(), 1, 1000, SteamwarUser.get(player.getUniqueId()).getUserGroup().getColorCode() + player.getName());
}
private PlayerListItem.Item construct(UUID uuid, String username, Property[] properties, PlayerPublicKey publicKey, int gamemode, int ping, String displayName) {
@ -140,15 +184,21 @@ public class TablistManager extends BasicListener {
return item;
}
private PlayerListItem removePacket() {
private PlayerListItem.Item construct(UUID uuid) {
PlayerListItem.Item item = new PlayerListItem.Item();
item.setUuid(uuid);
return item;
}
private PlayerListItem removePacket(int newLength) {
PlayerListItem packet = new PlayerListItem();
packet.setAction(PlayerListItem.Action.REMOVE_PLAYER);
packet.setItems(shown);
packet.setItems(IntStream.range(newLength, shown).mapToObj(i -> construct(uuids[i])).toArray(PlayerListItem.Item[]::new));
return packet;
}
private void remove() {
player.unsafe().sendPacket(removePacket());
player.unsafe().sendPacket(removePacket(0));
}
}
}

Datei anzeigen

@ -115,6 +115,10 @@ public interface ChatSender {
return parseToComponent(false, message).toLegacyText();
}
default BaseComponent[] parse(boolean prefixed, String format, Object... params) {
return parse(prefixed, new Message(format, params));
}
default BaseComponent[] parse(boolean prefixed, Message message) {
Locale locale = getLocale();
ResourceBundle resourceBundle = SteamwarResourceBundle.getResourceBundle(locale);

Datei anzeigen

@ -35,7 +35,7 @@ public class SteamwarResourceBundle extends PropertyResourceBundle {
return getResourceBundle(locale.toString(), getResourceBundle(locale.getLanguage(), getResourceBundle( "", null)));
}
private static ResourceBundle getResourceBundle(String locale, ResourceBundle parent) {
private static synchronized ResourceBundle getResourceBundle(String locale, ResourceBundle parent) {
return bundles.computeIfAbsent(locale, locale1 -> {
InputStream inputStream = Message.class.getResourceAsStream(BASE_PATH + ("".equals(locale) ? "" : "_" + locale) + ".properties");
if(inputStream == null)