Merge pull request 'Tablist' (#411) from tablist into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #411 Reviewed-by: Chaoscaot <chaoscaot444@gmail.com>
Dieser Commit ist enthalten in:
Commit
129e41cb77
@ -27,6 +27,7 @@ import de.steamwar.bungeecore.listeners.mods.*;
|
|||||||
import de.steamwar.bungeecore.network.BungeeNetworkHandler;
|
import de.steamwar.bungeecore.network.BungeeNetworkHandler;
|
||||||
import de.steamwar.bungeecore.network.NetworkReceiver;
|
import de.steamwar.bungeecore.network.NetworkReceiver;
|
||||||
import de.steamwar.bungeecore.sql.*;
|
import de.steamwar.bungeecore.sql.*;
|
||||||
|
import de.steamwar.bungeecore.tablist.TablistManager;
|
||||||
import de.steamwar.command.SWCommandUtils;
|
import de.steamwar.command.SWCommandUtils;
|
||||||
import de.steamwar.command.SWTypeMapperCreator;
|
import de.steamwar.command.SWTypeMapperCreator;
|
||||||
import de.steamwar.command.TypeMapper;
|
import de.steamwar.command.TypeMapper;
|
||||||
@ -68,6 +69,7 @@ public class BungeeCore extends Plugin {
|
|||||||
public static final Map<String, String> commands = new HashMap<>();
|
public static final Map<String, String> commands = new HashMap<>();
|
||||||
|
|
||||||
private ErrorLogger errorLogger;
|
private ErrorLogger errorLogger;
|
||||||
|
private TablistManager tablistManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable(){
|
public void onEnable(){
|
||||||
@ -175,7 +177,7 @@ public class BungeeCore extends Plugin {
|
|||||||
new SessionManager();
|
new SessionManager();
|
||||||
new NetworkReceiver();
|
new NetworkReceiver();
|
||||||
BungeeNetworkHandler.register();
|
BungeeNetworkHandler.register();
|
||||||
new TablistManager();
|
tablistManager = new TablistManager();
|
||||||
new SettingsChangedListener();
|
new SettingsChangedListener();
|
||||||
|
|
||||||
getProxy().getScheduler().schedule(this, () -> {
|
getProxy().getScheduler().schedule(this, () -> {
|
||||||
@ -203,6 +205,7 @@ public class BungeeCore extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tablistManager.disable();
|
||||||
errorLogger.unregister();
|
errorLogger.unregister();
|
||||||
Statement.closeAll();
|
Statement.closeAll();
|
||||||
}
|
}
|
||||||
|
@ -1,335 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is a part of the SteamWar software.
|
|
||||||
|
|
||||||
Copyright (C) 2020 SteamWar.de-Serverteam
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.bungeecore.listeners;
|
|
||||||
|
|
||||||
import codecrafter47.bungeetablistplus.api.bungee.BungeeTabListPlusAPI;
|
|
||||||
import codecrafter47.bungeetablistplus.api.bungee.Icon;
|
|
||||||
import codecrafter47.bungeetablistplus.tablist.DefaultCustomTablist;
|
|
||||||
import de.steamwar.bungeecore.BungeeCore;
|
|
||||||
import de.steamwar.bungeecore.Message;
|
|
||||||
import de.steamwar.bungeecore.Servertype;
|
|
||||||
import de.steamwar.bungeecore.Subserver;
|
|
||||||
import de.steamwar.bungeecore.sql.SteamwarUser;
|
|
||||||
import de.steamwar.bungeecore.sql.UserGroup;
|
|
||||||
import net.md_5.bungee.BungeeCord;
|
|
||||||
import de.steamwar.network.packets.common.FightInfoPacket;
|
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
||||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
|
||||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
|
||||||
import net.md_5.bungee.event.EventHandler;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class TablistManager extends BasicListener {
|
|
||||||
|
|
||||||
private static final Map<ProxiedPlayer, Tablist> tablists = new HashMap<>();
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public synchronized void onJoin(PostLoginEvent e){
|
|
||||||
BungeeCord.getInstance().getScheduler().schedule(BungeeCore.get(), () -> {
|
|
||||||
if (e.getPlayer().isConnected()) {
|
|
||||||
tablists.put(e.getPlayer(), new Tablist(e.getPlayer()));
|
|
||||||
}
|
|
||||||
}, 1, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public synchronized void onLeave(PlayerDisconnectEvent e){
|
|
||||||
tablists.remove(e.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static final Map<ServerInfo, FightInfoPacket> fightInfos = new HashMap<>();
|
|
||||||
|
|
||||||
public static synchronized void newFightInfo(ServerInfo info, FightInfoPacket packet) {
|
|
||||||
fightInfos.put(info, packet);
|
|
||||||
fightInfos.keySet().removeIf(serverInfo -> serverInfo.getPlayers().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static Icon darkGray;
|
|
||||||
private static Icon gray;
|
|
||||||
|
|
||||||
private int seconds = 0;
|
|
||||||
private int size;
|
|
||||||
private TablistGroup tablist;
|
|
||||||
|
|
||||||
public TablistManager(){
|
|
||||||
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), this::updateTablist, 1, 1, TimeUnit.SECONDS);
|
|
||||||
try{
|
|
||||||
BungeeTabListPlusAPI.createIcon(ImageIO.read(new File("/configs/BungeeTabListPlus/heads/colors/dark_gray.png")), (icon) -> darkGray = icon);
|
|
||||||
BungeeTabListPlusAPI.createIcon(ImageIO.read(new File("/configs/BungeeTabListPlus/heads/colors/gray.png")), (icon) -> gray = icon);
|
|
||||||
}catch(IOException e){
|
|
||||||
throw new SecurityException("Could not load icons", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProxyServer.getInstance().getPlayers().forEach(p -> tablists.put(p, new Tablist(p)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void updateTablist(){
|
|
||||||
//Calculate server-player-map
|
|
||||||
tablist = new TablistGroup(true, "");
|
|
||||||
TablistGroup bau = new TablistGroup(false, "Bau");
|
|
||||||
for (ServerInfo server : new ArrayList<>(ProxyServer.getInstance().getServers().values())){
|
|
||||||
if(server.getPlayers().isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Subserver subserver = Subserver.getSubserver(server);
|
|
||||||
if(subserver != null && subserver.getType() == Servertype.BAUSERVER)
|
|
||||||
bau.addSubTablist(new TablistServer(server));
|
|
||||||
else if(fightInfos.containsKey(server))
|
|
||||||
tablist.addSubTablist(new TablistServer(server, fightInfos.get(server)));
|
|
||||||
else
|
|
||||||
tablist.addSubTablist(new TablistServer(server));
|
|
||||||
}
|
|
||||||
if(bau.size() > 0)
|
|
||||||
tablist.addSubTablist(bau);
|
|
||||||
|
|
||||||
size = (int) Math.ceil((tablist.size() - 1) / 20.0);
|
|
||||||
tablists.values().forEach(Tablist::refresh);
|
|
||||||
seconds++;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Tablist extends DefaultCustomTablist {
|
|
||||||
private final ProxiedPlayer player;
|
|
||||||
private int pos = 0;
|
|
||||||
|
|
||||||
private Tablist(ProxiedPlayer player){
|
|
||||||
this.player = player;
|
|
||||||
BungeeTabListPlusAPI.setCustomTabList(player, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String header(){
|
|
||||||
int phase = (seconds % 16) / 3;
|
|
||||||
switch(phase){
|
|
||||||
case 0:
|
|
||||||
return Message.parse("TABLIST_PHASE_1", player);
|
|
||||||
case 1:
|
|
||||||
return Message.parse("TABLIST_PHASE_2", player);
|
|
||||||
case 2:
|
|
||||||
default:
|
|
||||||
return Message.parse("TABLIST_PHASE_DEFAULT", player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 void refresh(){
|
|
||||||
if (player.getServer() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pos = 0;
|
|
||||||
setHeader(header());
|
|
||||||
setFooter(Message.parse("TABLIST_FOOTER", player, player.getServer().getInfo().getName(), ping(), ProxyServer.getInstance().getPlayers().size()));
|
|
||||||
int currentSize = size > 4 ? tablist.slimSize(player) : size;
|
|
||||||
setSize(currentSize, 20);
|
|
||||||
|
|
||||||
tablist.print(this, size > 4);
|
|
||||||
|
|
||||||
while (pos < currentSize*20){
|
|
||||||
setSlot(darkGray, "", 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSlot(Icon icon, String name, int ping){
|
|
||||||
if(pos / 20 >= getColumns())
|
|
||||||
return;
|
|
||||||
|
|
||||||
setSlot(pos % 20, pos / 20, icon, name, ping);
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface TablistPart {
|
|
||||||
int size();
|
|
||||||
int slimSize(ProxiedPlayer viewer);
|
|
||||||
String name();
|
|
||||||
void print(Tablist viewer, boolean slim);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TablistGroup implements TablistPart {
|
|
||||||
|
|
||||||
private final boolean withHeaders;
|
|
||||||
private final String orderName;
|
|
||||||
private final List<TablistPart> subTablists = new ArrayList<>();
|
|
||||||
|
|
||||||
private TablistGroup(boolean withHeaders, String orderName) {
|
|
||||||
this.withHeaders = withHeaders;
|
|
||||||
this.orderName = orderName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addSubTablist(TablistPart tablist){
|
|
||||||
subTablists.add(tablist);
|
|
||||||
subTablists.sort((t1, t2) -> t1.name().compareToIgnoreCase(t2.name()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return slimSize(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int slimSize(ProxiedPlayer viewer) {
|
|
||||||
return subTablists.stream().mapToInt(tPart -> viewer == null ? tPart.size() : tPart.slimSize(viewer)).map(size -> {
|
|
||||||
size += withHeaders ? 1 : 0; // Space for header
|
|
||||||
size += withHeaders && size > 1 ? 1 : 0; // Space for footer
|
|
||||||
return size;
|
|
||||||
}).sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return orderName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(Tablist viewer, boolean slim) {
|
|
||||||
for (int i = 0; i < subTablists.size(); i++) {
|
|
||||||
TablistPart tPart = subTablists.get(i);
|
|
||||||
String name = tPart.name();
|
|
||||||
if (name.equals("Bau")) {
|
|
||||||
name = Message.parse("TABLIST_BAU", viewer.player);
|
|
||||||
}
|
|
||||||
boolean withoutFooter = i == subTablists.size() - 1;
|
|
||||||
if (withHeaders) {
|
|
||||||
if (slim) {
|
|
||||||
int slimSize = tPart.slimSize(viewer.player);
|
|
||||||
int size = tPart.size();
|
|
||||||
if (size == slimSize) {
|
|
||||||
viewer.setSlot(gray, "§7§l" + name, 1000);
|
|
||||||
} else if (slimSize == 0) {
|
|
||||||
viewer.setSlot(gray, "§7§l" + name + " §8(§7" + size + "§8)", 1000);
|
|
||||||
withoutFooter = true;
|
|
||||||
} else {
|
|
||||||
viewer.setSlot(gray, "§7§l" + name + " §8(§7+" + (size - slimSize) + "§8)", 1000);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
viewer.setSlot(gray, "§7§l" + name, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tPart.print(viewer, slim);
|
|
||||||
if (withHeaders && !withoutFooter) {
|
|
||||||
viewer.setSlot(darkGray, "", 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TablistServer implements TablistPart {
|
|
||||||
private static class TablistPlayer {
|
|
||||||
private final ProxiedPlayer player;
|
|
||||||
private final String defaultName;
|
|
||||||
|
|
||||||
private TablistPlayer(ProxiedPlayer player, String defaultName) {
|
|
||||||
this.player = player;
|
|
||||||
this.defaultName = defaultName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private final List<TablistPlayer> players = new ArrayList<>();
|
|
||||||
private final ServerInfo info;
|
|
||||||
private final Subserver subserver;
|
|
||||||
|
|
||||||
private TablistServer(ServerInfo info, FightInfoPacket packet){
|
|
||||||
this.info = info;
|
|
||||||
subserver = Subserver.getSubserver(info);
|
|
||||||
Collection<ProxiedPlayer> onlinePlayers = info.getPlayers();
|
|
||||||
addPlayers(packet.getBlueName().substring(0, 2), packet.getBluePlayers(), onlinePlayers);
|
|
||||||
addPlayers(packet.getRedName().substring(0, 2), packet.getRedPlayers(), onlinePlayers);
|
|
||||||
addPlayers("§7", packet.getSpectators(), onlinePlayers);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addPlayers(String prefix, List<Integer> teamPlayers, Collection<ProxiedPlayer> onlinePlayers){
|
|
||||||
teamPlayers.stream().map(SteamwarUser::get).map(
|
|
||||||
user -> onlinePlayers.stream().filter(player -> player.getUniqueId().equals(user.getUuid())).findAny()
|
|
||||||
).filter(Optional::isPresent).map(Optional::get).sorted(
|
|
||||||
(p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName())
|
|
||||||
).forEachOrdered(player -> players.add(new TablistPlayer(player, prefix + player.getName())));
|
|
||||||
}
|
|
||||||
|
|
||||||
private TablistServer(ServerInfo info) {
|
|
||||||
this.info = info;
|
|
||||||
subserver = Subserver.getSubserver(info);
|
|
||||||
info.getPlayers().forEach(player -> players.add(new TablistPlayer(player, SteamwarUser.get(player.getUniqueId()).getUserGroup().getColorCode() + player.getName())));
|
|
||||||
players.sort((tp1, tp2) -> tp1.player.getName().compareToIgnoreCase(tp2.player.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean displaySlim(ProxiedPlayer viewer, ProxiedPlayer player){
|
|
||||||
if(viewer.getServer().getInfo() == info)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if(subserver != null && subserver.getType() == Servertype.ARENA && info.getPlayers().size() == 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
SteamwarUser user = SteamwarUser.get(player);
|
|
||||||
if(user.getUserGroup() != UserGroup.Member)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return user.getTeam() != 0 && SteamwarUser.get(viewer).getTeam() == user.getTeam();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return players.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int slimSize(ProxiedPlayer viewer) {
|
|
||||||
if(viewer.getServer().getInfo() == info)
|
|
||||||
return size();
|
|
||||||
|
|
||||||
return players.stream().mapToInt(player -> displaySlim(viewer, player.player) ? 1 : 0).sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return info.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(Tablist viewer, boolean slim) {
|
|
||||||
boolean sameServer = viewer.player.getServer().getInfo() == info;
|
|
||||||
|
|
||||||
SteamwarUser user = SteamwarUser.get(viewer.player.getUniqueId());
|
|
||||||
for(TablistPlayer player : players){
|
|
||||||
if(slim && !displaySlim(viewer.player, player.player))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int ping = sameServer ? 1 : 1000;
|
|
||||||
String name = player.defaultName.startsWith("§7") && user.getTeam() != 0 && user.getTeam() == SteamwarUser.get(player.player.getUniqueId()).getTeam() ? "§f" + player.player.getName() : player.defaultName;
|
|
||||||
viewer.setSlot(BungeeTabListPlusAPI.getIconFromPlayer(player.player), name, ping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,10 +19,9 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore.network.handlers;
|
package de.steamwar.bungeecore.network.handlers;
|
||||||
|
|
||||||
import de.steamwar.bungeecore.listeners.TablistManager;
|
|
||||||
import de.steamwar.bungeecore.network.NetworkReceiver;
|
|
||||||
import de.steamwar.bungeecore.network.NetworkSender;
|
import de.steamwar.bungeecore.network.NetworkSender;
|
||||||
import de.steamwar.bungeecore.network.ServerMetaInfo;
|
import de.steamwar.bungeecore.network.ServerMetaInfo;
|
||||||
|
import de.steamwar.bungeecore.tablist.TablistManager;
|
||||||
import de.steamwar.network.packets.PacketHandler;
|
import de.steamwar.network.packets.PacketHandler;
|
||||||
import de.steamwar.network.packets.common.FightInfoPacket;
|
import de.steamwar.network.packets.common.FightInfoPacket;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
252
src/de/steamwar/bungeecore/tablist/Tablist.java
Normale Datei
252
src/de/steamwar/bungeecore/tablist/Tablist.java
Normale Datei
@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import de.steamwar.bungeecore.Storage;
|
||||||
|
import de.steamwar.messages.ChatSender;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
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.BaseComponent;
|
||||||
|
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.netty.PipelineUtils;
|
||||||
|
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.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
@ChannelHandler.Sharable
|
||||||
|
public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
|
||||||
|
|
||||||
|
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);
|
||||||
|
private static final String TAB_TEAM = "»SW-Tab";
|
||||||
|
private static final Team teamPacket = new Team(TAB_TEAM, (byte) 0, ComponentSerializer.toString(TextComponent.fromLegacyText("")), ComponentSerializer.toString(TextComponent.fromLegacyText("")), ComponentSerializer.toString(TextComponent.fromLegacyText("")), "always", "always", 21, (byte)0x00, names);
|
||||||
|
|
||||||
|
private final Map<UUID, PlayerListItem.Item> directTabItems;
|
||||||
|
private final Set<UUID> npcs = new HashSet<>();
|
||||||
|
private final List<PlayerListItem.Item> current = new ArrayList<>();
|
||||||
|
|
||||||
|
private final ProxiedPlayer player;
|
||||||
|
private final ChatSender viewer;
|
||||||
|
private ServerConnection connection;
|
||||||
|
|
||||||
|
public Tablist(ProxiedPlayer player) {
|
||||||
|
this.player = player;
|
||||||
|
this.viewer = ChatSender.of(player);
|
||||||
|
this.directTabItems = Storage.directTabItems.computeIfAbsent(player, p -> new HashMap<>());
|
||||||
|
onServerSwitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(TablistPart global, int seconds) {
|
||||||
|
if (player.getServer() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
player.unsafe().sendPacket(new PlayerListHeaderFooter(
|
||||||
|
ComponentSerializer.toString(header(viewer, seconds)),
|
||||||
|
ComponentSerializer.toString(viewer.parse(false, "TABLIST_FOOTER", connection.getInfo().getName(), ping(), ProxyServer.getInstance().getPlayers().size()))
|
||||||
|
));
|
||||||
|
|
||||||
|
List<TablistPart.Item> tablist = new ArrayList<>();
|
||||||
|
List<TablistPart.Item> direct = new ArrayList<>();
|
||||||
|
global.print(viewer, player, tablist, direct);
|
||||||
|
|
||||||
|
// NPC handling
|
||||||
|
List<String> addNpc = new ArrayList<>();
|
||||||
|
List<String> removeNpc = new ArrayList<>();
|
||||||
|
List<PlayerListItem.Item> update = new ArrayList<>();
|
||||||
|
for (TablistPart.Item item : direct) {
|
||||||
|
if(npcs.remove(item.getUuid()))
|
||||||
|
removeNpc.add(directTabItems.get(item.getUuid()).getUsername());
|
||||||
|
|
||||||
|
PlayerListItem.Item tabItem = directTabItems.get(item.getUuid());
|
||||||
|
if(tabItem == null) {
|
||||||
|
tablist.add(0, item);
|
||||||
|
} else if(!tabItem.getDisplayName().equals(item.getDisplayName())) {
|
||||||
|
tabItem.setDisplayName(item.getDisplayName());
|
||||||
|
update.add(tabItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Set<UUID> nonNPCs = direct.stream().map(TablistPart.Item::getUuid).collect(Collectors.toSet());
|
||||||
|
for(PlayerListItem.Item item : directTabItems.values()) {
|
||||||
|
if(!nonNPCs.contains(item.getUuid()) && !npcs.contains(item.getUuid()))
|
||||||
|
addNpc.add(item.getUsername());
|
||||||
|
}
|
||||||
|
sendNpcPacket(addNpc, false);
|
||||||
|
sendNpcPacket(removeNpc, true);
|
||||||
|
|
||||||
|
// Main list handling
|
||||||
|
int i = 0;
|
||||||
|
List<PlayerListItem.Item> add = new ArrayList<>();
|
||||||
|
for (; i < tablist.size() && i < 80; i++) {
|
||||||
|
PlayerListItem.Item tabItem;
|
||||||
|
if(current.size() > i) {
|
||||||
|
tabItem = current.get(i);
|
||||||
|
} else {
|
||||||
|
tabItem = new PlayerListItem.Item();
|
||||||
|
tabItem.setUuid(uuids[i]);
|
||||||
|
tabItem.setUsername(names[i]);
|
||||||
|
tabItem.setGamemode(1);
|
||||||
|
tabItem.setPing(1000);
|
||||||
|
current.add(tabItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
TablistPart.Item item = tablist.get(i);
|
||||||
|
if(!Arrays.equals(tabItem.getProperties(), item.getProperties())) {
|
||||||
|
tabItem.setProperties(item.getProperties());
|
||||||
|
tabItem.setDisplayName(item.getDisplayName());
|
||||||
|
add.add(tabItem);
|
||||||
|
} else if(!item.getDisplayName().equals(tabItem.getDisplayName())) {
|
||||||
|
tabItem.setDisplayName(item.getDisplayName());
|
||||||
|
update.add(tabItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sendTabPacket(add, PlayerListItem.Action.ADD_PLAYER);
|
||||||
|
sendTabPacket(update, PlayerListItem.Action.UPDATE_DISPLAY_NAME);
|
||||||
|
|
||||||
|
// Excess removal
|
||||||
|
List<PlayerListItem.Item> remove = new ArrayList<>();
|
||||||
|
while(i < current.size()) {
|
||||||
|
remove.add(current.remove(i));
|
||||||
|
}
|
||||||
|
sendTabPacket(remove, PlayerListItem.Action.REMOVE_PLAYER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServerSwitch() {
|
||||||
|
connection = (ServerConnection) player.getServer();
|
||||||
|
directTabItems.clear();
|
||||||
|
sendNpcPacket(npcs.stream().map(npc -> directTabItems.get(npc).getUsername()).collect(Collectors.toList()), true);
|
||||||
|
npcs.clear();
|
||||||
|
|
||||||
|
if(connection != null) {
|
||||||
|
connection.getCh().getHandle().pipeline().addBefore(PipelineUtils.BOSS_HANDLER, "steamwar-tablist", this);
|
||||||
|
player.unsafe().sendPacket(teamPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable() {
|
||||||
|
sendTabPacket(current, PlayerListItem.Action.REMOVE_PLAYER);
|
||||||
|
current.clear();
|
||||||
|
sendNpcPacket(npcs.stream().map(npc -> directTabItems.get(npc).getUsername()).collect(Collectors.toList()), true);
|
||||||
|
npcs.clear();
|
||||||
|
|
||||||
|
if(connection != null)
|
||||||
|
connection.getCh().getHandle().pipeline().remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext ctx, PacketWrapper packetWrapper, List<Object> out) {
|
||||||
|
if(!connection.isObsolete()) {
|
||||||
|
DefinedPacket packet = packetWrapper.packet;
|
||||||
|
|
||||||
|
if(packet instanceof PlayerListHeaderFooter) {
|
||||||
|
packetWrapper.trySingleRelease();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(packet instanceof PlayerListItem) {
|
||||||
|
PlayerListItem list = (PlayerListItem) packet;
|
||||||
|
PlayerListItem.Action action = list.getAction();
|
||||||
|
|
||||||
|
switch(action) {
|
||||||
|
case UPDATE_LATENCY:
|
||||||
|
case UPDATE_DISPLAY_NAME:
|
||||||
|
packetWrapper.trySingleRelease();
|
||||||
|
return;
|
||||||
|
case UPDATE_GAMEMODE:
|
||||||
|
for (PlayerListItem.Item item : list.getItems()) {
|
||||||
|
ProxiedPlayer p = ProxyServer.getInstance().getPlayer(item.getUuid());
|
||||||
|
if(p != null && p != player && item.getGamemode() == 3) {
|
||||||
|
item.setGamemode(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ADD_PLAYER:
|
||||||
|
for (PlayerListItem.Item item : list.getItems()) {
|
||||||
|
item.setPing(1);
|
||||||
|
item.setDisplayName(ComponentSerializer.toString(TextComponent.fromLegacyText("")));
|
||||||
|
if(!player.getUniqueId().equals(item.getUuid()) && item.getGamemode() == 3)
|
||||||
|
item.setGamemode(1);
|
||||||
|
|
||||||
|
directTabItems.put(item.getUuid(), item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REMOVE_PLAYER:
|
||||||
|
for(PlayerListItem.Item item : list.getItems()) {
|
||||||
|
directTabItems.remove(item.getUuid());
|
||||||
|
npcs.remove(item.getUuid());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.add(packetWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendTabPacket(List<PlayerListItem.Item> items, PlayerListItem.Action action) {
|
||||||
|
if(!items.isEmpty()) {
|
||||||
|
PlayerListItem packet = new PlayerListItem();
|
||||||
|
packet.setAction(action);
|
||||||
|
packet.setItems(items.toArray(new PlayerListItem.Item[0]));
|
||||||
|
player.unsafe().sendPacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendNpcPacket(List<String> names, boolean remove) {
|
||||||
|
if(!names.isEmpty()) {
|
||||||
|
Team packet = new Team(TAB_TEAM);
|
||||||
|
packet.setMode((byte) (remove ? 4 : 3));
|
||||||
|
packet.setPlayers(names.toArray(new String[0]));
|
||||||
|
player.unsafe().sendPacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseComponent[] header(ChatSender p, int seconds) {
|
||||||
|
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 String ping() {
|
||||||
|
int ping = player.getPing();
|
||||||
|
if (ping < 50) {
|
||||||
|
return "§a" + ping;
|
||||||
|
} else if (ping < 150) {
|
||||||
|
return "§e" + ping;
|
||||||
|
} else {
|
||||||
|
return "§c" + ping;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
src/de/steamwar/bungeecore/tablist/TablistBuild.java
Normale Datei
69
src/de/steamwar/bungeecore/tablist/TablistBuild.java
Normale Datei
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import de.steamwar.bungeecore.Servertype;
|
||||||
|
import de.steamwar.bungeecore.Subserver;
|
||||||
|
import de.steamwar.messages.ChatSender;
|
||||||
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TablistBuild implements TablistPart {
|
||||||
|
|
||||||
|
private final List<ServerInfo> servers = new ArrayList<>();
|
||||||
|
private final Map<ServerInfo, List<Item>> players = new HashMap<>();
|
||||||
|
|
||||||
|
public TablistBuild() {
|
||||||
|
for (ServerInfo server : ProxyServer.getInstance().getServersCopy().values()){
|
||||||
|
Subserver subserver = Subserver.getSubserver(server);
|
||||||
|
if(server.getPlayers().isEmpty() || subserver == null || subserver.getType() != Servertype.BAUSERVER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
servers.add(server);
|
||||||
|
players.put(server, server.getPlayers().stream().sorted(((p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName()))).map(Item::new).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
servers.sort((s1, s2) -> s1.getName().compareToIgnoreCase(s2.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String sortKey() {
|
||||||
|
return "Build";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(ChatSender viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct) {
|
||||||
|
ServerInfo server = player.getServer().getInfo();
|
||||||
|
if(players.keySet().stream().anyMatch(info -> server != info)) {
|
||||||
|
tablist.add(new Item(null, "", TablistServer.GRAY));
|
||||||
|
tablist.add(new Item(null, viewer.parseToLegacy("TABLIST_BAU"), TablistServer.LIGHT_GRAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(ServerInfo info : servers) {
|
||||||
|
(server == info ? direct : tablist).addAll(players.get(info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
src/de/steamwar/bungeecore/tablist/TablistGroup.java
Normale Datei
45
src/de/steamwar/bungeecore/tablist/TablistGroup.java
Normale Datei
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import de.steamwar.messages.ChatSender;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TablistGroup implements TablistPart {
|
||||||
|
private final List<TablistPart> sublists;
|
||||||
|
|
||||||
|
public TablistGroup(List<TablistPart> sublists) {
|
||||||
|
this.sublists = sublists;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String sortKey() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(ChatSender viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct) {
|
||||||
|
for (TablistPart sublist : sublists) {
|
||||||
|
sublist.print(viewer, player, tablist, direct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
107
src/de/steamwar/bungeecore/tablist/TablistManager.java
Normale Datei
107
src/de/steamwar/bungeecore/tablist/TablistManager.java
Normale Datei
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import de.steamwar.bungeecore.BungeeCore;
|
||||||
|
import de.steamwar.bungeecore.Servertype;
|
||||||
|
import de.steamwar.bungeecore.Storage;
|
||||||
|
import de.steamwar.bungeecore.Subserver;
|
||||||
|
import de.steamwar.bungeecore.listeners.BasicListener;
|
||||||
|
import de.steamwar.network.packets.common.FightInfoPacket;
|
||||||
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||||
|
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||||
|
import net.md_5.bungee.api.event.ServerSwitchEvent;
|
||||||
|
import net.md_5.bungee.event.EventHandler;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class TablistManager extends BasicListener {
|
||||||
|
|
||||||
|
private static final Map<ServerInfo, FightInfoPacket> fightInfos = new HashMap<>();
|
||||||
|
|
||||||
|
public static synchronized void newFightInfo(ServerInfo info, FightInfoPacket packet) {
|
||||||
|
fightInfos.put(info, packet);
|
||||||
|
fightInfos.keySet().removeIf(serverInfo -> serverInfo.getPlayers().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PostLoginEvent event) {
|
||||||
|
synchronized (tablists) {
|
||||||
|
tablists.put(event.getPlayer(), new Tablist(event.getPlayer()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onServerConnection(ServerSwitchEvent event) {
|
||||||
|
synchronized (tablists) {
|
||||||
|
tablists.get(event.getPlayer()).onServerSwitch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onLeave(PlayerDisconnectEvent event) {
|
||||||
|
synchronized (tablists) {
|
||||||
|
tablists.remove(event.getPlayer());
|
||||||
|
Storage.directTabItems.remove(event.getPlayer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable() {
|
||||||
|
synchronized (tablists) {
|
||||||
|
tablists.forEach((player, tablist) -> tablist.disable());
|
||||||
|
tablists.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTablist() {
|
||||||
|
List<TablistPart> subservers = new ArrayList<>();
|
||||||
|
for (ServerInfo server : ProxyServer.getInstance().getServersCopy().values()){
|
||||||
|
if(server.getPlayers().isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Subserver subserver = Subserver.getSubserver(server);
|
||||||
|
if(fightInfos.containsKey(server))
|
||||||
|
subservers.add(new TablistServer(server, fightInfos.get(server)));
|
||||||
|
else if(subserver == null || subserver.getType() != Servertype.BAUSERVER)
|
||||||
|
subservers.add(new TablistServer(server));
|
||||||
|
}
|
||||||
|
subservers.add(new TablistBuild());
|
||||||
|
subservers.sort((s1, s2) -> s1.sortKey().compareToIgnoreCase(s2.sortKey()));
|
||||||
|
TablistPart global = new TablistGroup(subservers);
|
||||||
|
|
||||||
|
synchronized (tablists) {
|
||||||
|
tablists.forEach((player, tablist) -> tablist.update(global, seconds));
|
||||||
|
}
|
||||||
|
seconds++;
|
||||||
|
}
|
||||||
|
}
|
75
src/de/steamwar/bungeecore/tablist/TablistPart.java
Normale Datei
75
src/de/steamwar/bungeecore/tablist/TablistPart.java
Normale Datei
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import de.steamwar.bungeecore.sql.SteamwarUser;
|
||||||
|
import de.steamwar.messages.ChatSender;
|
||||||
|
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.connection.InitialHandler;
|
||||||
|
import net.md_5.bungee.protocol.Property;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
interface TablistPart {
|
||||||
|
String sortKey();
|
||||||
|
void print(ChatSender viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct);
|
||||||
|
|
||||||
|
class Item {
|
||||||
|
|
||||||
|
public static Property[] playerProperties(ProxiedPlayer player) {
|
||||||
|
return ((InitialHandler) player.getPendingConnection()).getLoginProfile().getProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final UUID uuid;
|
||||||
|
private final String displayName;
|
||||||
|
private final Property[] properties;
|
||||||
|
|
||||||
|
public Item(UUID uuid, String displayName, Property[] properties) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.displayName = reformat(displayName);
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item(ProxiedPlayer player) {
|
||||||
|
this.uuid = player.getUniqueId();
|
||||||
|
this.displayName = reformat(SteamwarUser.get(player.getUniqueId()).getUserGroup().getColorCode() + player.getName());
|
||||||
|
this.properties = playerProperties(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Property[] getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String reformat(String string) {
|
||||||
|
return ComponentSerializer.toString(TextComponent.fromLegacyText(string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
src/de/steamwar/bungeecore/tablist/TablistServer.java
Normale Datei
86
src/de/steamwar/bungeecore/tablist/TablistServer.java
Normale Datei
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import de.steamwar.bungeecore.sql.SteamwarUser;
|
||||||
|
import de.steamwar.messages.ChatSender;
|
||||||
|
import de.steamwar.network.packets.common.FightInfoPacket;
|
||||||
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.protocol.Property;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TablistServer implements TablistPart {
|
||||||
|
|
||||||
|
public static final Property[] GRAY = new Property[]{new Property("textures", "eyJ0aW1lc3RhbXAiOjE0NTU1NzQxMTk0MzMsInByb2ZpbGVJZCI6ImIzYjE4MzQ1MzViZjRiNzU4ZTBjZGJmMGY4MjA2NTZlIiwicHJvZmlsZU5hbWUiOiIxMDExMTEiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzZlNzJkMzE0NzczMmQ5NzFkZWZhZTIzMWIzOGQ5NDI0MTRiMDU3YTcxNTFjNTNjNWZkNjI5NmEzYjllZGEwYWIifX19", "ro/ZKHt7278yhCr+CFTcPp/q6wAUlef//85k2DzkfRaZqy0CtGgwisDs2U4pVKvQ2pfXvitzWgbJvD0bLeQ12xWi4c1Fc29LCArosVJoFmrJDHz7N2MlstHT+ynQROb9d2aiFA6uOXfLjPKb1noUZ/YQoZjqcPIvD5oFZtD5DHV5O4hYz0IvgHbIjDqjz6ITsTcKiBlbxNg2loTFxSlW1ZfnNCO+kcAmeyB5NFY3j0e+/AqVANiNoiC3OKsECM/yEx/acf+vKWcT8mQn4wRoIGtxfEU7ZjNtgdh73NvXXBygW+K9AiJ242g8Y06Xxuk8kaNEGmT6H/mM7nbwjZmQQXpi/Pao2gYqyeIofeCPfr8RsGXoDX3nXDAw8/LyhTCHgx+sp6IQYSfGcSMJtoNeTJ0liIFxqn1V9/zKmzOZAPzR6qrQPOjoRFljLAlv7rfzotaEqh/1ldd40GdS8tstczn7f29OQerNDaqvbDb00Gy0STdUr1bVyCDptA54XKjT9WFv7QpBikEculxqSppAXPxD2Fb/ZmphbZx8WEGfG6bVFhf6fQdDAUXlcv8BxjElNPwlolF86M2KJd5VquLluhrCjwID7OK/pffNultAVH+Lxw4QOAXmJqjUrA1KHgyG1S0Cwj/f4E2hdxZJBvkfVtq9qPkd9nignhEoTCTOHf0=")};
|
||||||
|
public static final Property[] LIGHT_GRAY = new Property[]{new Property("textures", "eyJ0aW1lc3RhbXAiOjE0NTU2MjU1OTM5NjIsInByb2ZpbGVJZCI6ImIzYjE4MzQ1MzViZjRiNzU4ZTBjZGJmMGY4MjA2NTZlIiwicHJvZmlsZU5hbWUiOiIxMDExMTEiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzc4Y2I3ZmMyMDhiMzM4NTUwNGE4MTQ0MjA0NDI4ZmRjZDYzMjRiZWIzMWNhMmNlODZjYzQyNGI5NjNkODVjIn19fQ==", "R/wZUZRC1dishRdM9a2SSxxW3oYa0XSb/MxHbQpEUA791HxyqjaKLDu0wFX2r2a8ZTeVjzXpNzkg3+PkrA11o8h7lt86MTD1pi/rQqj/WRuoqf2LP+ypbssKV+LU15cYez2cj3QQVcJDXgWEnfSLNuBv6NG8BDUpUAjTWldvu99NCJHUoD0jNMHxY/fu4k5vCgOjaBaKgkjVk2bmUhegusmtMwco+3pYx+y8+gUW8ptx5SnePG+dOwTqLyBFiOt2AQ+gSvbU/jP9aAXgxOwz/b1pMaBWtzVhFU865NHlIdSpIHg/sh3uNah3a7gTgtTvxPQv1OzM/KtqYKiamsrRzAQMzRcs4A7Tp0GakLuxEaz401IwvQ7UGVYLFzGUVLB2MyqtPgifiqQSQxZpiqj9sM5QadhsUw00nfX7mTdW46U0MtNIbby1rLrvgQKoj08zt6LJlhI3yjyawy4iZkgF4oc+PCNwZc93GIbVL9LJaGkXk3RVA+JpGwfMJrGVbL7hl8ibbAcUv7uCEWdkAgZCd6w75jEE4tlhDSPDD4rXbn+FeTZRg2n/PGKtnoTZRzbniiFaNoSAHDZSVRG39xvBDFvtmL3SPaKhzKaifiYrgNn453WtR3kymqdAtPf1GN9d1VltGZ/+vMPwqPJb6thcrlcU64UGHbg1olRkiyZHvY8=")};
|
||||||
|
|
||||||
|
private final ServerInfo server;
|
||||||
|
private final List<Item> players;
|
||||||
|
|
||||||
|
public TablistServer(ServerInfo server) {
|
||||||
|
this(server, server.getPlayers().stream().sorted((p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName())).map(TablistPart.Item::new).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TablistServer(ServerInfo server, FightInfoPacket info) {
|
||||||
|
this(server, new ArrayList<>());
|
||||||
|
|
||||||
|
Collection<ProxiedPlayer> onlinePlayers = server.getPlayers();
|
||||||
|
addPlayers(info.getBlueName().substring(0, 2), info.getBluePlayers(), onlinePlayers);
|
||||||
|
addPlayers(info.getRedName().substring(0, 2), info.getRedPlayers(), onlinePlayers);
|
||||||
|
addPlayers("§7", info.getSpectators(), onlinePlayers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TablistServer(ServerInfo server, List<Item> players) {
|
||||||
|
this.server = server;
|
||||||
|
this.players = players;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String sortKey() {
|
||||||
|
return server.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(ChatSender viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct) {
|
||||||
|
boolean onServer = player.getServer().getInfo() == server;
|
||||||
|
List<Item> items = onServer ? direct : tablist;
|
||||||
|
|
||||||
|
if(!onServer) {
|
||||||
|
items.add(new Item(null, "", GRAY));
|
||||||
|
items.add(new Item(null, "§7§l" + server.getName(), LIGHT_GRAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
items.addAll(players);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPlayers(String prefix, List<Integer> teamPlayers, Collection<ProxiedPlayer> onlinePlayers){
|
||||||
|
teamPlayers.stream().map(SteamwarUser::get).map(
|
||||||
|
user -> onlinePlayers.stream().filter(player -> player.getUniqueId().equals(user.getUuid())).findAny()
|
||||||
|
).filter(Optional::isPresent).map(Optional::get).sorted(
|
||||||
|
(p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName())
|
||||||
|
).forEachOrdered(player -> players.add(new Item(player.getUniqueId(), prefix + player.getName(), Item.playerProperties(player))));
|
||||||
|
}
|
||||||
|
}
|
@ -552,7 +552,7 @@ TABLIST_PHASE_1=§8Teamspeak: §eSteam§8War.de
|
|||||||
TABLIST_PHASE_2=§8Discord: §8https://§eSteam§8War.de/discord
|
TABLIST_PHASE_2=§8Discord: §8https://§eSteam§8War.de/discord
|
||||||
TABLIST_PHASE_DEFAULT=§8Website: https://§eSteam§8War.de
|
TABLIST_PHASE_DEFAULT=§8Website: https://§eSteam§8War.de
|
||||||
TABLIST_FOOTER=§e{0} {1}§8ms §ePlayers§8: §7{2}
|
TABLIST_FOOTER=§e{0} {1}§8ms §ePlayers§8: §7{2}
|
||||||
TABLIST_BAU=Build
|
TABLIST_BAU=§7§lBuild
|
||||||
LIST_COMMAND=§e{0}§8: §7{1}
|
LIST_COMMAND=§e{0}§8: §7{1}
|
||||||
|
|
||||||
#EventStarter
|
#EventStarter
|
||||||
|
@ -531,7 +531,7 @@ TABLIST_PHASE_1=§8Teamspeak: §eSteam§8War.de
|
|||||||
TABLIST_PHASE_2=§8Discord: §8https://§eSteam§8War.de/discord
|
TABLIST_PHASE_2=§8Discord: §8https://§eSteam§8War.de/discord
|
||||||
TABLIST_PHASE_DEFAULT=§8Website: https://§eSteam§8War.de
|
TABLIST_PHASE_DEFAULT=§8Website: https://§eSteam§8War.de
|
||||||
TABLIST_FOOTER=§e{0} {1}§8ms §eSpieler§8: §7{2}
|
TABLIST_FOOTER=§e{0} {1}§8ms §eSpieler§8: §7{2}
|
||||||
TABLIST_BAU=Bau
|
TABLIST_BAU=§7§lBau
|
||||||
LIST_COMMAND=§e{0}§8: §7{1}
|
LIST_COMMAND=§e{0}§8: §7{1}
|
||||||
|
|
||||||
#EventStarter
|
#EventStarter
|
||||||
|
@ -115,6 +115,10 @@ public interface ChatSender {
|
|||||||
return parseToComponent(false, message).toLegacyText();
|
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) {
|
default BaseComponent[] parse(boolean prefixed, Message message) {
|
||||||
Locale locale = getLocale();
|
Locale locale = getLocale();
|
||||||
ResourceBundle resourceBundle = SteamwarResourceBundle.getResourceBundle(locale);
|
ResourceBundle resourceBundle = SteamwarResourceBundle.getResourceBundle(locale);
|
||||||
|
@ -35,7 +35,7 @@ public class SteamwarResourceBundle extends PropertyResourceBundle {
|
|||||||
return getResourceBundle(locale.toString(), getResourceBundle(locale.getLanguage(), getResourceBundle( "", null)));
|
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 -> {
|
return bundles.computeIfAbsent(locale, locale1 -> {
|
||||||
InputStream inputStream = Message.class.getResourceAsStream(BASE_PATH + ("".equals(locale) ? "" : "_" + locale) + ".properties");
|
InputStream inputStream = Message.class.getResourceAsStream(BASE_PATH + ("".equals(locale) ? "" : "_" + locale) + ".properties");
|
||||||
if(inputStream == null)
|
if(inputStream == null)
|
||||||
|
@ -2,4 +2,5 @@ name: BungeeCore
|
|||||||
main: de.steamwar.bungeecore.BungeeCore
|
main: de.steamwar.bungeecore.BungeeCore
|
||||||
version: 1.0
|
version: 1.0
|
||||||
author: Lixfel
|
author: Lixfel
|
||||||
depends: [PersistentBungeeCore, BungeeTabListPlus]
|
depends:
|
||||||
|
- PersistentBungeeCore
|
In neuem Issue referenzieren
Einen Benutzer sperren