Persistent MonoRepo, Velocity: Tablist
Signed-off-by: Lixfel <git-5w3l@lixfel.de>
Dieser Commit ist enthalten in:
Ursprung
9b0d7bd856
Commit
c87ec5214a
66
Persistent/build.gradle
Normale Datei
66
Persistent/build.gradle
Normale Datei
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'de.steamwar'
|
||||||
|
version ''
|
||||||
|
|
||||||
|
compileJava.options.encoding = 'UTF-8'
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
java {
|
||||||
|
srcDirs = ['src/']
|
||||||
|
include '**/*.java', '**/*.kt'
|
||||||
|
}
|
||||||
|
resources {
|
||||||
|
srcDirs = ['src/']
|
||||||
|
exclude '**/*.java', '**/*.kt'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url = 'https://repo.fvdh.dev/releases'
|
||||||
|
content {
|
||||||
|
includeGroup 'net.frankheijden.serverutils'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly 'org.projectlombok:lombok:1.18.22'
|
||||||
|
testCompileOnly 'org.projectlombok:lombok:1.18.22'
|
||||||
|
annotationProcessor 'org.projectlombok:lombok:1.18.22'
|
||||||
|
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'
|
||||||
|
|
||||||
|
compileOnly 'de.steamwar:velocity:RELEASE'
|
||||||
|
annotationProcessor 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT'
|
||||||
|
|
||||||
|
compileOnly 'net.frankheijden.serverutils:ServerUtils:3.5.4'
|
||||||
|
}
|
18
Persistent/src/de/steamwar/bungeecore/Arenaserver.java
Normale Datei
18
Persistent/src/de/steamwar/bungeecore/Arenaserver.java
Normale Datei
@ -0,0 +1,18 @@
|
|||||||
|
package de.steamwar.bungeecore;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Arenaserver extends Subserver {
|
||||||
|
|
||||||
|
private final String mode;
|
||||||
|
private final String map;
|
||||||
|
private final boolean allowMerge;
|
||||||
|
|
||||||
|
public Arenaserver(String serverName, String mode, String map, boolean allowMerge, int port, ProcessBuilder processBuilder, Runnable shutdownCallback) {
|
||||||
|
super(Servertype.ARENA, serverName, port, processBuilder, shutdownCallback, null);
|
||||||
|
this.mode = mode;
|
||||||
|
this.map = map;
|
||||||
|
this.allowMerge = allowMerge;
|
||||||
|
}
|
||||||
|
}
|
65
Persistent/src/de/steamwar/bungeecore/Bauserver.java
Normale Datei
65
Persistent/src/de/steamwar/bungeecore/Bauserver.java
Normale Datei
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Bauserver extends Subserver {
|
||||||
|
private static final Map<UUID, Bauserver> servers = new HashMap<>();
|
||||||
|
public static Bauserver get(UUID owner) {
|
||||||
|
synchronized (servers) {
|
||||||
|
return servers.get(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final UUID owner;
|
||||||
|
|
||||||
|
public Bauserver(String serverName, UUID owner, int port, ProcessBuilder processBuilder, Runnable shutdownCallback){
|
||||||
|
this(serverName, owner, port, processBuilder, shutdownCallback, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bauserver(String serverName, UUID owner, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, Consumer<Exception> failureCallback){
|
||||||
|
super(Servertype.BAUSERVER, serverName, port, processBuilder, shutdownCallback, failureCallback);
|
||||||
|
this.owner = owner;
|
||||||
|
|
||||||
|
synchronized (servers) {
|
||||||
|
servers.put(owner, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void register() {
|
||||||
|
super.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void unregister() {
|
||||||
|
synchronized (servers) {
|
||||||
|
servers.remove(owner);
|
||||||
|
}
|
||||||
|
super.unregister();
|
||||||
|
}
|
||||||
|
}
|
64
Persistent/src/de/steamwar/bungeecore/Builderserver.java
Normale Datei
64
Persistent/src/de/steamwar/bungeecore/Builderserver.java
Normale Datei
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Builderserver extends Subserver {
|
||||||
|
|
||||||
|
private static final Map<String, Builderserver> servers = new HashMap<>();
|
||||||
|
public static Builderserver get(String map) {
|
||||||
|
synchronized (servers) {
|
||||||
|
return servers.get(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String map;
|
||||||
|
public Builderserver(String serverName, String map, int port, ProcessBuilder processBuilder, Runnable shutdownCallback){
|
||||||
|
this(serverName, map, port, processBuilder, shutdownCallback, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builderserver(String serverName, String map, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, Consumer<Exception> failureCallback){
|
||||||
|
super(Servertype.BUILDER, serverName, port, processBuilder, shutdownCallback, failureCallback);
|
||||||
|
this.map = map;
|
||||||
|
|
||||||
|
synchronized (servers) {
|
||||||
|
servers.put(map, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void register() {
|
||||||
|
super.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void unregister() {
|
||||||
|
synchronized (servers) {
|
||||||
|
servers.remove(map);
|
||||||
|
}
|
||||||
|
super.unregister();
|
||||||
|
}
|
||||||
|
}
|
81
Persistent/src/de/steamwar/bungeecore/Persistent.java
Normale Datei
81
Persistent/src/de/steamwar/bungeecore/Persistent.java
Normale Datei
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.velocitypowered.api.command.BrigadierCommand;
|
||||||
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
|
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||||
|
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||||
|
import com.velocitypowered.api.plugin.Dependency;
|
||||||
|
import com.velocitypowered.api.plugin.Plugin;
|
||||||
|
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||||
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.frankheijden.serverutils.velocity.ServerUtils;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@Plugin(
|
||||||
|
id = "persistentvelocitycore",
|
||||||
|
name = "PersistentVelocityCore",
|
||||||
|
dependencies = { @Dependency(id = "serverutils") }
|
||||||
|
)
|
||||||
|
public class Persistent {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static Persistent instance;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public Persistent(ProxyServer proxyServer, Logger logger, @DataDirectory Path dataDirectory) {
|
||||||
|
instance = this;
|
||||||
|
this.proxyServer = proxyServer;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final ProxyServer proxyServer;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onEnable(ProxyInitializeEvent event) {
|
||||||
|
proxyServer.getCommandManager().register(
|
||||||
|
new BrigadierCommand(
|
||||||
|
BrigadierCommand.literalArgumentBuilder("softreload")
|
||||||
|
.requires(commandSource -> commandSource.hasPermission("bungeecore.softreload"))
|
||||||
|
.executes(commandContext -> softreload())
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onDisable(ProxyShutdownEvent event) {
|
||||||
|
Subserver.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int softreload() {
|
||||||
|
ServerUtils.getInstance().getPlugin().getPluginManager().reloadPlugin("VelocityCore");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
26
Persistent/src/de/steamwar/bungeecore/Servertype.java
Normale Datei
26
Persistent/src/de/steamwar/bungeecore/Servertype.java
Normale Datei
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
|
public enum Servertype {
|
||||||
|
BAUSERVER,
|
||||||
|
ARENA,
|
||||||
|
BUILDER
|
||||||
|
}
|
52
Persistent/src/de/steamwar/bungeecore/Storage.java
Normale Datei
52
Persistent/src/de/steamwar/bungeecore/Storage.java
Normale Datei
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfoPacket;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class Storage {
|
||||||
|
public static final Map<Player, List<Player>> challenges = new HashMap<>();
|
||||||
|
|
||||||
|
public static final Map<Player, Player> lastChats = new HashMap<>();
|
||||||
|
|
||||||
|
public static final Map<Integer, List<Integer>> teamInvitations = new HashMap<>(); // UserID -> List<TeamIDs>
|
||||||
|
|
||||||
|
public static final Map<Player, Timestamp> sessions = new HashMap<>(); // Contains session start timestamp
|
||||||
|
|
||||||
|
public static final Map<Integer, Subserver> eventServer = new HashMap<>(); // TeamID -> Subserver map
|
||||||
|
|
||||||
|
public static final Map<Player, Integer> fabricCheckedPlayers = new HashMap<>();
|
||||||
|
|
||||||
|
public static final Map<Player, Long> fabricExpectPluginMessage = new HashMap<>();
|
||||||
|
|
||||||
|
public static final Map<Integer, ServerInfo> teamServers = new HashMap<>(); // TeamID -> ServerInfo map
|
||||||
|
|
||||||
|
public static final Map<Player, Map<UUID, UpsertPlayerInfoPacket.Entry>> directTabItems = new HashMap<>();
|
||||||
|
}
|
268
Persistent/src/de/steamwar/bungeecore/Subserver.java
Normale Datei
268
Persistent/src/de/steamwar/bungeecore/Subserver.java
Normale Datei
@ -0,0 +1,268 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class Subserver {
|
||||||
|
|
||||||
|
private static final Component PREFIX = Component
|
||||||
|
.text("Steam").color(NamedTextColor.YELLOW)
|
||||||
|
.append(Component.text("War» ").color(NamedTextColor.DARK_GRAY));
|
||||||
|
|
||||||
|
private static final Logger logger = Persistent.getInstance().getLogger();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static final List<Subserver> serverList = new LinkedList<>();
|
||||||
|
private static final Map<ServerInfo, Subserver> infoToServer = new HashMap<>();
|
||||||
|
|
||||||
|
public static Subserver getSubserver(Player p) {
|
||||||
|
synchronized (serverList) {
|
||||||
|
for (int i = serverList.size() - 1; i >= 0; i--) {
|
||||||
|
if (serverList.get(i).onServer(p))
|
||||||
|
return serverList.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Subserver getSubserver(ServerInfo server) {
|
||||||
|
synchronized (serverList) {
|
||||||
|
return infoToServer.get(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shutdown() {
|
||||||
|
while (!serverList.isEmpty()) {
|
||||||
|
Subserver server = serverList.get(0);
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String serverName;
|
||||||
|
private final boolean checkpoint;
|
||||||
|
private final Runnable shutdownCallback;
|
||||||
|
private final Consumer<Exception> failureCallback;
|
||||||
|
private final Process process;
|
||||||
|
private final PrintWriter writer;
|
||||||
|
@Getter
|
||||||
|
private final ServerInfo server;
|
||||||
|
@Getter
|
||||||
|
private RegisteredServer registeredServer;
|
||||||
|
@Getter
|
||||||
|
private final Servertype type;
|
||||||
|
private final Thread thread;
|
||||||
|
@Getter
|
||||||
|
private boolean started;
|
||||||
|
|
||||||
|
private final List<Player> cachedPlayers = new LinkedList<>();
|
||||||
|
@Getter
|
||||||
|
private final Map<Player, String> tablistNames = new HashMap<>();
|
||||||
|
|
||||||
|
protected Subserver(Servertype type, String serverName, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, Consumer<Exception> failureCallback) {
|
||||||
|
this.started = false;
|
||||||
|
this.serverName = serverName;
|
||||||
|
this.type = type;
|
||||||
|
this.shutdownCallback = shutdownCallback;
|
||||||
|
this.failureCallback = failureCallback == null ? this::fatalError : failureCallback;
|
||||||
|
this.checkpoint = processBuilder.command().contains("criu");
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.process = processBuilder.start();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new SecurityException("Server could not be started", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
InetSocketAddress address = new InetSocketAddress("127.0.0.1", port);
|
||||||
|
this.server = new ServerInfo(serverName, address);
|
||||||
|
this.writer = new PrintWriter(process.getOutputStream(), true);
|
||||||
|
|
||||||
|
this.thread = new Thread(this::run, "Subserver " + serverName);
|
||||||
|
this.thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
|
public boolean hasStarted() {
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendPlayer(Player p) {
|
||||||
|
if (!started) {
|
||||||
|
p.sendActionBar(generateBar(0));
|
||||||
|
cachedPlayers.add(p);
|
||||||
|
} else {
|
||||||
|
p.createConnectionRequest(registeredServer).connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute(String command) {
|
||||||
|
writer.println(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
try {
|
||||||
|
long pid = process.pid();
|
||||||
|
if (checkpoint)
|
||||||
|
pid = process.children().findAny().map(ProcessHandle::pid).orElse(pid);
|
||||||
|
|
||||||
|
Runtime.getRuntime().exec(new String[]{"kill", "-SIGUSR1", Long.toString(pid)});
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to send SIGUSR1 to subserver.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!process.waitFor(1, TimeUnit.MINUTES)) {
|
||||||
|
logger.log(Level.SEVERE, () -> serverName + " did not stop correctly, forcibly stopping!");
|
||||||
|
process.destroyForcibly();
|
||||||
|
}
|
||||||
|
|
||||||
|
thread.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.log(Level.SEVERE, "Subserver stop interrupted!", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onServer(Player p) {
|
||||||
|
return cachedPlayers.contains(p) || (registeredServer != null && registeredServer.getPlayersConnected().contains(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fatalError(Exception e) {
|
||||||
|
logger.log(Level.SEVERE, e, () -> serverName + " did not run correctly!");
|
||||||
|
|
||||||
|
for (Player cached : cachedPlayers)
|
||||||
|
cached.sendMessage(PREFIX.append(Component.text("Unexpected error during server startup.").color(NamedTextColor.RED)));
|
||||||
|
if (registeredServer != null) {
|
||||||
|
for (Player player : registeredServer.getPlayersConnected())
|
||||||
|
player.sendMessage(PREFIX.append(Component.text("Lost connection to server.").color(NamedTextColor.RED)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start(InputStream stream, Predicate<String> test) throws IOException {
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
|
||||||
|
String line = "";
|
||||||
|
while (!started && (line = reader.readLine()) != null) {
|
||||||
|
started = test.test(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line == null)
|
||||||
|
throw new IOException(serverName + " did not start correctly!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void register() {
|
||||||
|
if (Persistent.getInstance().getProxyServer().getServer(serverName).isPresent()) {
|
||||||
|
SecurityException e = new SecurityException("Server already registered: " + serverName);
|
||||||
|
stop();
|
||||||
|
failureCallback.accept(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (serverList) {
|
||||||
|
registeredServer = Persistent.getInstance().getProxyServer().registerServer(server);
|
||||||
|
serverList.add(this);
|
||||||
|
infoToServer.put(server, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unregister() {
|
||||||
|
synchronized (serverList) {
|
||||||
|
infoToServer.remove(server);
|
||||||
|
serverList.remove(this);
|
||||||
|
Persistent.getInstance().getProxyServer().unregisterServer(server);
|
||||||
|
registeredServer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void run() {
|
||||||
|
register();
|
||||||
|
|
||||||
|
Exception ex = null;
|
||||||
|
try {
|
||||||
|
if (checkpoint) {
|
||||||
|
start(process.getErrorStream(), line -> line.contains("Restore finished successfully."));
|
||||||
|
} else {
|
||||||
|
start(process.getInputStream(), line -> {
|
||||||
|
if (line.contains("Loading libraries, please wait"))
|
||||||
|
sendProgress(2);
|
||||||
|
else if (line.contains("Starting Minecraft server on"))
|
||||||
|
sendProgress(4);
|
||||||
|
else if (line.contains("Preparing start region"))
|
||||||
|
sendProgress(6);
|
||||||
|
return line.contains("Finished mapping loading");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sendProgress(8);
|
||||||
|
|
||||||
|
Thread.sleep(300);
|
||||||
|
|
||||||
|
sendProgress(10);
|
||||||
|
for (Player cachedPlayer : cachedPlayers) {
|
||||||
|
sendPlayer(cachedPlayer);
|
||||||
|
}
|
||||||
|
cachedPlayers.clear();
|
||||||
|
|
||||||
|
process.waitFor();
|
||||||
|
} catch (IOException e) {
|
||||||
|
ex = e;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
ex = e;
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
} finally {
|
||||||
|
unregister();
|
||||||
|
shutdownCallback.run();
|
||||||
|
if (ex != null)
|
||||||
|
failureCallback.accept(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component generateBar(int progress) {
|
||||||
|
return Component.text("⬛".repeat(Math.max(0, progress))).color(NamedTextColor.GOLD)
|
||||||
|
.append(Component.text("⬛".repeat(Math.max(0, 10 - progress))).color(NamedTextColor.DARK_GRAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendProgress(int progress) {
|
||||||
|
Component tc = generateBar(progress);
|
||||||
|
for (Player cached : cachedPlayers)
|
||||||
|
cached.sendActionBar(tc);
|
||||||
|
}
|
||||||
|
}
|
15
build.gradle
15
build.gradle
@ -18,13 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
// Adding the base plugin fixes the following gradle warnings in IntelliJ:
|
|
||||||
//
|
|
||||||
// Warning: root project 'module-work-multi': Unable to resolve all content root directories
|
|
||||||
// Details: java.lang.IllegalStateException: No value has been specified for this provider.
|
|
||||||
//
|
|
||||||
// Warning: root project 'module-work-multi': Unable to resolve additional project configuration.
|
|
||||||
// Details: java.lang.IllegalStateException: No value has been specified for this provider.
|
|
||||||
id 'base'
|
id 'base'
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'application'
|
id 'application'
|
||||||
@ -57,7 +50,8 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
allprojects {
|
||||||
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven {
|
maven {
|
||||||
url 'https://repo.papermc.io/repository/maven-public/'
|
url 'https://repo.papermc.io/repository/maven-public/'
|
||||||
@ -77,6 +71,7 @@ repositories {
|
|||||||
includeGroup 'com.lunarclient'
|
includeGroup 'com.lunarclient'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
@ -96,9 +91,7 @@ dependencies {
|
|||||||
|
|
||||||
annotationProcessor 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT'
|
annotationProcessor 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT'
|
||||||
compileOnly 'de.steamwar:velocity:RELEASE'
|
compileOnly 'de.steamwar:velocity:RELEASE'
|
||||||
//compileOnly 'de.steamwar:persistentbungeecore:RELEASE'
|
compileOnly project(":Persistent")
|
||||||
// TODO: Monorepo?
|
|
||||||
compileOnly files('persistentvelocitycore.jar')
|
|
||||||
|
|
||||||
implementation("net.dv8tion:JDA:4.4.0_352") {
|
implementation("net.dv8tion:JDA:4.4.0_352") {
|
||||||
exclude module: 'opus-java'
|
exclude module: 'opus-java'
|
||||||
|
@ -29,3 +29,4 @@ pluginManagement {
|
|||||||
rootProject.name = 'VelocityCore'
|
rootProject.name = 'VelocityCore'
|
||||||
|
|
||||||
include 'CommonCore'
|
include 'CommonCore'
|
||||||
|
include 'Persistent'
|
||||||
|
@ -21,16 +21,10 @@ package de.steamwar.bungeecore;
|
|||||||
|
|
||||||
import de.steamwar.sql.SchematicType;
|
import de.steamwar.sql.SchematicType;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static de.steamwar.bungeecore.util.YamlUtils.*;
|
public class ArenaMode extends GameModeConfig {
|
||||||
|
|
||||||
public class ArenaMode {
|
|
||||||
|
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
|
|
||||||
@ -50,18 +44,25 @@ public class ArenaMode {
|
|||||||
bySchemType.clear();
|
bySchemType.clear();
|
||||||
allModes.clear();
|
allModes.clear();
|
||||||
|
|
||||||
File folder = new File(VelocityCore.get().getDataDirectory().getParent().toFile(), "FightSystem");
|
GameModeConfig.loadAll(ArenaMode.class, (file, mode) -> {
|
||||||
for(File configFile : Arrays.stream(folder.listFiles((file, name) -> name.endsWith(".yml") && !name.endsWith(".kits.yml"))).sorted().toList()) {
|
if(mode.getServer() == null)
|
||||||
Map<String, Object> config;
|
return;
|
||||||
try {
|
|
||||||
config = loadYaml(configFile);
|
mode.config = file.getName();
|
||||||
} catch (IOException e) {
|
mode.internalName = file.getName().replace(".yml", "");
|
||||||
throw new SecurityException("Could not load SchematicTypes", e);
|
mode.getMaps().forEach(map -> mode.lowerToRealMapNames.put(map.toLowerCase(), map));
|
||||||
|
if(mode.getGameName() == null)
|
||||||
|
mode.setGameName(mode.internalName);
|
||||||
|
|
||||||
|
allModes.add(mode);
|
||||||
|
byInternal.put(mode.internalName, mode);
|
||||||
|
for(String name : mode.getServer().getChatNames()){
|
||||||
|
byChat.put(name.toLowerCase(), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config.containsKey("Server"))
|
if(mode.getSchematic() != null && mode.getSchemType() != null)
|
||||||
new ArenaMode(configFile.getName().replace(".yml", ""), config);
|
bySchemType.put(SchematicType.fromDB(mode.getSchemType()), mode);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArenaMode getByChat(String name){
|
public static ArenaMode getByChat(String name){
|
||||||
@ -75,17 +76,8 @@ public class ArenaMode {
|
|||||||
public static List<String> getAllChatNames(boolean historic) {
|
public static List<String> getAllChatNames(boolean historic) {
|
||||||
List<String> chatNames = new LinkedList<>();
|
List<String> chatNames = new LinkedList<>();
|
||||||
for(ArenaMode mode : byInternal.values()){
|
for(ArenaMode mode : byInternal.values()){
|
||||||
if(historic == mode.historic)
|
if(historic == mode.isHistoric())
|
||||||
chatNames.addAll(mode.chatNames);
|
chatNames.addAll(mode.getServer().getChatNames());
|
||||||
}
|
|
||||||
return chatNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> getAllRankedChatNames(){
|
|
||||||
List<String> chatNames = new LinkedList<>();
|
|
||||||
for(ArenaMode mode : byInternal.values()){
|
|
||||||
if(mode.isRanked())
|
|
||||||
chatNames.addAll(mode.chatNames);
|
|
||||||
}
|
}
|
||||||
return chatNames;
|
return chatNames;
|
||||||
}
|
}
|
||||||
@ -94,57 +86,16 @@ public class ArenaMode {
|
|||||||
return bySchemType.get(schemType);
|
return bySchemType.get(schemType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final String displayName;
|
|
||||||
@Getter
|
|
||||||
private final String folder;
|
|
||||||
private final List<String> chatNames;
|
|
||||||
@Getter
|
|
||||||
private final String serverJar;
|
|
||||||
@Getter
|
|
||||||
private final String config;
|
|
||||||
@Getter
|
|
||||||
private final List<String> maps;
|
|
||||||
private final Map<String, String> lowerToRealMapNames = new HashMap<>();
|
private final Map<String, String> lowerToRealMapNames = new HashMap<>();
|
||||||
@Getter
|
|
||||||
private final boolean historic;
|
|
||||||
@Getter
|
|
||||||
private final String internalName;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final boolean ranked;
|
private String internalName;
|
||||||
@Getter
|
@Getter
|
||||||
private final String schemType;
|
private String config;
|
||||||
|
|
||||||
private ArenaMode(String internalName, Map<String, Object> config) {
|
|
||||||
this.internalName = internalName;
|
|
||||||
this.config = internalName + ".yml";
|
|
||||||
|
|
||||||
this.displayName = get(config, "GameName", internalName);
|
|
||||||
Map<String, Object> server = get(config, "Server");
|
|
||||||
|
|
||||||
this.folder = get(server, "Folder");
|
|
||||||
this.serverJar = get(server, "ServerJar");
|
|
||||||
this.chatNames = get(server, "ChatNames");
|
|
||||||
this.maps = get(server, "Maps");
|
|
||||||
this.ranked = get(server, "Ranked", false);
|
|
||||||
this.historic = get(server, "Historic", false);
|
|
||||||
maps.forEach(map -> lowerToRealMapNames.put(map.toLowerCase(), map));
|
|
||||||
|
|
||||||
this.schemType = get(config, "Schematic.Type", "").toLowerCase();
|
|
||||||
|
|
||||||
allModes.add(this);
|
|
||||||
byInternal.put(internalName, this);
|
|
||||||
for(String name : chatNames){
|
|
||||||
byChat.put(name.toLowerCase(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!this.schemType.isEmpty())
|
|
||||||
bySchemType.put(SchematicType.fromDB(this.schemType), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String hasMap(String map){
|
public String hasMap(String map){
|
||||||
for(String m : maps){
|
for(String m : getMaps()) {
|
||||||
if(m.equalsIgnoreCase(map))
|
if(m.equalsIgnoreCase(map))
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
@ -152,7 +103,7 @@ public class ArenaMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getRandomMap(){
|
public String getRandomMap(){
|
||||||
return maps.get(random.nextInt(maps.size()));
|
return getMaps().get(random.nextInt(getMaps().size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String convertToRealMapName(String map){
|
public String convertToRealMapName(String map){
|
||||||
@ -160,11 +111,11 @@ public class ArenaMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getChatName(){
|
public String getChatName(){
|
||||||
return chatNames.get(0);
|
return getServer().getChatNames().get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean withoutChatName(){
|
public boolean withoutChatName(){
|
||||||
return chatNames.isEmpty();
|
return getServer().getChatNames().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
101
src/de/steamwar/bungeecore/GameModeConfig.java
Normale Datei
101
src/de/steamwar/bungeecore/GameModeConfig.java
Normale Datei
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 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;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.constructor.Constructor;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class GameModeConfig {
|
||||||
|
|
||||||
|
public static <T extends GameModeConfig> void loadAll(Class<T> config, BiConsumer<File, T> consumer) {
|
||||||
|
File folder = new File(VelocityCore.get().getDataDirectory().getParent().toFile(), "FightSystem");
|
||||||
|
if(!folder.exists())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Yaml yaml = new Yaml(new Constructor(config));
|
||||||
|
for(File file : Arrays.stream(folder.listFiles((file, name) -> name.endsWith(".yml") && !name.endsWith(".kits.yml"))).sorted().toList()) {
|
||||||
|
try {
|
||||||
|
consumer.accept(file, yaml.load(new FileInputStream(file)));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new SecurityException("Could not load GameModeConfig", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Server Server = null;
|
||||||
|
private List<String> CheckQuestions = Collections.emptyList();
|
||||||
|
private String deadline = null;
|
||||||
|
private Schematic Schematic = null;
|
||||||
|
@Setter
|
||||||
|
private String GameName;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public static class Server {
|
||||||
|
private String Folder;
|
||||||
|
private String ServerJar;
|
||||||
|
private List<String> ChatNames = Collections.emptyList();
|
||||||
|
private List<String> Maps;
|
||||||
|
private boolean Ranked = false;
|
||||||
|
private boolean Historic = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public static class Schematic {
|
||||||
|
private String Type;
|
||||||
|
private String Shortcut;
|
||||||
|
private String Material;
|
||||||
|
private boolean ManualCheck = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServerJar() {
|
||||||
|
return getServer().getServerJar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFolder() {
|
||||||
|
return getServer().getFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getMaps() {
|
||||||
|
return getServer().getMaps();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHistoric() {
|
||||||
|
return getServer().isHistoric();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRanked() {
|
||||||
|
return getServer().isRanked();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSchemType() {
|
||||||
|
return getSchematic().getType();
|
||||||
|
}
|
||||||
|
}
|
@ -53,7 +53,7 @@ public class ServerStarter {
|
|||||||
|
|
||||||
public ServerStarter arena(ArenaMode mode, String map) {
|
public ServerStarter arena(ArenaMode mode, String map) {
|
||||||
portrange = ARENA_PORTS;
|
portrange = ARENA_PORTS;
|
||||||
serverNameProvider = port -> mode.getDisplayName() + (port - portrange.start);
|
serverNameProvider = port -> mode.getGameName() + (port - portrange.start);
|
||||||
serverJar = mode.getServerJar();
|
serverJar = mode.getServerJar();
|
||||||
allowMerge = true;
|
allowMerge = true;
|
||||||
fightMap = map;
|
fightMap = map;
|
||||||
|
@ -56,9 +56,7 @@ import java.util.logging.Logger;
|
|||||||
@Plugin(
|
@Plugin(
|
||||||
id = "velocitycore",
|
id = "velocitycore",
|
||||||
name = "VelocityCore",
|
name = "VelocityCore",
|
||||||
dependencies = {
|
dependencies = { @Dependency(id = "persistentvelocitycore") }
|
||||||
@Dependency(id = "persistentvelocitycore")
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
public class VelocityCore {
|
public class VelocityCore {
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public class ChallengeCommand extends SWCommand {
|
|||||||
challenges.remove(p);
|
challenges.remove(p);
|
||||||
|
|
||||||
new ServerStarter().arena(mode, map).blueLeader(sender.getPlayer()).redLeader(target).callback(
|
new ServerStarter().arena(mode, map).blueLeader(sender.getPlayer()).redLeader(target).callback(
|
||||||
arena -> Chatter.broadcast().system("CHALLENGE_BROADCAST", "CHALLENGE_BROADCAST_HOVER", ClickEvent.runCommand("/arena " + arena.getServer().getName()), mode.getDisplayName(), p, target)
|
arena -> Chatter.broadcast().system("CHALLENGE_BROADCAST", "CHALLENGE_BROADCAST_HOVER", ClickEvent.runCommand("/arena " + arena.getServer().getName()), mode.getGameName(), p, target)
|
||||||
).start();
|
).start();
|
||||||
}else{
|
}else{
|
||||||
if(!challenges.containsKey(p)){
|
if(!challenges.containsKey(p)){
|
||||||
@ -60,8 +60,8 @@ public class ChallengeCommand extends SWCommand {
|
|||||||
|
|
||||||
challenges.get(p).add(target);
|
challenges.get(p).add(target);
|
||||||
|
|
||||||
sender.system("CHALLENGE_CHALLENGED", target, mode.getDisplayName());
|
sender.system("CHALLENGE_CHALLENGED", target, mode.getGameName());
|
||||||
Chatter.of(target).system("CHALLENGE_CHALLENGED_TARGET", p, mode.getDisplayName(), mode.getMaps().size() != 1 ? new Message("CHALLENGE_CHALLENGED_MAP", m) : "");
|
Chatter.of(target).system("CHALLENGE_CHALLENGED_TARGET", p, mode.getGameName(), mode.getMaps().size() != 1 ? new Message("CHALLENGE_CHALLENGED_MAP", m) : "");
|
||||||
|
|
||||||
Chatter.of(target).system("CHALLENGE_ACCEPT", new Message("CHALLENGE_ACCEPT_HOVER"), ClickEvent.runCommand("/challenge " + p.getUsername() + " " + mode.getChatName() + " " + m));
|
Chatter.of(target).system("CHALLENGE_ACCEPT", new Message("CHALLENGE_ACCEPT_HOVER"), ClickEvent.runCommand("/challenge " + p.getUsername() + " " + mode.getChatName() + " " + m));
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ public class FightCommand extends SWCommand {
|
|||||||
declineMerge.run(sender, mode, map);
|
declineMerge.run(sender, mode, map);
|
||||||
});
|
});
|
||||||
Arenaserver finalMergable = mergable;
|
Arenaserver finalMergable = mergable;
|
||||||
SWItem item = new SWItem(new Message("FIGHT_MERGE_INFO", mode.getDisplayName(), finalMergable.getMap()), 11);
|
SWItem item = new SWItem(new Message("FIGHT_MERGE_INFO", mode.getGameName(), finalMergable.getMap()), 11);
|
||||||
item.addLore(new Message("FIGHT_MERGE_INFO_LORE_1", finalMergable.getRegisteredServer().getPlayersConnected().toArray(new Player[1])[0].getUsername()));
|
item.addLore(new Message("FIGHT_MERGE_INFO_LORE_1", finalMergable.getRegisteredServer().getPlayersConnected().toArray(new Player[1])[0].getUsername()));
|
||||||
inventory.addItem(4, item, click -> {});
|
inventory.addItem(4, item, click -> {});
|
||||||
inventory.addItem(8, new SWItem(new Message("FIGHT_MERGE_ACCEPT"), 10), click -> {
|
inventory.addItem(8, new SWItem(new Message("FIGHT_MERGE_ACCEPT"), 10), click -> {
|
||||||
@ -127,7 +127,7 @@ public class FightCommand extends SWCommand {
|
|||||||
public void fight(@Validator("arenaPlayer") PlayerChatter sender, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
|
public void fight(@Validator("arenaPlayer") PlayerChatter sender, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
|
||||||
createArena(sender, "/fight ", true, arenaMode, map, false,
|
createArena(sender, "/fight ", true, arenaMode, map, false,
|
||||||
(p, mode, m) -> new ServerStarter().arena(mode, m).blueLeader(p.getPlayer()).callback(
|
(p, mode, m) -> new ServerStarter().arena(mode, m).blueLeader(p.getPlayer()).callback(
|
||||||
arena -> Chatter.broadcast().system("FIGHT_BROADCAST", "FIGHT_BROADCAST_HOVER", ClickEvent.runCommand("/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getPlayer().getUsername())
|
arena -> Chatter.broadcast().system("FIGHT_BROADCAST", "FIGHT_BROADCAST_HOVER", ClickEvent.runCommand("/arena " + arena.getServer().getName()), mode.getGameName(), p.getPlayer().getUsername())
|
||||||
).start()
|
).start()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public class HistoricCommand extends SWCommand {
|
|||||||
@Register
|
@Register
|
||||||
public void historic(@Validator("arenaPlayer") PlayerChatter player, @Mapper("historicArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
|
public void historic(@Validator("arenaPlayer") PlayerChatter player, @Mapper("historicArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
|
||||||
FightCommand.createArena(player, "/historic ", true, arenaMode, map, true, (p, mode, m) -> new ServerStarter().arena(mode, m).blueLeader(p.getPlayer()).callback(
|
FightCommand.createArena(player, "/historic ", true, arenaMode, map, true, (p, mode, m) -> new ServerStarter().arena(mode, m).blueLeader(p.getPlayer()).callback(
|
||||||
arena -> Chatter.broadcast().system("HISTORIC_BROADCAST", "HISTORIC_BROADCAST_HOVER", ClickEvent.runCommand("/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getPlayer())
|
arena -> Chatter.broadcast().system("HISTORIC_BROADCAST", "HISTORIC_BROADCAST_HOVER", ClickEvent.runCommand("/arena " + arena.getServer().getName()), mode.getGameName(), p.getPlayer())
|
||||||
).start());
|
).start());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,27 +20,30 @@
|
|||||||
package de.steamwar.bungeecore.discord.util;
|
package de.steamwar.bungeecore.discord.util;
|
||||||
|
|
||||||
import de.steamwar.bungeecore.discord.DiscordBot;
|
import de.steamwar.bungeecore.discord.DiscordBot;
|
||||||
import de.steamwar.bungeecore.discord.DiscordConfig;
|
|
||||||
import de.steamwar.sql.SteamwarUser;
|
import de.steamwar.sql.SteamwarUser;
|
||||||
|
import de.steamwar.sql.UserPerm;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
|
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.Set;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class DiscordRanks {
|
public class DiscordRanks {
|
||||||
|
|
||||||
|
private final Map<UserPerm.Prefix, String> prefixToPermName = UserPerm.prefixes.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, entry -> entry.getKey().name()));
|
||||||
|
|
||||||
public void update(SteamwarUser user) {
|
public void update(SteamwarUser user) {
|
||||||
if (user.getDiscordId() == null)
|
if (user.getDiscordId() == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Set<String> swRoles = new HashSet<>(DiscordConfig.RANKS.values());
|
Set<String> swRoles = new HashSet<>(DiscordBot.getInstance().getConfig().getRanks().values());
|
||||||
|
|
||||||
Guild guild = DiscordBot.getGuild();
|
Guild guild = DiscordBot.getGuild();
|
||||||
guild.retrieveMemberById(user.getDiscordId()).queue(member -> {
|
guild.retrieveMemberById(user.getDiscordId()).queue(member -> {
|
||||||
String prefixRole = DiscordConfig.RANKS.get(user.prefix());
|
String prefixRole = DiscordBot.getInstance().getConfig().getRanks().get(prefixToPermName.get(user.prefix()));
|
||||||
member.getRoles().stream()
|
member.getRoles().stream()
|
||||||
.filter(role -> swRoles.contains(role.getId()))
|
.filter(role -> swRoles.contains(role.getId()))
|
||||||
.filter(role -> !role.getId().equals(prefixRole))
|
.filter(role -> !role.getId().equals(prefixRole))
|
||||||
|
@ -21,7 +21,6 @@ package de.steamwar.bungeecore.network.handlers;
|
|||||||
|
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
|
||||||
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.bungeecore.tablist.TablistManager;
|
||||||
@ -45,13 +44,13 @@ public class FightInfoHandler extends PacketHandler {
|
|||||||
|
|
||||||
@Handler
|
@Handler
|
||||||
public void handle(FightInfoPacket packet) {
|
public void handle(FightInfoPacket packet) {
|
||||||
ServerInfo info = ((ServerMetaInfo) packet.getMetaInfos()).getSender().getServerInfo();
|
RegisteredServer server = ((ServerMetaInfo) packet.getMetaInfos()).getSender().getServer();
|
||||||
|
|
||||||
FightInfoPacket lobbyPacket = packet.withServerName(info.getName());
|
FightInfoPacket lobbyPacket = packet.withServerName(server.getServerInfo().getName());
|
||||||
|
|
||||||
TablistManager.newFightInfo(info, packet);
|
TablistManager.newFightInfo(server, packet);
|
||||||
|
|
||||||
lobbys.removeIf(server -> server.getPlayersConnected().isEmpty());
|
lobbys.removeIf(s -> s.getPlayersConnected().isEmpty());
|
||||||
lobbys.forEach(lobby -> NetworkSender.send(lobby, lobbyPacket));
|
lobbys.forEach(lobby -> NetworkSender.send(lobby, lobbyPacket));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,46 +19,48 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore.tablist;
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
|
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
|
||||||
|
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||||
|
import com.velocitypowered.proxy.network.Connections;
|
||||||
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfoPacket;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.UpdateTeamsPacket;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfoPacket;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
|
||||||
import de.steamwar.bungeecore.Storage;
|
import de.steamwar.bungeecore.Storage;
|
||||||
|
import de.steamwar.bungeecore.VelocityCore;
|
||||||
import de.steamwar.messages.Chatter;
|
import de.steamwar.messages.Chatter;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
import io.netty.util.ReferenceCountUtil;
|
||||||
import net.md_5.bungee.ServerConnection;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.md_5.bungee.UserConnection;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
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.netty.PipelineUtils;
|
|
||||||
import net.md_5.bungee.protocol.DefinedPacket;
|
|
||||||
import net.md_5.bungee.protocol.Either;
|
|
||||||
import net.md_5.bungee.protocol.PacketWrapper;
|
|
||||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
|
||||||
import net.md_5.bungee.protocol.packet.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
@ChannelHandler.Sharable
|
@ChannelHandler.Sharable
|
||||||
public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
|
public class Tablist extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
private static final UUID[] uuids = IntStream.range(0, 80).mapToObj(i -> UUID.randomUUID()).toArray(UUID[]::new);
|
private static final UUID[] swUuids = IntStream.range(0, 80).mapToObj(i -> UUID.randomUUID()).toArray(UUID[]::new);
|
||||||
private static final String[] names = IntStream.range(0, 80).mapToObj(i -> " »SW« " + String.format("%02d", i)).toArray(String[]::new);
|
private static final String[] swNames = IntStream.range(0, 80).mapToObj(i -> " »SW« " + String.format("%02d", i)).toArray(String[]::new);
|
||||||
private static final String TAB_TEAM = "zzzzzsw-tab";
|
private static final String TAB_TEAM = "zzzzzsw-tab";
|
||||||
private static final Team teamPacket = new Team(TAB_TEAM, (byte) 0, Either.right(TextComponent.fromLegacy("")), Either.right(TextComponent.fromLegacy("")), Either.right(TextComponent.fromLegacy("")), "never", "always", 21, (byte)0x00, names);
|
private static final UpdateTeamsPacket createTeamPacket = new UpdateTeamsPacket(TAB_TEAM, UpdateTeamsPacket.Mode.CREATE, Component.empty(), Component.empty(), Component.empty(), UpdateTeamsPacket.NameTagVisibility.NEVER, UpdateTeamsPacket.CollisionRule.ALWAYS, 21, (byte)0x00, Arrays.stream(swNames).toList());
|
||||||
|
|
||||||
private final Map<UUID, PlayerListItem.Item> directTabItems;
|
private final Map<UUID, UpsertPlayerInfoPacket.Entry> directTabItems;
|
||||||
private final Set<UUID> npcs = new HashSet<>();
|
private final Set<UUID> npcs = new HashSet<>();
|
||||||
private final List<PlayerListItem.Item> current = new ArrayList<>();
|
private final List<UpsertPlayerInfoPacket.Entry> current = new ArrayList<>();
|
||||||
|
|
||||||
private final ProxiedPlayer player;
|
private final Player player;
|
||||||
private final Chatter viewer;
|
private final Chatter viewer;
|
||||||
private ServerConnection connection;
|
private VelocityServerConnection connection;
|
||||||
|
|
||||||
public Tablist(ProxiedPlayer player) {
|
public Tablist(Player player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.viewer = Chatter.of(player);
|
this.viewer = Chatter.of(player);
|
||||||
this.directTabItems = Storage.directTabItems.computeIfAbsent(player, p -> new HashMap<>());
|
this.directTabItems = Storage.directTabItems.computeIfAbsent(player, p -> new HashMap<>());
|
||||||
@ -69,7 +71,8 @@ public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
|
|||||||
if (connection == null)
|
if (connection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
player.setTabHeader(header(viewer, seconds), viewer.parse(false, "TABLIST_FOOTER", connection.getInfo().getName(), ping(), ProxyServer.getInstance().getPlayers().size()));
|
player.sendPlayerListHeaderAndFooter(header(viewer, seconds), viewer.parse(false, "TABLIST_FOOTER", connection.getServerInfo().getName(), ping(), VelocityCore.getProxy().getPlayerCount()));
|
||||||
|
player.getTabList();
|
||||||
|
|
||||||
List<TablistPart.Item> tablist = new ArrayList<>();
|
List<TablistPart.Item> tablist = new ArrayList<>();
|
||||||
List<TablistPart.Item> direct = new ArrayList<>();
|
List<TablistPart.Item> direct = new ArrayList<>();
|
||||||
@ -78,28 +81,28 @@ public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
|
|||||||
// NPC handling
|
// NPC handling
|
||||||
List<String> addNpc = new ArrayList<>();
|
List<String> addNpc = new ArrayList<>();
|
||||||
List<String> removeNpc = new ArrayList<>();
|
List<String> removeNpc = new ArrayList<>();
|
||||||
List<PlayerListItem.Item> update = new ArrayList<>();
|
List<UpsertPlayerInfoPacket.Entry> update = new ArrayList<>();
|
||||||
Set<UUID> nonNPCs = direct.stream().map(TablistPart.Item::getUuid).collect(Collectors.toSet());
|
Set<UUID> nonNPCs = direct.stream().map(TablistPart.Item::getUuid).collect(Collectors.toSet());
|
||||||
synchronized (directTabItems) {
|
synchronized (directTabItems) {
|
||||||
for (TablistPart.Item item : direct) {
|
for (TablistPart.Item item : direct) {
|
||||||
PlayerListItem.Item tabItem = directTabItems.get(item.getUuid());
|
UpsertPlayerInfoPacket.Entry tabItem = directTabItems.get(item.getUuid());
|
||||||
|
|
||||||
if(npcs.remove(item.getUuid()))
|
if(npcs.remove(item.getUuid()))
|
||||||
removeNpc.add(tabItem.getUsername());
|
removeNpc.add(tabItem.getProfile().getName());
|
||||||
|
|
||||||
if(tabItem == null) {
|
if(tabItem == null) {
|
||||||
tablist.add(0, item);
|
tablist.add(0, item);
|
||||||
} else if(!tabItem.getDisplayName().equals(item.getDisplayName())) {
|
} else if(!item.getDisplayName().equals(getDisplayName(tabItem))) {
|
||||||
tabItem.setDisplayName(item.getDisplayName());
|
tabItem.setDisplayName(new ComponentHolder(player.getProtocolVersion(), item.getDisplayName()));
|
||||||
tabItem.setListed(true);
|
tabItem.setListed(true);
|
||||||
update.add(tabItem);
|
update.add(tabItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean playerNotOnTeamserver = !Storage.teamServers.containsValue(player.getServer().getInfo());
|
boolean playerNotOnTeamserver = !Storage.teamServers.containsValue(player.getCurrentServer().orElseThrow().getServerInfo());
|
||||||
for(PlayerListItem.Item item : directTabItems.values()) {
|
for(UpsertPlayerInfoPacket.Entry item : directTabItems.values()) {
|
||||||
if(playerNotOnTeamserver && !nonNPCs.contains(item.getUuid()) && !npcs.contains(item.getUuid()) && !player.getUniqueId().equals(item.getUuid())) {
|
if(playerNotOnTeamserver && !nonNPCs.contains(item.getProfileId()) && !npcs.contains(item.getProfileId()) && !player.getUniqueId().equals(item.getProfileId())) {
|
||||||
npcs.add(item.getUuid());
|
npcs.add(item.getProfileId());
|
||||||
addNpc.add(item.getUsername());
|
addNpc.add(item.getProfile().getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,32 +111,31 @@ public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
|
|||||||
|
|
||||||
// Main list handling
|
// Main list handling
|
||||||
int i = 0;
|
int i = 0;
|
||||||
List<PlayerListItem.Item> add = new ArrayList<>();
|
List<UpsertPlayerInfoPacket.Entry> add = new ArrayList<>();
|
||||||
List<PlayerListItem.Item> remove = new ArrayList<>();
|
List<UpsertPlayerInfoPacket.Entry> remove = new ArrayList<>();
|
||||||
for (; i < tablist.size() && i < 80; i++) {
|
for (; i < tablist.size() && i < 80; i++) {
|
||||||
PlayerListItem.Item tabItem;
|
TablistPart.Item item = tablist.get(i);
|
||||||
|
UpsertPlayerInfoPacket.Entry tabItem;
|
||||||
if(current.size() > i) {
|
if(current.size() > i) {
|
||||||
tabItem = current.get(i);
|
tabItem = current.get(i);
|
||||||
} else {
|
} else {
|
||||||
tabItem = new PlayerListItem.Item();
|
tabItem = new UpsertPlayerInfoPacket.Entry(swUuids[i]);
|
||||||
tabItem.setUuid(uuids[i]);
|
tabItem.setProfile(new GameProfile(swUuids[i], swNames[i], Collections.emptyList()));
|
||||||
tabItem.setUsername(names[i]);
|
tabItem.setGameMode(1);
|
||||||
tabItem.setGamemode(1);
|
|
||||||
tabItem.setListed(true);
|
tabItem.setListed(true);
|
||||||
tabItem.setPing(1000);
|
tabItem.setLatency(1000);
|
||||||
current.add(tabItem);
|
current.add(tabItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
TablistPart.Item item = tablist.get(i);
|
if(!tabItem.getProfile().getProperties().equals(item.getProperties())) {
|
||||||
if(!Arrays.equals(tabItem.getProperties(), item.getProperties())) {
|
tabItem.setProfile(new GameProfile(tabItem.getProfile().getId(), tabItem.getProfile().getName(), item.getProperties()));
|
||||||
tabItem.setProperties(item.getProperties());
|
tabItem.setDisplayName(new ComponentHolder(player.getProtocolVersion(), item.getDisplayName()));
|
||||||
tabItem.setDisplayName(item.getDisplayName());
|
|
||||||
add.add(tabItem);
|
add.add(tabItem);
|
||||||
if(current.size() > i) {
|
if(current.size() > i) {
|
||||||
remove.add(tabItem);
|
remove.add(tabItem);
|
||||||
}
|
}
|
||||||
} else if(!item.getDisplayName().equals(tabItem.getDisplayName())) {
|
} else if(!item.getDisplayName().equals(getDisplayName(tabItem))) {
|
||||||
tabItem.setDisplayName(item.getDisplayName());
|
tabItem.setDisplayName(new ComponentHolder(player.getProtocolVersion(), item.getDisplayName()));
|
||||||
update.add(tabItem);
|
update.add(tabItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,208 +145,127 @@ public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
|
|||||||
remove.add(current.remove(i));
|
remove.add(current.remove(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTabPacket(remove, PlayerListItem.Action.REMOVE_PLAYER);
|
sendTabPacket(remove, null);
|
||||||
sendTabPacket(update, PlayerListItem.Action.UPDATE_DISPLAY_NAME);
|
sendTabPacket(update, UpsertPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME);
|
||||||
sendTabPacket(add, PlayerListItem.Action.ADD_PLAYER);
|
sendTabPacket(add, UpsertPlayerInfoPacket.Action.ADD_PLAYER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServerSwitch() {
|
public void onServerSwitch() {
|
||||||
injection();
|
injection();
|
||||||
|
|
||||||
synchronized (directTabItems) {
|
synchronized (directTabItems) {
|
||||||
sendNpcPacket(npcs.stream().map(npc -> directTabItems.get(npc).getUsername()).collect(Collectors.toList()), true);
|
sendNpcPacket(npcs.stream().map(npc -> directTabItems.get(npc).getProfile().getName()).toList(), true);
|
||||||
directTabItems.clear();
|
directTabItems.clear();
|
||||||
npcs.clear();
|
npcs.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void injection() {
|
private void injection() {
|
||||||
connection = (ServerConnection) player.getServer();
|
connection = (VelocityServerConnection) player.getCurrentServer().orElse(null);
|
||||||
|
if(connection == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if(connection != null) {
|
ChannelPipeline pipeline = connection.getConnection().getChannel().pipeline();
|
||||||
ChannelPipeline pipeline = connection.getCh().getHandle().pipeline();
|
|
||||||
if(pipeline.get("steamwar-tablist") != null) //Catch unclean exit
|
if(pipeline.get("steamwar-tablist") != null) //Catch unclean exit
|
||||||
pipeline.remove("steamwar-tablist");
|
pipeline.remove("steamwar-tablist");
|
||||||
|
|
||||||
pipeline.addBefore(PipelineUtils.BOSS_HANDLER, "steamwar-tablist", this);
|
pipeline.addBefore(Connections.HANDLER, "steamwar-tablist", this);
|
||||||
sendQueued(player, teamPacket);
|
sendPacket(player, createTeamPacket);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disable() {
|
public void disable() {
|
||||||
sendTabPacket(current, PlayerListItem.Action.REMOVE_PLAYER);
|
sendTabPacket(current, null);
|
||||||
current.clear();
|
current.clear();
|
||||||
synchronized (directTabItems) {
|
synchronized (directTabItems) {
|
||||||
sendNpcPacket(npcs.stream().map(npc -> directTabItems.get(npc).getUsername()).collect(Collectors.toList()), true);
|
sendNpcPacket(npcs.stream().map(npc -> directTabItems.get(npc).getProfile().getName()).collect(Collectors.toList()), true);
|
||||||
npcs.clear();
|
npcs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(connection != null)
|
if(connection != null)
|
||||||
connection.getCh().getHandle().pipeline().remove(this);
|
connection.getConnection().getChannel().pipeline().remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void decode(ChannelHandlerContext ctx, PacketWrapper packetWrapper, List<Object> out) {
|
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||||
if(!connection.isObsolete()) {
|
if(msg instanceof UpsertPlayerInfoPacket packet) {
|
||||||
DefinedPacket packet = packetWrapper.packet;
|
packet.getActions().remove(UpsertPlayerInfoPacket.Action.INITIALIZE_CHAT);
|
||||||
|
packet.getActions().remove(UpsertPlayerInfoPacket.Action.UPDATE_LATENCY);
|
||||||
if(packet instanceof PlayerListHeaderFooter) {
|
packet.getActions().remove(UpsertPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME);
|
||||||
packetWrapper.trySingleRelease();
|
packet.getActions().remove(UpsertPlayerInfoPacket.Action.UPDATE_LISTED);
|
||||||
|
if(packet.getActions().isEmpty()) {
|
||||||
|
ReferenceCountUtil.release(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(packet instanceof PlayerListItem) {
|
if(packet.containsAction(UpsertPlayerInfoPacket.Action.ADD_PLAYER)) {
|
||||||
PlayerListItem list = (PlayerListItem) packet;
|
for (UpsertPlayerInfoPacket.Entry entry : packet.getEntries()) {
|
||||||
PlayerListItem.Action action = list.getAction();
|
entry.setLatency(1);
|
||||||
|
entry.setChatSession(null);
|
||||||
|
|
||||||
switch(action) {
|
if (!Storage.teamServers.containsValue(connection.getServerInfo())) {
|
||||||
case UPDATE_LATENCY:
|
entry.setDisplayName(new ComponentHolder(player.getProtocolVersion(), Component.empty()));
|
||||||
case UPDATE_DISPLAY_NAME:
|
entry.setListed(false);
|
||||||
packetWrapper.trySingleRelease();
|
} else if (entry.getDisplayName() == null) {
|
||||||
return;
|
entry.setDisplayName(new ComponentHolder(player.getProtocolVersion(), Component.text(entry.getProfile().getName()).color(NamedTextColor.GRAY)));
|
||||||
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:
|
|
||||||
boolean playerNotOnTeamserver = !Storage.teamServers.containsValue(player.getServer().getInfo());
|
|
||||||
for (PlayerListItem.Item item : list.getItems()) {
|
|
||||||
item.setPing(1);
|
|
||||||
if (playerNotOnTeamserver) {
|
|
||||||
item.setDisplayName(new TextComponent());
|
|
||||||
item.setListed(false);
|
|
||||||
} else if (item.getDisplayName() == null) {
|
|
||||||
item.setDisplayName(TextComponent.fromLegacy("§7" + item.getUsername()));
|
|
||||||
}
|
|
||||||
item.setPublicKey(null);
|
|
||||||
if(!player.getUniqueId().equals(item.getUuid()) && item.getGamemode() == 3)
|
|
||||||
item.setGamemode(1);
|
|
||||||
|
|
||||||
synchronized (directTabItems) {
|
synchronized (directTabItems) {
|
||||||
directTabItems.put(item.getUuid(), item);
|
directTabItems.put(entry.getProfileId(), entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case REMOVE_PLAYER:
|
packet.addAction(UpsertPlayerInfoPacket.Action.UPDATE_LISTED);
|
||||||
|
packet.addAction(UpsertPlayerInfoPacket.Action.UPDATE_LATENCY);
|
||||||
|
packet.addAction(UpsertPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME);
|
||||||
|
packet.addAction(UpsertPlayerInfoPacket.Action.UPDATE_GAME_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(packet.containsAction(UpsertPlayerInfoPacket.Action.UPDATE_GAME_MODE)) {
|
||||||
|
for(UpsertPlayerInfoPacket.Entry entry : packet.getEntries()) {
|
||||||
|
if(!entry.getProfileId().equals(player.getUniqueId()) && entry.getGameMode() == 3)
|
||||||
|
entry.setGameMode(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(msg instanceof RemovePlayerInfoPacket packet) {
|
||||||
List<String> names = new ArrayList<>();
|
List<String> names = new ArrayList<>();
|
||||||
for(PlayerListItem.Item item : list.getItems()) {
|
for(UUID uuid : packet.getProfilesToRemove()) {
|
||||||
synchronized (directTabItems) {
|
synchronized (directTabItems) {
|
||||||
PlayerListItem.Item directItem = directTabItems.remove(item.getUuid());
|
UpsertPlayerInfoPacket.Entry directItem = directTabItems.remove(uuid);
|
||||||
if(npcs.remove(item.getUuid()))
|
|
||||||
names.add(directItem.getUsername());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sendNpcPacket(names, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if(packet instanceof PlayerListItemRemove) {
|
|
||||||
List<String> names = new ArrayList<>();
|
|
||||||
for(UUID uuid : ((PlayerListItemRemove) packet).getUuids()) {
|
|
||||||
synchronized (directTabItems) {
|
|
||||||
PlayerListItem.Item directItem = directTabItems.remove(uuid);
|
|
||||||
if(npcs.remove(uuid))
|
if(npcs.remove(uuid))
|
||||||
names.add(directItem.getUsername());
|
names.add(directItem.getProfile().getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendNpcPacket(names, true);
|
sendNpcPacket(names, true);
|
||||||
} else if(packet instanceof PlayerListItemUpdate) {
|
}
|
||||||
PlayerListItemUpdate list = (PlayerListItemUpdate) packet;
|
|
||||||
EnumSet<PlayerListItemUpdate.Action> actions = list.getActions();
|
ctx.fireChannelRead(msg);
|
||||||
actions.remove(PlayerListItemUpdate.Action.INITIALIZE_CHAT);
|
}
|
||||||
actions.remove(PlayerListItemUpdate.Action.UPDATE_LATENCY);
|
|
||||||
actions.remove(PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME);
|
private void sendTabPacket(List<UpsertPlayerInfoPacket.Entry> items, UpsertPlayerInfoPacket.Action action) { //Breaks in 1.19.3 if action != UPDATE_DISPLAY_NAME, ADD_PLAYER or REMOVE_PLAYER
|
||||||
actions.remove(PlayerListItemUpdate.Action.UPDATE_LISTED);
|
if(items.isEmpty())
|
||||||
if(actions.isEmpty()) {
|
return;
|
||||||
packetWrapper.trySingleRelease();
|
|
||||||
|
if(action == null) { //REMOVE
|
||||||
|
sendPacket(player, new RemovePlayerInfoPacket(items.stream().map(item -> item.getProfile().getId()).toList()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean playerNotOnTeamserver = !Storage.teamServers.containsValue(player.getServer().getInfo());
|
sendPacket(player, new UpsertPlayerInfoPacket(
|
||||||
for(PlayerListItemUpdate.Action action : actions) {
|
action == UpsertPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME ? EnumSet.of(UpsertPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, UpsertPlayerInfoPacket.Action.UPDATE_LISTED) : EnumSet.of(UpsertPlayerInfoPacket.Action.ADD_PLAYER, UpsertPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, UpsertPlayerInfoPacket.Action.UPDATE_LATENCY, UpsertPlayerInfoPacket.Action.UPDATE_LISTED, UpsertPlayerInfoPacket.Action.UPDATE_GAME_MODE),
|
||||||
switch (action) {
|
items
|
||||||
case ADD_PLAYER:
|
));
|
||||||
for (PlayerListItem.Item item : list.getItems()) {
|
|
||||||
item.setPing(1);
|
|
||||||
if (playerNotOnTeamserver) {
|
|
||||||
item.setDisplayName(new TextComponent());
|
|
||||||
item.setListed(false);
|
|
||||||
} else if (item.getDisplayName() == null) {
|
|
||||||
item.setDisplayName(TextComponent.fromLegacy("§7" + item.getUsername()));
|
|
||||||
}
|
|
||||||
item.setPublicKey(null);
|
|
||||||
if(!player.getUniqueId().equals(item.getUuid()) && item.getGamemode() == 3)
|
|
||||||
item.setGamemode(1);
|
|
||||||
|
|
||||||
synchronized (directTabItems) {
|
|
||||||
directTabItems.put(item.getUuid(), item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
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 UPDATE_LISTED:
|
|
||||||
case INITIALIZE_CHAT:
|
|
||||||
case UPDATE_LATENCY:
|
|
||||||
case UPDATE_DISPLAY_NAME:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(actions.contains(PlayerListItemUpdate.Action.ADD_PLAYER)) {
|
|
||||||
actions.add(PlayerListItemUpdate.Action.UPDATE_LISTED);
|
|
||||||
actions.add(PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME);
|
|
||||||
actions.add(PlayerListItemUpdate.Action.UPDATE_LATENCY);
|
|
||||||
actions.add(PlayerListItemUpdate.Action.UPDATE_GAMEMODE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out.add(packetWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean oldTab() {
|
|
||||||
return player.getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_19_3;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendTabPacket(List<PlayerListItem.Item> items, PlayerListItem.Action action) { //Breaks in 1.19.3 if action != UPDATE_DISPLAY_NAME, ADD_PLAYER or REMOVE_PLAYER
|
|
||||||
if(!items.isEmpty()) {
|
|
||||||
if(oldTab()) {
|
|
||||||
PlayerListItem packet = new PlayerListItem();
|
|
||||||
packet.setAction(action);
|
|
||||||
packet.setItems(items.toArray(new PlayerListItem.Item[0]));
|
|
||||||
sendQueued(player, packet);
|
|
||||||
} else if(action == PlayerListItem.Action.REMOVE_PLAYER) {
|
|
||||||
PlayerListItemRemove packet = new PlayerListItemRemove();
|
|
||||||
packet.setUuids(items.stream().map(PlayerListItem.Item::getUuid).toArray(UUID[]::new));
|
|
||||||
sendQueued(player, packet);
|
|
||||||
} else {
|
|
||||||
PlayerListItemUpdate packet = new PlayerListItemUpdate();
|
|
||||||
packet.setActions(action == PlayerListItem.Action.UPDATE_DISPLAY_NAME ? EnumSet.of(PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME, PlayerListItemUpdate.Action.UPDATE_LISTED) : EnumSet.of(PlayerListItemUpdate.Action.ADD_PLAYER, PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME, PlayerListItemUpdate.Action.UPDATE_LATENCY, PlayerListItemUpdate.Action.UPDATE_LISTED, PlayerListItemUpdate.Action.UPDATE_GAMEMODE));
|
|
||||||
packet.setItems(items.toArray(new PlayerListItem.Item[0]));
|
|
||||||
sendQueued(player, packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendNpcPacket(List<String> names, boolean remove) {
|
private void sendNpcPacket(List<String> names, boolean remove) {
|
||||||
if(!names.isEmpty()) {
|
if(!names.isEmpty()) {
|
||||||
Team packet = new Team(TAB_TEAM);
|
UpdateTeamsPacket packet = new UpdateTeamsPacket();
|
||||||
packet.setMode((byte) (remove ? 4 : 3));
|
packet.setMode(remove ? UpdateTeamsPacket.Mode.REMOVE_PLAYER : UpdateTeamsPacket.Mode.ADD_PLAYER);
|
||||||
packet.setPlayers(names.toArray(new String[0]));
|
packet.setPlayers(names);
|
||||||
sendQueued(player, packet);
|
sendPacket(player, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BaseComponent header(Chatter p, int seconds) {
|
private Component header(Chatter p, int seconds) {
|
||||||
int phase = (seconds % 10) / 5;
|
int phase = (seconds % 10) / 5;
|
||||||
if (phase == 0)
|
if (phase == 0)
|
||||||
return p.parse(false, "TABLIST_PHASE_DISCORD");
|
return p.parse(false, "TABLIST_PHASE_DISCORD");
|
||||||
@ -353,7 +274,7 @@ public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String ping() {
|
private String ping() {
|
||||||
int ping = player.getPing();
|
long ping = player.getPing();
|
||||||
if (ping < 50) {
|
if (ping < 50) {
|
||||||
return "§a" + ping;
|
return "§a" + ping;
|
||||||
} else if (ping < 150) {
|
} else if (ping < 150) {
|
||||||
@ -363,7 +284,15 @@ public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sendQueued(ProxiedPlayer player, DefinedPacket packet) {
|
private Component getDisplayName(UpsertPlayerInfoPacket.Entry entry) {
|
||||||
((UserConnection)player).sendPacketQueued(packet);
|
ComponentHolder displayName = entry.getDisplayName();
|
||||||
|
if(displayName == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return displayName.getComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendPacket(Player player, MinecraftPacket packet) {
|
||||||
|
((ConnectedPlayer) player).getConnection().write(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore.tablist;
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import de.steamwar.bungeecore.Servertype;
|
import de.steamwar.bungeecore.Servertype;
|
||||||
import de.steamwar.bungeecore.Subserver;
|
import de.steamwar.bungeecore.Subserver;
|
||||||
|
import de.steamwar.bungeecore.VelocityCore;
|
||||||
import de.steamwar.messages.Chatter;
|
import de.steamwar.messages.Chatter;
|
||||||
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.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -34,19 +34,19 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
public class TablistBuild implements TablistPart {
|
public class TablistBuild implements TablistPart {
|
||||||
|
|
||||||
private final List<ServerInfo> servers = new ArrayList<>();
|
private final List<RegisteredServer> servers = new ArrayList<>();
|
||||||
private final Map<ServerInfo, List<Item>> players = new HashMap<>();
|
private final Map<RegisteredServer, List<Item>> players = new HashMap<>();
|
||||||
|
|
||||||
public TablistBuild() {
|
public TablistBuild() {
|
||||||
for (ServerInfo server : new ArrayList<>(ProxyServer.getInstance().getServers().values())){
|
for (RegisteredServer server : VelocityCore.getProxy().getAllServers()){
|
||||||
Subserver subserver = Subserver.getSubserver(server);
|
Subserver subserver = Subserver.getSubserver(server.getServerInfo());
|
||||||
if(server.getPlayers().isEmpty() || subserver == null || subserver.getType() != Servertype.BAUSERVER)
|
if(server.getPlayersConnected().isEmpty() || subserver == null || subserver.getType() != Servertype.BAUSERVER)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
servers.add(server);
|
servers.add(server);
|
||||||
players.put(server, server.getPlayers().stream().sorted(((p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName()))).map(Item::new).collect(Collectors.toList()));
|
players.put(server, server.getPlayersConnected().stream().sorted(((p1, p2) -> p1.getUsername().compareToIgnoreCase(p2.getUsername()))).map(Item::new).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
servers.sort((s1, s2) -> s1.getName().compareToIgnoreCase(s2.getName()));
|
servers.sort((s1, s2) -> s1.getServerInfo().getName().compareToIgnoreCase(s2.getServerInfo().getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -55,14 +55,14 @@ public class TablistBuild implements TablistPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void print(Chatter viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct) {
|
public void print(Chatter viewer, Player player, List<Item> tablist, List<Item> direct) {
|
||||||
ServerInfo server = player.getServer().getInfo();
|
RegisteredServer server = player.getCurrentServer().orElseThrow().getServer();
|
||||||
if(players.keySet().stream().anyMatch(info -> server != info)) {
|
if(players.keySet().stream().anyMatch(info -> server != info)) {
|
||||||
tablist.add(new Item(null, "", TablistServer.GRAY));
|
tablist.add(new Item(null, "", TablistServer.GRAY));
|
||||||
tablist.add(new Item(null, viewer.parseToLegacy("TABLIST_BAU"), TablistServer.LIGHT_GRAY));
|
tablist.add(new Item(null, viewer.parseToLegacy("TABLIST_BAU"), TablistServer.LIGHT_GRAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ServerInfo info : servers) {
|
for (RegisteredServer info : servers) {
|
||||||
TablistServer.teamify(players.get(info), player)
|
TablistServer.teamify(players.get(info), player)
|
||||||
.forEach(((server == info) ? direct : tablist)::add);
|
.forEach(((server == info) ? direct : tablist)::add);
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore.tablist;
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import de.steamwar.messages.Chatter;
|
import de.steamwar.messages.Chatter;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ public class TablistGroup implements TablistPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void print(Chatter viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct) {
|
public void print(Chatter viewer, Player player, List<Item> tablist, List<Item> direct) {
|
||||||
for (TablistPart sublist : sublists) {
|
for (TablistPart sublist : sublists) {
|
||||||
sublist.print(viewer, player, tablist, direct);
|
sublist.print(viewer, player, tablist, direct);
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,23 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore.tablist;
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
|
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
||||||
|
import com.velocitypowered.api.event.connection.PostLoginEvent;
|
||||||
|
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import de.steamwar.bungeecore.Servertype;
|
||||||
|
import de.steamwar.bungeecore.Storage;
|
||||||
|
import de.steamwar.bungeecore.Subserver;
|
||||||
import de.steamwar.bungeecore.VelocityCore;
|
import de.steamwar.bungeecore.VelocityCore;
|
||||||
import de.steamwar.bungeecore.listeners.BasicListener;
|
import de.steamwar.bungeecore.listeners.BasicListener;
|
||||||
import de.steamwar.network.packets.common.FightInfoPacket;
|
import de.steamwar.network.packets.common.FightInfoPacket;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class TablistManager extends BasicListener {
|
public class TablistManager extends BasicListener {
|
||||||
@ -48,22 +58,22 @@ public class TablistManager extends BasicListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@Subscribe
|
||||||
public void onJoin(PostLoginEvent event) {
|
public void onJoin(PostLoginEvent event) {
|
||||||
synchronized (tablists) {
|
synchronized (tablists) {
|
||||||
tablists.put(event.getPlayer(), new Tablist(event.getPlayer()));
|
tablists.put(event.getPlayer(), new Tablist(event.getPlayer()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@Subscribe
|
||||||
public void onServerConnection(ServerSwitchEvent event) {
|
public void onServerConnection(ServerConnectedEvent event) {
|
||||||
synchronized (tablists) {
|
synchronized (tablists) {
|
||||||
tablists.get(event.getPlayer()).onServerSwitch();
|
tablists.get(event.getPlayer()).onServerSwitch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@Subscribe
|
||||||
public void onLeave(PlayerDisconnectEvent event) {
|
public void onLeave(DisconnectEvent event) {
|
||||||
synchronized (tablists) {
|
synchronized (tablists) {
|
||||||
tablists.remove(event.getPlayer());
|
tablists.remove(event.getPlayer());
|
||||||
Storage.directTabItems.remove(event.getPlayer());
|
Storage.directTabItems.remove(event.getPlayer());
|
||||||
@ -79,11 +89,11 @@ public class TablistManager extends BasicListener {
|
|||||||
|
|
||||||
private void updateTablist() {
|
private void updateTablist() {
|
||||||
List<TablistPart> subservers = new ArrayList<>();
|
List<TablistPart> subservers = new ArrayList<>();
|
||||||
for (ServerInfo server : new ArrayList<>(ProxyServer.getInstance().getServers().values())){
|
for (RegisteredServer server : new ArrayList<>(VelocityCore.getProxy().getAllServers())){
|
||||||
if(server.getPlayers().isEmpty())
|
if(server.getPlayersConnected().isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Subserver subserver = Subserver.getSubserver(server);
|
Subserver subserver = Subserver.getSubserver(server.getServerInfo());
|
||||||
if(fightInfos.containsKey(server))
|
if(fightInfos.containsKey(server))
|
||||||
subservers.add(new TablistServer(server, fightInfos.get(server)));
|
subservers.add(new TablistServer(server, fightInfos.get(server)));
|
||||||
else if(subserver == null || subserver.getType() != Servertype.BAUSERVER)
|
else if(subserver == null || subserver.getType() != Servertype.BAUSERVER)
|
||||||
|
@ -20,72 +20,46 @@
|
|||||||
package de.steamwar.bungeecore.tablist;
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import de.steamwar.messages.Chatter;
|
import de.steamwar.messages.Chatter;
|
||||||
import de.steamwar.sql.SteamwarUser;
|
import de.steamwar.sql.SteamwarUser;
|
||||||
import de.steamwar.sql.UserPerm;
|
import de.steamwar.sql.UserPerm;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import lombok.Getter;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import net.md_5.bungee.connection.InitialHandler;
|
|
||||||
import net.md_5.bungee.connection.LoginResult;
|
|
||||||
import net.md_5.bungee.protocol.Property;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
interface TablistPart {
|
public interface TablistPart {
|
||||||
String sortKey();
|
String sortKey();
|
||||||
void print(Chatter viewer, Player player, List<Item> tablist, List<Item> direct);
|
void print(Chatter viewer, Player player, List<Item> tablist, List<Item> direct);
|
||||||
|
|
||||||
|
@Getter
|
||||||
class Item {
|
class Item {
|
||||||
|
|
||||||
public static Property[] playerProperties(Player player) {
|
|
||||||
LoginResult loginResult = ((InitialHandler) player.getPendingConnection()).getLoginProfile();
|
|
||||||
if(loginResult == null)
|
|
||||||
return new Property[0];
|
|
||||||
|
|
||||||
return loginResult.getProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final BaseComponent displayName;
|
private final Component displayName;
|
||||||
private final Property[] properties;
|
private final List<GameProfile.Property> properties;
|
||||||
|
|
||||||
public Item(UUID uuid, String displayName, Property[] properties) {
|
public Item(UUID uuid, String displayName, List<GameProfile.Property> properties) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.displayName = reformat(displayName);
|
this.displayName = LegacyComponentSerializer.legacySection().deserialize(displayName);
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item(ProxiedPlayer player) {
|
public Item(Player player) {
|
||||||
this(player, false);
|
this(player, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item(ProxiedPlayer player, boolean sameTeam) {
|
public Item(Player player, boolean sameTeam) {
|
||||||
this.uuid = player.getUniqueId();
|
this.uuid = player.getUniqueId();
|
||||||
UserPerm.Prefix prefix = SteamwarUser.get(player.getUniqueId()).prefix();
|
UserPerm.Prefix prefix = SteamwarUser.get(player.getUniqueId()).prefix();
|
||||||
if (prefix == UserPerm.emptyPrefix && sameTeam) {
|
if (prefix == UserPerm.emptyPrefix && sameTeam) {
|
||||||
this.displayName = reformat("§f" + player.getName());
|
this.displayName = LegacyComponentSerializer.legacySection().deserialize("§f" + player.getUsername());
|
||||||
} else {
|
} else {
|
||||||
this.displayName = reformat(prefix.getColorCode() + player.getName());
|
this.displayName = LegacyComponentSerializer.legacySection().deserialize(prefix.getColorCode() + player.getUsername());
|
||||||
}
|
}
|
||||||
this.properties = playerProperties(player);
|
this.properties = player.getGameProfileProperties();
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getUuid() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseComponent getDisplayName() {
|
|
||||||
return displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Property[] getProperties() {
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BaseComponent reformat(String string) {
|
|
||||||
return TextComponent.fromLegacy(string);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,16 @@
|
|||||||
|
|
||||||
package de.steamwar.bungeecore.tablist;
|
package de.steamwar.bungeecore.tablist;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.proxy.ServerConnection;
|
||||||
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import de.steamwar.bungeecore.Servertype;
|
import de.steamwar.bungeecore.Servertype;
|
||||||
import de.steamwar.bungeecore.Subserver;
|
import de.steamwar.bungeecore.Subserver;
|
||||||
import de.steamwar.sql.SteamwarUser;
|
import de.steamwar.bungeecore.VelocityCore;
|
||||||
import de.steamwar.messages.Chatter;
|
import de.steamwar.messages.Chatter;
|
||||||
import de.steamwar.network.packets.common.FightInfoPacket;
|
import de.steamwar.network.packets.common.FightInfoPacket;
|
||||||
import net.md_5.bungee.BungeeCord;
|
import de.steamwar.sql.SteamwarUser;
|
||||||
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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -38,63 +39,63 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
public class TablistServer implements TablistPart {
|
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 List<GameProfile.Property> GRAY = List.of(new GameProfile.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=")};
|
public static final List<GameProfile.Property> LIGHT_GRAY = List.of(new GameProfile.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 RegisteredServer server;
|
||||||
private final List<Item> players;
|
private final List<Item> players;
|
||||||
|
|
||||||
public TablistServer(ServerInfo server) {
|
public TablistServer(RegisteredServer server) {
|
||||||
this(server, server.getPlayers().stream().sorted((p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName())).map(TablistPart.Item::new).collect(Collectors.toList()));
|
this(server, server.getPlayersConnected().stream().sorted((p1, p2) -> p1.getUsername().compareToIgnoreCase(p2.getUsername())).map(TablistPart.Item::new).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TablistServer(ServerInfo server, FightInfoPacket info) {
|
public TablistServer(RegisteredServer server, FightInfoPacket info) {
|
||||||
this(server, new ArrayList<>());
|
this(server, new ArrayList<>());
|
||||||
|
|
||||||
Collection<ProxiedPlayer> onlinePlayers = server.getPlayers();
|
Collection<Player> onlinePlayers = server.getPlayersConnected();
|
||||||
addPlayers(info.getBlueName().substring(0, 2), info.getBluePlayers(), onlinePlayers);
|
addPlayers(info.getBlueName().substring(0, 2), info.getBluePlayers(), onlinePlayers);
|
||||||
addPlayers(info.getRedName().substring(0, 2), info.getRedPlayers(), onlinePlayers);
|
addPlayers(info.getRedName().substring(0, 2), info.getRedPlayers(), onlinePlayers);
|
||||||
addPlayers("§7", info.getSpectators(), onlinePlayers);
|
addPlayers("§7", info.getSpectators(), onlinePlayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TablistServer(ServerInfo server, List<Item> players) {
|
public TablistServer(RegisteredServer server, List<Item> players) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.players = players;
|
this.players = players;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sortKey() {
|
public String sortKey() {
|
||||||
return server.getName();
|
return server.getServerInfo().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void print(Chatter viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct) {
|
public void print(Chatter viewer, Player player, List<Item> tablist, List<Item> direct) {
|
||||||
boolean onServer = player.getServer().getInfo() == server;
|
boolean onServer = player.getCurrentServer().orElseThrow().getServer() == server;
|
||||||
List<Item> items = onServer ? direct : tablist;
|
List<Item> items = onServer ? direct : tablist;
|
||||||
|
|
||||||
if(!onServer) {
|
if(!onServer) {
|
||||||
items.add(new Item(null, "", GRAY));
|
items.add(new Item(null, "", GRAY));
|
||||||
items.add(new Item(null, "§7§l" + server.getName(), LIGHT_GRAY));
|
items.add(new Item(null, "§7§l" + server.getServerInfo().getName(), LIGHT_GRAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
teamify(players, player).forEach(items::add);
|
teamify(players, player).forEach(items::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPlayers(String prefix, List<Integer> teamPlayers, Collection<ProxiedPlayer> onlinePlayers){
|
private void addPlayers(String prefix, List<Integer> teamPlayers, Collection<Player> onlinePlayers) {
|
||||||
teamPlayers.stream().map(SteamwarUser::get).map(
|
teamPlayers.stream().map(SteamwarUser::get).map(
|
||||||
user -> onlinePlayers.stream().filter(player -> player.getUniqueId().equals(user.getUUID())).findAny()
|
user -> onlinePlayers.stream().filter(player -> player.getUniqueId().equals(user.getUUID())).findAny()
|
||||||
).filter(Optional::isPresent).map(Optional::get).sorted(
|
).filter(Optional::isPresent).map(Optional::get).sorted(
|
||||||
(p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName())
|
(p1, p2) -> p1.getUsername().compareToIgnoreCase(p2.getUsername())
|
||||||
).forEachOrdered(player -> players.add(new Item(player.getUniqueId(), prefix + player.getName(), Item.playerProperties(player))));
|
).forEachOrdered(player -> players.add(new Item(player.getUniqueId(), prefix + player.getUsername(), player.getGameProfileProperties())));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<Item> teamify(List<Item> players, ProxiedPlayer player) {
|
public static Stream<Item> teamify(List<Item> players, Player player) {
|
||||||
int team = SteamwarUser.get(player.getUniqueId()).getTeam();
|
int team = SteamwarUser.get(player.getUniqueId()).getTeam();
|
||||||
if (team == 0) return players.stream();
|
if (team == 0) return players.stream();
|
||||||
return players.stream().map(item -> {
|
return players.stream().map(item -> {
|
||||||
ProxiedPlayer p = BungeeCord.getInstance().getPlayer(item.getUuid());
|
Player p = VelocityCore.getProxy().getPlayer(item.getUuid()).orElse(null);
|
||||||
if (p == null) return item;
|
if (p == null) return item;
|
||||||
Subserver subserver = Subserver.getSubserver(p.getServer().getInfo());
|
Subserver subserver = Subserver.getSubserver(p.getCurrentServer().map(ServerConnection::getServerInfo).orElse(null));
|
||||||
if (subserver != null && subserver.getType() == Servertype.ARENA) return item;
|
if (subserver != null && subserver.getType() == Servertype.ARENA) return item;
|
||||||
if (SteamwarUser.get(p.getUniqueId()).getTeam() != team) return item;
|
if (SteamwarUser.get(p.getUniqueId()).getTeam() != team) return item;
|
||||||
return new Item(p, true);
|
return new Item(p, true);
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is a part of the SteamWar software.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2024 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.util;
|
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class YamlUtils {
|
|
||||||
|
|
||||||
public <T> T get(Map<String, Object> config, String key) {
|
|
||||||
if (key.contains(".")) {
|
|
||||||
return getRecursive(config, key.split("\\."), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (T) config.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T get(Map<String, Object> config, String key, T def) {
|
|
||||||
if (key.contains(".")) {
|
|
||||||
return getRecursive(config, key.split("\\."), def);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (T) config.getOrDefault(key, def);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T getRecursive(Map<String, Object> config, String[] keys, T def) {
|
|
||||||
if (keys.length == 1) {
|
|
||||||
return get(config, keys[0], def);
|
|
||||||
} else {
|
|
||||||
Object o = get(config, keys[0], null);
|
|
||||||
if (o == null) {
|
|
||||||
if (def == null) {
|
|
||||||
throw new IllegalArgumentException("Key " + keys[0] + " not found");
|
|
||||||
}
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o instanceof Map) {
|
|
||||||
return getRecursive((Map<String, Object>) o, Arrays.copyOfRange(keys, 1, keys.length), def);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Key " + keys[0] + " is not a map");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> List<T> getList(Map<String, Object> config, String key) {
|
|
||||||
return (List<T>) config.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T loadYaml(File f) throws FileNotFoundException {
|
|
||||||
return loadYaml(f, new Yaml());
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T loadYaml(File f, Yaml yaml) throws FileNotFoundException {
|
|
||||||
return yaml.load(new FileInputStream(f));
|
|
||||||
}
|
|
||||||
}
|
|
@ -21,19 +21,15 @@ package de.steamwar.sql;
|
|||||||
|
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import de.steamwar.bungeecore.GameModeConfig;
|
||||||
import de.steamwar.bungeecore.VelocityCore;
|
import de.steamwar.bungeecore.VelocityCore;
|
||||||
import de.steamwar.bungeecore.commands.CheckCommand;
|
import de.steamwar.bungeecore.commands.CheckCommand;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.Date;
|
||||||
import java.util.stream.Collectors;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import static de.steamwar.bungeecore.util.YamlUtils.*;
|
|
||||||
|
|
||||||
public class SQLWrapperImpl implements SQLWrapper {
|
public class SQLWrapperImpl implements SQLWrapper {
|
||||||
private static final SimpleDateFormat deadlineFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");
|
private static final SimpleDateFormat deadlineFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");
|
||||||
@ -50,44 +46,27 @@ public class SQLWrapperImpl implements SQLWrapper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadSchemTypes(List<SchematicType> tmpTypes, Map<String, SchematicType> tmpFromDB) {
|
public void loadSchemTypes(List<SchematicType> tmpTypes, Map<String, SchematicType> tmpFromDB) {
|
||||||
File folder = new File(VelocityCore.get().getDataDirectory().getParent().toFile(), "FightSystem");
|
GameModeConfig.loadAll(GameModeConfig.class, (file, config) -> {
|
||||||
if(folder.exists()) {
|
if(config.getSchematic() == null || tmpFromDB.containsKey(config.getSchemType().toLowerCase()))
|
||||||
for(File configFile : Arrays.stream(folder.listFiles((file, name) -> name.endsWith(".yml") && !name.endsWith(".kits.yml"))).sorted().collect(Collectors.toList())) {
|
return;
|
||||||
Map<String, Object> config;
|
|
||||||
Yaml yaml = new Yaml();
|
|
||||||
try {
|
|
||||||
config = yaml.load(new FileInputStream(configFile));
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new SecurityException("Could not load config.yml", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!config.containsKey("Schematic"))
|
String shortcut = config.getSchematic().getShortcut();
|
||||||
continue;
|
String material = config.getSchematic().getMaterial();
|
||||||
|
|
||||||
String type = get(config, "Schematic.Type");
|
|
||||||
assert type != null;
|
|
||||||
String shortcut = get(config,"Schematic.Shortcut");
|
|
||||||
if(tmpFromDB.containsKey(type.toLowerCase()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SchematicType checktype = null;
|
SchematicType checktype = null;
|
||||||
String material = get(config,"Schematic.Material");
|
if(!config.getCheckQuestions().isEmpty()) {
|
||||||
|
checktype = new SchematicType("C" + config.getSchemType(), "C" + shortcut, SchematicType.Type.CHECK_TYPE, null, material, true);
|
||||||
if(!getList(config,"CheckQuestions").isEmpty()) {
|
|
||||||
checktype = new SchematicType("C" + type, "C" + shortcut, SchematicType.Type.CHECK_TYPE, null, material, true);
|
|
||||||
tmpTypes.add(checktype);
|
tmpTypes.add(checktype);
|
||||||
tmpFromDB.put(checktype.toDB(), checktype);
|
tmpFromDB.put(checktype.toDB(), checktype);
|
||||||
CheckCommand.setCheckQuestions(checktype, get(config, "CheckQuestions"));
|
CheckCommand.setCheckQuestions(checktype, config.getCheckQuestions());
|
||||||
}
|
}
|
||||||
boolean manualCheck = get(config, "Schematic.ManualCheck", true);
|
|
||||||
|
|
||||||
SchematicType current = new SchematicType(type, shortcut, !config.containsKey("Server") ? SchematicType.Type.FIGHT_TYPE : SchematicType.Type.NORMAL, checktype, material, parseDeadline(get(config,"deadline", null)), manualCheck);
|
SchematicType current = new SchematicType(config.getSchemType(), shortcut, config.getServer() != null ? SchematicType.Type.FIGHT_TYPE : SchematicType.Type.NORMAL, checktype, material, parseDeadline(config.getDeadline()), config.getSchematic().isManualCheck());
|
||||||
tmpTypes.add(current);
|
tmpTypes.add(current);
|
||||||
tmpFromDB.put(type.toLowerCase(), current);
|
tmpFromDB.put(config.getSchemType().toLowerCase(), current);
|
||||||
if(checktype != null)
|
if(checktype != null)
|
||||||
CheckCommand.addFightType(checktype, current);
|
CheckCommand.addFightType(checktype, current);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,5 +3,6 @@ build:
|
|||||||
- "./gradlew --stop"
|
- "./gradlew --stop"
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
"/binarys/bungeecore.jar": "build/libs/bungeecore.jar"
|
"/binarys/PersistentVelocityCore.jar": "Persistent/build/libs/Persistent.jar"
|
||||||
|
"/binarys/VelocityCore.jar": "build/libs/velocitycore.jar"
|
||||||
"/binarys/deployarena.py": "deployarena.py"
|
"/binarys/deployarena.py": "deployarena.py"
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren