SteamWar/BungeeCore
Archiviert
13
2

Merge pull request 'Velocity' (#516) from velocity into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Reviewed-on: #516
Dieser Commit ist enthalten in:
Lixfel 2024-06-28 08:39:04 +02:00
Commit 213bc3d319
208 geänderte Dateien mit 8737 neuen und 9145 gelöschten Zeilen

55
Persistent/build.gradle Normale Datei
Datei anzeigen

@ -0,0 +1,55 @@
/*
* 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'
}
}
}
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.32'
testCompileOnly 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'org.projectlombok:lombok:1.18.32'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.32'
compileOnly 'de.steamwar:velocity:RELEASE'
annotationProcessor 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT'
}

Datei anzeigen

@ -0,0 +1,37 @@
/*
* 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.persistent;
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;
}
}

Datei anzeigen

@ -0,0 +1,60 @@
/*
* 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.persistent;
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 unregister() {
synchronized (servers) {
servers.remove(owner);
}
super.unregister();
}
}

Datei anzeigen

@ -0,0 +1,59 @@
/*
* 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.persistent;
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 unregister() {
synchronized (servers) {
servers.remove(map);
}
super.unregister();
}
}

Datei anzeigen

@ -0,0 +1,203 @@
/*
* 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.persistent;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.name.Names;
import com.mojang.brigadier.Command;
import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.command.CommandManager;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.event.EventManager;
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.Plugin;
import com.velocitypowered.api.plugin.PluginContainer;
import com.velocitypowered.api.plugin.PluginDescription;
import com.velocitypowered.api.plugin.PluginManager;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.scheduler.ScheduledTask;
import com.velocitypowered.proxy.plugin.PluginClassLoader;
import com.velocitypowered.proxy.plugin.VelocityPluginManager;
import com.velocitypowered.proxy.plugin.loader.VelocityPluginContainer;
import com.velocitypowered.proxy.plugin.loader.java.JavaPluginLoader;
import lombok.Getter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.io.IOException;
import java.nio.file.Path;
import java.util.NoSuchElementException;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
@Plugin(
id = "persistentvelocitycore",
name = "PersistentVelocityCore"
)
public class Persistent {
private static final Reflection.Method<VelocityPluginManager> registerPlugin = new Reflection.Method<>(VelocityPluginManager.class, "registerPlugin", PluginContainer.class);
@Getter
private static Persistent instance;
@Getter
private final ProxyServer proxy;
@Getter
private final Logger logger;
private final Path directory;
@Inject
public Persistent(ProxyServer proxy, Logger logger, @DataDirectory Path dataDirectory) {
instance = this;
this.proxy = proxy;
this.logger = logger;
this.directory = dataDirectory;
}
@Subscribe
public void onEnable(ProxyInitializeEvent event) {
proxy.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() {
PluginContainer container = null;
ReloadablePlugin plugin = null;
try {
container = proxy.getPluginManager().getPlugin("velocitycore").orElseThrow();
plugin = (ReloadablePlugin) container.getInstance().orElseThrow();
} catch (NoSuchElementException e) {
logger.log(Level.WARNING, "Could not find loaded VelocityCore, continuing without unloading.");
}
PluginContainer newContainer;
try {
newContainer = prepareLoad();
} catch (Exception e) {
logger.log(Level.SEVERE, "Could not instantiate new VelocityCore, aborting softreload.", e);
return Command.SINGLE_SUCCESS;
}
broadcast("§eNetwork update is starting§8.");
try {
if(container != null && plugin != null) {
plugin.onProxyShutdown(new ProxyShutdownEvent());
unload(container, plugin);
}
registerPlugin.invoke((VelocityPluginManager) proxy.getPluginManager(), newContainer);
((ReloadablePlugin) newContainer.getInstance().orElseThrow()).onProxyInitialization(new ProxyInitializeEvent());
} catch (Throwable t) {
logger.log(Level.SEVERE, "Error during softreload", t);
broadcast("§cNetwork update failed§8, §cexpect network restart soon§8.");
return Command.SINGLE_SUCCESS;
}
broadcast("§eNetwork update complete§8.");
return Command.SINGLE_SUCCESS;
}
private void broadcast(String message) {
Component component = LegacyComponentSerializer.legacySection().deserialize("§eSteam§8War» " + message);
proxy.getAllPlayers().forEach(player -> player.sendMessage(component));
proxy.getConsoleCommandSource().sendMessage(component);
}
private PluginContainer prepareLoad() throws Exception {
Path plugins = directory.getParent();
JavaPluginLoader loader = new JavaPluginLoader(proxy, plugins);
PluginDescription description = loader.createPluginFromCandidate(loader.loadCandidate(plugins.resolve("velocitycore.jar")));
PluginContainer container = new VelocityPluginContainer(description);
AbstractModule commonModule = new AbstractModule() {
@Override
protected void configure() {
this.bind(ProxyServer.class).toInstance(proxy);
this.bind(PluginManager.class).toInstance(proxy.getPluginManager());
this.bind(EventManager.class).toInstance(proxy.getEventManager());
this.bind(CommandManager.class).toInstance(proxy.getCommandManager());
this.bind(PluginContainer.class).annotatedWith(Names.named(container.getDescription().getId())).toInstance(container);
}
};
Module module = loader.createModule(container);
loader.createPlugin(container, module, commonModule);
return container;
}
private void unload(PluginContainer container, Object plugin) throws InterruptedException, IOException {
PluginClassLoader classLoader = ((PluginClassLoader) plugin.getClass().getClassLoader());
CommandManager commandManager = proxy.getCommandManager();
for(String alias : commandManager.getAliases()) {
CommandMeta meta = commandManager.getCommandMeta(alias);
if(meta != null && meta.getPlugin() == plugin)
commandManager.unregister(meta);
}
proxy.getEventManager().unregisterListeners(plugin);
proxy.getScheduler().tasksByPlugin(plugin).forEach(ScheduledTask::cancel);
container.getExecutorService().shutdown();
if(!container.getExecutorService().awaitTermination(100, TimeUnit.MILLISECONDS))
logger.log(Level.WARNING, "ExecutorService termination took longer than 100ms, continuing.");
for(Thread thread : Thread.getAllStackTraces().keySet()) {
if(thread.getClass().getClassLoader() != classLoader)
continue;
thread.interrupt();
thread.join(100);
if (thread.isAlive())
logger.log(Level.WARNING, "Could not stop thread %s of plugin %s. Still running".formatted(thread.getName(), container.getDescription().getId()));
}
//TODO close all log handlers
/*for (Handler handler : plugin.getLogger().getHandlers()) {
handler.close();
}*/
//Clear resource bundle cache
ResourceBundle.clearCache(classLoader);
classLoader.close();
}
}

Datei anzeigen

@ -0,0 +1,75 @@
/*
* 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.persistent;
import lombok.experimental.UtilityClass;
@UtilityClass
public class Reflection {
public static class Field<C, T> {
private final java.lang.reflect.Field f;
public Field(Class<C> target, String name) {
try {
f = target.getDeclaredField(name);
f.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException("Cannot find field with name " + name, e);
}
}
public T get(C target) {
try {
return (T) f.get(target);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Cannot access reflection.", e);
}
}
public void set(C target, T value) {
try {
f.set(target, value);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Cannot access reflection.", e);
}
}
}
public static class Method<C> {
private final java.lang.reflect.Method m;
public Method(Class<C> clazz, String methodName, Class<?>... params) {
try {
m = clazz.getDeclaredMethod(methodName, params);
m.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Cannot find method with name " + methodName, e);
}
}
public Object invoke(C target, Object... arguments) {
try {
return m.invoke(target, arguments);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot invoke method " + m, e);
}
}
}
}

Datei anzeigen

@ -0,0 +1,28 @@
/*
* 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.persistent;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
public interface ReloadablePlugin {
void onProxyInitialization(ProxyInitializeEvent event);
default void onProxyShutdown(ProxyShutdownEvent event) {}
}

Datei anzeigen

@ -0,0 +1,26 @@
/*
* 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.persistent;
public enum Servertype {
BAUSERVER,
ARENA,
BUILDER
}

Datei anzeigen

@ -0,0 +1,52 @@
/*
* 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.persistent;
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<>();
}

Datei anzeigen

@ -0,0 +1,263 @@
/*
* 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.persistent;
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();
}
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().getProxy().getServer(serverName).isPresent()) {
SecurityException e = new SecurityException("Server already registered: " + serverName);
stop();
failureCallback.accept(e);
throw e;
}
synchronized (serverList) {
registeredServer = Persistent.getInstance().getProxy().registerServer(server);
serverList.add(this);
infoToServer.put(server, this);
}
}
protected void unregister() {
synchronized (serverList) {
infoToServer.remove(server);
serverList.remove(this);
Persistent.getInstance().getProxy().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.YELLOW)
.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);
}
}

Datei anzeigen

@ -18,18 +18,11 @@
*/ */
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'
id 'com.github.johnrengelman.shadow' version '5.0.0' id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'de.steamwar.gradle' version 'RELEASE' id 'de.steamwar.gradle' version 'RELEASE'
} }
@ -38,8 +31,10 @@ version ''
compileJava.options.encoding = 'UTF-8' compileJava.options.encoding = 'UTF-8'
sourceCompatibility = 1.8 java {
targetCompatibility = 1.8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
mainClassName = '' mainClassName = ''
@ -55,44 +50,63 @@ sourceSets {
} }
} }
repositories { allprojects {
mavenCentral() repositories {
maven { mavenCentral()
url 'https://m2.dv8tion.net/releases' maven {
content { url 'https://repo.papermc.io/repository/maven-public/'
includeGroup 'net.dv8tion' content {
includeGroup 'com.velocitypowered'
}
} }
} maven {
maven { url 'https://m2.dv8tion.net/releases'
url 'https://repo.lunarclient.dev' content {
content { includeGroup 'net.dv8tion'
includeGroup 'com.lunarclient' }
}
maven {
url 'https://repo.lunarclient.dev'
content {
includeGroup 'com.lunarclient'
}
} }
} }
} }
shadowJar { shadowJar {
exclude 'META-INF/*' exclude 'META-INF/*'
exclude 'org/sqlite/native/FreeBSD/**', 'org/sqlite/native/Mac/**', 'org/sqlite/native/Windows/**', 'org/sqlite/native/Linux-Android/**', 'org/sqlite/native/Linux-Musl/**'
exclude 'org/sqlite/native/Linux/aarch64/**', 'org/sqlite/native/Linux/arm/**', 'org/sqlite/native/Linux/armv6/**', 'org/sqlite/native/Linux/armv7/**', 'org/sqlite/native/Linux/ppc64/**', 'org/sqlite/native/Linux/x86/**'
exclude 'org/slf4j/**'
//https://imperceptiblethoughts.com/shadow/configuration/minimizing/ //https://imperceptiblethoughts.com/shadow/configuration/minimizing/
minimize { minimize {
exclude project(':') exclude project(':')
exclude dependency('mysql:mysql-connector-java:.*')
} }
duplicatesStrategy DuplicatesStrategy.INCLUDE duplicatesStrategy DuplicatesStrategy.INCLUDE
} }
dependencies { dependencies {
compileOnly 'org.projectlombok:lombok:1.18.22' compileOnly 'org.projectlombok:lombok:1.18.32'
testCompileOnly 'org.projectlombok:lombok:1.18.22' testCompileOnly 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'org.projectlombok:lombok:1.18.22' annotationProcessor 'org.projectlombok:lombok:1.18.32'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' testAnnotationProcessor 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT'
compileOnly 'de.steamwar:velocity:RELEASE'
compileOnly project(":Persistent")
implementation project(":CommonCore")
implementation 'org.xerial:sqlite-jdbc:3.46.0.0'
implementation 'mysql:mysql-connector-java:8.0.33'
compileOnly 'de.steamwar:waterfall:RELEASE'
compileOnly 'de.steamwar:persistentbungeecore:RELEASE'
implementation("net.dv8tion:JDA:4.4.0_352") { implementation("net.dv8tion:JDA:4.4.0_352") {
exclude module: 'opus-java' exclude module: 'opus-java'
} }
implementation project(":CommonCore") implementation 'org.msgpack:msgpack-core:0.9.8' //AlpineClient
implementation 'com.lunarclient:apollo-api:1.1.0' implementation 'com.lunarclient:apollo-api:1.1.0'
implementation 'com.lunarclient:apollo-common:1.1.0' implementation 'com.lunarclient:apollo-common:1.1.0'

Datei anzeigen

@ -1,5 +1,5 @@
#Sat Apr 10 23:34:12 CEST 2021 #Sat Apr 10 23:34:12 CEST 2021
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-all.zip
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

Datei anzeigen

@ -26,6 +26,7 @@ pluginManagement {
} }
} }
rootProject.name = 'BungeeCore' rootProject.name = 'VelocityCore'
include 'CommonCore' include 'CommonCore'
include 'Persistent'

Datei anzeigen

@ -1,197 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore;
import de.steamwar.sql.SchematicType;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
public class ArenaMode {
private static final Random random = new Random();
private static final Map<String, ArenaMode> byChat = new HashMap<>();
private static final Map<String, ArenaMode> byInternal = new HashMap<>();
private static final Map<SchematicType, ArenaMode> bySchemType = new HashMap<>();
private static final List<ArenaMode> allModes = new LinkedList<>();
static {
init();
}
public static void init() {
byChat.clear();
byInternal.clear();
bySchemType.clear();
allModes.clear();
File folder = new File(ProxyServer.getInstance().getPluginsFolder(), "FightSystem");
for(File configFile : Arrays.stream(folder.listFiles((file, name) -> name.endsWith(".yml") && !name.endsWith(".kits.yml"))).sorted().collect(Collectors.toList())) {
Configuration config;
try {
config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
} catch (IOException e) {
throw new SecurityException("Could not load SchematicTypes", e);
}
if(config.contains("Server"))
new ArenaMode(configFile.getName().replace(".yml", ""), config);
}
}
public static ArenaMode getByChat(String name){
return byChat.get(name.toLowerCase());
}
public static ArenaMode getByInternal(String name){
return byInternal.get(name);
}
public static List<String> getAllChatNames(boolean historic) {
List<String> chatNames = new LinkedList<>();
for(ArenaMode mode : byInternal.values()){
if(historic == mode.historic)
chatNames.addAll(mode.chatNames);
}
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;
}
public static ArenaMode getBySchemType(SchematicType schemType){
return bySchemType.get(schemType);
}
public static List<ArenaMode> getAllModes(){
return allModes;
}
private final String displayName;
private final String folder;
private final List<String> chatNames;
private final String serverJar;
private final String config;
private final List<String> maps;
private final Map<String, String> lowerToRealMapNames = new HashMap<>();
private final boolean historic;
private final String internalName;
private final boolean ranked;
private final String schemType;
private ArenaMode(String internalName, Configuration config){
this.internalName = internalName;
this.folder = config.getString("Server.Folder");
this.serverJar = config.getString("Server.ServerJar");
this.config = internalName + ".yml";
this.maps = config.getStringList("Server.Maps");
maps.forEach(map -> lowerToRealMapNames.put(map.toLowerCase(), map));
this.displayName = config.getString("GameName", internalName);
this.chatNames = config.getStringList("Server.ChatNames");
this.schemType = config.getString("Schematic.Type", "").toLowerCase();
this.ranked = config.getBoolean("Server.Ranked", false);
this.historic = config.getBoolean("Server.Historic", false);
allModes.add(this);
byInternal.put(internalName, this);
for(String name : chatNames){
byChat.put(name.toLowerCase(), this);
}
if(!this.schemType.equals(""))
bySchemType.put(SchematicType.fromDB(this.schemType), this);
}
public String getDisplayName() {
return displayName;
}
public String serverJar() {
return serverJar;
}
public String getConfig(){
return config;
}
public String hasMap(String map){
for(String m : maps){
if(m.equalsIgnoreCase(map))
return m;
}
return null;
}
public String getFolder() {
return folder;
}
public String getRandomMap(){
return maps.get(random.nextInt(maps.size()));
}
public List<String> getMaps() {
return maps;
}
public String convertToRealMapName(String map){
return lowerToRealMapNames.get(map.toLowerCase());
}
public String getChatName(){
return chatNames.get(0);
}
public boolean withoutChatName(){
return chatNames.isEmpty();
}
public boolean isHistoric(){
return historic;
}
public boolean isRanked() {
return ranked;
}
public String getSchemType() {
return schemType;
}
public String getInternalName() {
return internalName;
}
}

Datei anzeigen

@ -1,327 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.bungeecore.commands.*;
import de.steamwar.bungeecore.listeners.*;
import de.steamwar.bungeecore.mods.ServerListPing;
import de.steamwar.bungeecore.mods.*;
import de.steamwar.bungeecore.network.BungeeNetworkHandler;
import de.steamwar.bungeecore.tablist.TablistManager;
import de.steamwar.command.SWCommandUtils;
import de.steamwar.command.SWTypeMapperCreator;
import de.steamwar.command.TabCompletionCache;
import de.steamwar.command.TypeMapper;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
import de.steamwar.sql.UserElo;
import de.steamwar.sql.internal.Statement;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public class BungeeCore extends Plugin {
public static boolean MAIN_SERVER;
public static String CHAT_PREFIX;
public static String LOBBY_SERVER;
public static boolean EVENT_MODE;
private static BungeeCore instance;
public static Node local;
private ErrorLogger errorLogger;
private TablistManager tablistManager;
@Override
public void onEnable(){
setInstance(this);
MAIN_SERVER = ProxyServer.getInstance().getConfig().getListeners().stream().anyMatch(info -> ((InetSocketAddress) info.getSocketAddress()).getPort() == 25565);
loadConfig();
errorLogger = new ErrorLogger();
SWCommandUtils.init((SWTypeMapperCreator<TypeMapper<Object>, CommandSender, Object>) (mapper, tabCompleter) -> new TypeMapper<Object>() {
@Override
public Object map(CommandSender commandSender, String[] previousArguments, String s) {
return mapper.apply(s);
}
@Override
public Collection<String> tabCompletes(CommandSender sender, String[] previousArguments, String s) {
return tabCompleter.apply(sender, s);
}
});
ProxyServer.getInstance().getScheduler().schedule(this, TabCompletionCache::invalidateOldEntries, 1, 1, TimeUnit.SECONDS);
new Hostname();
new ServerListPing();
new PluginMessage();
new Schematica();
new Badlion();
new FabricModSender();
new ReplayMod();
new FML2();
new ConnectionListener();
new ChatListener();
new BanListener();
new CheckListener();
new IPSanitizer();
local = new Node.LocalNode();
if(MAIN_SERVER) {
//new Node.RemoteNode("lx");
}
new TeamchatCommand();
new MsgCommand();
new RCommand();
new PingCommand();
new AlertCommand();
new KickCommand();
new JoinmeCommand();
new TpCommand();
HelpCommand helpCommand = new HelpCommand();
new TeamCommand();
new ServerTeamchatCommand();
new DevCommand();
new EventCommand();
new EventreloadCommand();
new EventRescheduleCommand();
new PollCommand();
new BugCommand();
new WhoisCommand();
new RegelnCommand();
new IgnoreCommand();
new UnIgnoreCommand();
new PollresultCommand();
new ListCommand();
new StatCommand();
new VerifyCommand();
new GDPRQuery();
new PlaytimeCommand();
new ArenaCommand();
new RankCommand();
new LocalCommand();
new SetLocaleCommand();
new BuilderCloudCommand();
new ModCommand();
// Punishment Commands:
new PunishmentCommand("ban", Punishment.PunishmentType.Ban);
new PunishmentCommand("mute", Punishment.PunishmentType.Mute);
new PunishmentCommand("noschemreceiving", Punishment.PunishmentType.NoSchemReceiving);
new PunishmentCommand("noschemsharing", Punishment.PunishmentType.NoSchemSharing);
new PunishmentCommand("noschemsubmitting", Punishment.PunishmentType.NoSchemSubmitting);
new PunishmentCommand("nodev", Punishment.PunishmentType.NoDevServer);
new PunishmentCommand("nofight", Punishment.PunishmentType.NoFightServer);
new PunishmentCommand("noteamserver", Punishment.PunishmentType.NoTeamServer);
new PunishmentCommand("note", Punishment.PunishmentType.Note);
if(!EVENT_MODE){
new BauCommand(helpCommand);
new WebpasswordCommand();
new FightCommand();
new ChallengeCommand();
new HistoricCommand();
new CheckCommand();
new ReplayCommand();
new TutorialCommand();
new Broadcaster();
}else{
new EventModeListener();
}
new EventStarter();
new SessionManager();
BungeeNetworkHandler.register();
tablistManager = new TablistManager();
new SettingsChangedListener();
getProxy().getScheduler().schedule(this, () -> {
SteamwarUser.clear();
UserElo.clear();
Team.clear();
}, 1, 1, TimeUnit.HOURS);
if (SteamwarDiscordBotConfig.loaded) {
try {
new SteamwarDiscordBot();
} catch (Throwable e) {
getLogger().log(Level.SEVERE, "Could not initialize discord bot", e);
}
}
}
@Override
public void onDisable(){
if (SteamwarDiscordBotConfig.loaded) {
try {
SteamwarDiscordBot.instance().getJda().shutdown();
} catch (Throwable e) {
getLogger().log(Level.SEVERE, "Could not shutdown discord bot", e);
}
}
if(tablistManager != null)
tablistManager.disable();
errorLogger.unregister();
Statement.closeAll();
}
public static BungeeCore get() {
return instance;
}
public static TextComponent stringToText(String msg){
return new TextComponent(TextComponent.fromLegacyText(msg));
}
public static void send(ProxiedPlayer player, String msg){
send(player, msg, null, null);
}
public static void send(CommandSender sender, String msg){
sender.sendMessage(stringToText(msg));
}
public static void send(ProxiedPlayer player, ChatMessageType type, String msg){
send(player, type, msg, null, null);
}
public static void send(ProxiedPlayer player, String msg, String onHover, ClickEvent onClick){
send(player, ChatMessageType.SYSTEM, msg, onHover, onClick);
}
public static void send(ProxiedPlayer player, ChatMessageType type, String msg, String onHover, ClickEvent onClick){
if(type == ChatMessageType.CHAT && player.getChatMode() != ProxiedPlayer.ChatMode.SHOWN)
return;
TextComponent message = stringToText(msg);
if(onHover != null)
message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(onHover)));
if(onClick != null)
message.setClickEvent(onClick);
player.sendMessage(type, message);
}
public static void broadcast(String msg){
ProxyServer.getInstance().broadcast(stringToText(msg));
}
public static void broadcast(String msg, String onHover, ClickEvent onClick){
TextComponent message = stringToText(msg);
if(onHover != null)
message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(onHover)));
if(onClick != null)
message.setClickEvent(onClick);
ProxyServer.getInstance().broadcast(message);
}
public static void log(final ServerInfo server, final String msg){
log(server.getName() + ": " + msg);
}
public static void log(final ProxiedPlayer player, final String msg){
log(player.getName() + ": " + msg);
}
public static void log(final String msg){
log(Level.INFO, msg);
}
public static void log(final Level logLevel, final String msg){
get().getLogger().log(logLevel, msg);
}
public static void log(final String msg, final Throwable e){
get().getLogger().log(Level.SEVERE, msg, e);
}
private static void loadConfig(){
Configuration config;
try{
if(!get().getDataFolder().exists() && !get().getDataFolder().mkdir())
throw new IOException();
File configFile = new File(get().getDataFolder().getPath(), "config.yml");
if(!configFile.exists()){
boolean created = configFile.createNewFile();
if(created)
ProxyServer.getInstance().stop("Config file not initialized");
else
ProxyServer.getInstance().stop("Could not save conig file");
return;
}
config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
}catch(Exception e){
log("Could not save/load config.yml", e);
ProxyServer.getInstance().stop();
return;
}
CHAT_PREFIX = config.getString("prefix");
LOBBY_SERVER = config.getString("lobbyserver");
EVENT_MODE = config.getBoolean("eventmode");
Broadcaster.setBroadCastMsgs(config.getStringList("broadcasts").toArray(new String[1]));
PollSystem.init(config.getString("poll.question"), config.getStringList("poll.answers"));
final Configuration servers = config.getSection("servers");
for(final String serverName : servers.getKeys()){
final Configuration server = servers.getSection(serverName);
List<String> cmds = server.getStringList("commands");
String cmd = cmds.remove(0);
if(server.contains("spectatePort"))
EventStarter.addSpectateServer(server.getInt("spectatePort"), cmd);
new ServerSwitchCommand(
cmd,
serverName,
cmds.toArray(new String[0])
);
}
File discordFile = new File(System.getProperty("user.home"), "discord.yml");
if(discordFile.exists() && !EVENT_MODE) {
try {
SteamwarDiscordBotConfig.loadConfig(ConfigurationProvider.getProvider(YamlConfiguration.class).load(discordFile));
} catch (IOException e) {
get().getLogger().log(Level.SEVERE, "Could not load discord bot configuration", e);
}
}
}
private static void setInstance(BungeeCore core){
instance = core;
}
}

Datei anzeigen

@ -1,145 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore;
import de.steamwar.messages.ChatSender;
import de.steamwar.messages.SteamwarResourceBundle;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
public class Message {
@Deprecated
public static TextComponent parseToComponent(String message, boolean prefixed, CommandSender sender, Object... params){
return new TextComponent(TextComponent.fromLegacyText(parse(message, prefixed, locale(sender), params)));
}
@Deprecated
public static String parsePrefixed(String message, CommandSender sender, Object... params){
return parse(message, true, locale(sender), params);
}
@Deprecated
public static String parse(String message, CommandSender sender, Object... params){
return parse(message, false, locale(sender), params);
}
@Deprecated
public static String parse(String message, Locale locale, Object... params){
return parse(message, false, locale, params);
}
@Deprecated
private static Locale locale(CommandSender sender) {
return ChatSender.of(sender).getLocale();
}
@Deprecated
private static String parse(String message, boolean prefixed, Locale locale, Object... params){
if(locale == null)
locale = Locale.getDefault();
ResourceBundle resourceBundle = SteamwarResourceBundle.getResourceBundle(locale);
String pattern = "";
if(prefixed)
pattern = resourceBundle.getObject("PREFIX") + " ";
pattern += (String)resourceBundle.getObject(message);
MessageFormat format = new MessageFormat(pattern, locale);
for (int i = 0; i < params.length; i++) {
if(params[i] instanceof Message) {
Message msg = (Message) params[i];
params[i] = parse(msg.getFormat(), false, locale, msg.getParams());
} else if(params[i] instanceof Date) {
params[i] = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale).format((Date) params[i]);
}
}
return format.format(params);
}
@Deprecated
public static void send(String message, CommandSender sender, Object... params){
send(message, true, sender, ChatMessageType.SYSTEM, null, null, params);
}
@Deprecated
public static void sendPrefixless(String message, CommandSender sender, Object... params){
send(message, false, sender, ChatMessageType.SYSTEM, null, null, params);
}
@Deprecated
public static void send(String message, CommandSender sender, String onHover, ClickEvent onClick, Object... params){
send(message, true, sender, ChatMessageType.SYSTEM, onHover, onClick, params);
}
@Deprecated
public static void sendPrefixless(String message, CommandSender sender, String onHover, ClickEvent onClick, Object... params){
send(message, false, sender, ChatMessageType.SYSTEM, onHover, onClick, params);
}
@Deprecated
private static void send(String message, boolean prefixed, CommandSender s, ChatMessageType type, String onHover, ClickEvent onClick, Object... params){
ChatSender sender = ChatSender.of(s);
if(type == ChatMessageType.CHAT && !sender.chatShown())
return;
sender.send(prefixed, type, onHover != null ? new Message("PLAIN_STRING", onHover) : null, onClick, new Message(message, params));
}
public static void broadcast(String message, Object... params) {
broadcast(message, null, null, params);
}
public static void broadcast(String message, String onHover, ClickEvent onClick, Object... params) {
ChatSender.allReceivers().forEach(player -> player.system(message, onHover != null ? new Message(onHover, params) : null, onClick, params));
}
public static void team(String message, Object... params) {
team(message, null, null, params);
}
public static void team(String message, String onHover, ClickEvent onClick, Object... params) {
ChatSender.serverteamReceivers().forEach(player -> player.prefixless(message, onHover != null ? new Message(onHover, params) : null, onClick, params));
}
private final String format;
private final Object[] params;
public Message(String format, Object... params) {
this.format = format;
this.params = params;
}
public String getFormat() {
return format;
}
public Object[] getParams() {
return params;
}
}

Datei anzeigen

@ -1,81 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.sql.SteamwarUser;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Emoji;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class AuthManager {
private static final Map<String, Long> TOKENS = new HashMap<>();
private static final Random rand = new Random();
public static String createDiscordAuthToken(Member member) {
if(TOKENS.containsValue(member.getIdLong())) return null;
byte[] randBytes = new byte[16];
rand.nextBytes(randBytes);
randBytes[0] = 'D';
randBytes[1] = 'C';
String code = Base64.getEncoder().encodeToString(randBytes);
TOKENS.put(code, member.getIdLong());
BungeeCore.log("Created Discord Auth-Token: " + code + " for: " + member.getUser().getAsTag());
BungeeCore.get().getProxy().getScheduler().schedule(BungeeCore.get(), () -> TOKENS.remove(code), 10, TimeUnit.MINUTES);
return code;
}
public static Member connectAuth(SteamwarUser user, String code) {
if (TOKENS.containsKey(code)) {
Member member = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).retrieveMemberById(TOKENS.get(code).longValue()).complete();
if(member == null) return null;
user.setDiscordId(member.getIdLong());
MessageBuilder builder = new MessageBuilder();
builder.setContent(":white_check_mark: Dein Discord Konto wurde mit **" + user.getUserName() + "** verknüpft");
builder.setActionRows(ActionRow.of(Button.success("tada", Emoji.fromUnicode("U+1F389")), Button.danger("invalid", "Ich war das nicht")));
try {
member.getUser().openPrivateChannel().queue(privateChannel -> privateChannel.sendMessage(builder.build()).queue());
if (member.getNickname() == null) {
try {
member.getGuild().modifyNickname(member, user.getUserName()).queue();
} catch (Exception e) {
// Ignored
}
}
TOKENS.remove(code);
return member;
} catch (Exception e) {
return null;
}
} else {
return null;
}
}
}

Datei anzeigen

@ -1,166 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.bot.commands.*;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.bungeecore.bot.events.EventManager;
import de.steamwar.bungeecore.bot.events.SchematicsManager;
import de.steamwar.bungeecore.bot.listeners.*;
import de.steamwar.bungeecore.bot.util.DiscordRolesMessage;
import de.steamwar.bungeecore.bot.util.DiscordRulesMessage;
import de.steamwar.bungeecore.bot.util.DiscordTicketMessage;
import de.steamwar.messages.ChatSender;
import de.steamwar.sql.Event;
import lombok.Getter;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.md_5.bungee.api.ProxyServer;
import javax.security.auth.login.LoginException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public class SteamwarDiscordBot {
private static SteamwarDiscordBot INSTANCE;
public static SteamwarDiscordBot instance() {
return INSTANCE;
}
@Getter
private volatile AnnouncementListener announcementListener;
@Getter
private volatile DiscordChatListener ingameChatListener;
@Getter
private volatile DiscordChatListener serverTeamChatListener;
@Getter
private final JDA jda;
@Getter
private static Map<String, BasicDiscordCommand> discordCommandMap = new HashMap<>();
public SteamwarDiscordBot() {
INSTANCE = this;
JDABuilder builder = JDABuilder.createDefault(SteamwarDiscordBotConfig.TOKEN);
builder.setStatus(OnlineStatus.ONLINE);
builder.setMemberCachePolicy(MemberCachePolicy.ONLINE);
try {
jda = builder.build();
} catch (LoginException e) {
throw new SecurityException("Could not Login: " + SteamwarDiscordBotConfig.TOKEN, e);
}
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
try {
jda.awaitReady();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
activity();
} catch (Exception e) {
BungeeCore.get().getLogger().log(Level.SEVERE, "Could not set initial activity to discord", e);
}
EventManager.update();
SchematicsManager.update();
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> {
try {
activity();
EventManager.update();
SchematicsManager.update();
} catch (ErrorResponseException e) {
//ignored
}
}, 30, 30, TimeUnit.SECONDS);
DiscordRolesMessage.sendMessage();
DiscordRulesMessage.sendMessage();
DiscordTicketMessage.sendMessage();
new RolesInteractionButtonListener();
new DiscordTicketListener();
new DiscordAuthListener();
new DiscordEventListener();
new PrivateMessageListener();
announcementListener = new AnnouncementListener();
ingameChatListener = new DiscordChatListener(SteamwarDiscordBotConfig.INGAME_CHANNEL, "CHAT_DISCORD_GLOBAL", ChatSender::globalReceivers);
serverTeamChatListener = new DiscordChatListener(SteamwarDiscordBotConfig.SERVER_TEAM_CHANNEL, "CHAT_SERVERTEAM", ChatSender::serverteamReceivers);
new SlashCommandListener();
jda.retrieveCommands().complete().forEach(command -> jda.deleteCommandById(command.getId()).queue());
Guild guild = jda.getGuildById(SteamwarDiscordBotConfig.GUILD);
guild.retrieveCommands().complete().forEach(command -> guild.deleteCommandById(command.getId()).complete());
CommandListUpdateAction commands = jda.getGuildById(SteamwarDiscordBotConfig.GUILD).updateCommands();
addCommand(commands, new MuteCommand());
addCommand(commands, new BanCommand());
addCommand(commands, new WhoisCommand());
addCommand(commands, new TeamCommand());
addCommand(commands, new ListCommand());
addCommand(commands, new UnbanCommand());
commands.complete();
});
}
private void addCommand(CommandListUpdateAction commands, BasicDiscordCommand basicDiscordCommand) {
commands.addCommands(basicDiscordCommand);
discordCommandMap.put(basicDiscordCommand.getName(), basicDiscordCommand);
}
private int index = 0;
private void activity() {
switch (index) {
case 0:
Event event = Event.get();
if (event != null) {
jda.getPresence().setActivity(Activity.competing("dem Event " + event.getEventName()));
} else {
jda.getPresence().setActivity(Activity.playing("auf SteamWar.de"));
}
break;
case 1:
int count = BungeeCore.get().getProxy().getOnlineCount();
if (count == 1) {
jda.getPresence().setActivity(Activity.playing("mit 1 Spieler"));
} else {
jda.getPresence().setActivity(Activity.playing("mit " + count + " Spielern"));
}
index = 0;
return;
}
index++;
}
public void addListener(ListenerAdapter listenerAdapter) {
jda.addEventListener(listenerAdapter);
}
}

Datei anzeigen

@ -1,66 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.commands.PunishmentCommand;
import de.steamwar.sql.SteamwarUser;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import java.sql.Timestamp;
public class BanCommand extends BasicDiscordCommand {
public BanCommand() {
super("ban", "Banne einen Nutzer, wenn du die Rechte hast.");
addOption(OptionType.STRING, "user", "Der Benutzer", true);
addOption(OptionType.STRING, "time", "Bis Wann", true);
addOption(OptionType.STRING, "reason", "Warum", true);
}
@Override
public void run(SlashCommandEvent event) {
if (!testPermission(event)) {
return;
}
SteamwarUser sender = SteamwarUser.get(event.getMember().getIdLong());
SteamwarUser target = PunishmentCommand.getOrCreateOfflinePlayer(event.getOption("user").getAsString());
if (target == null) {
event.reply("Angegebener User invalide").setEphemeral(true).queue();
return;
}
Timestamp time = PunishmentCommand.parseTime(null, event.getOption("time").getAsString());
if (time == null) {
event.reply("Angegebene Zeit invalide").setEphemeral(true).queue();
return;
}
String msg = event.getOption("reason").getAsString();
boolean isPerma = event.getOption("time").getAsString().equals("perma");
PunishmentCommand.ban(target, time, msg, sender, isPerma);
Message.team("BAN_TEAM", new Message("PREFIX"), target.getUserName(), sender.getUserName(), new Message((isPerma ? "BAN_PERMA" : "BAN_UNTIL"), time), msg);
event.reply("Erfolgreich " + target.getUserName() + (isPerma ? " permanent" : " bis " + time) + " gebannt").setEphemeral(true).queue();
}
}

Datei anzeigen

@ -1,54 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.commands;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
public abstract class BasicDiscordCommand extends CommandData {
protected BasicDiscordCommand(String name, String description) {
super(name, description);
}
public abstract void run(SlashCommandEvent event);
protected SteamwarUser getSteamwarUser(SlashCommandEvent event) {
Member member = event.getMember();
SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong());
if (steamwarUser == null) {
return null;
}
return steamwarUser;
}
protected boolean testPermission(SlashCommandEvent event) {
Member member = event.getMember();
SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong());
if (steamwarUser == null || (!steamwarUser.hasPerm(UserPerm.TEAM))) {
event.reply("Du hast für " + event.getName() + " keine Rechte oder es existiert keine Verknüpfung für dich.").setEphemeral(true).queue();
return false;
}
return true;
}
}

Datei anzeigen

@ -1,43 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.commands;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import java.util.stream.Collectors;
public class ListCommand extends BasicDiscordCommand {
public ListCommand() {
super("list", "Gebe eine Liste aller online Spieler");
}
@Override
public void run(SlashCommandEvent event) {
de.steamwar.bungeecore.commands.ListCommand.getCustomTablist();
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("List");
de.steamwar.bungeecore.commands.ListCommand.getCustomTablist().forEach((s, proxiedPlayers) -> {
embedBuilder.addField(s, proxiedPlayers.stream().map(player -> "`" + player.getName() + "`").collect(Collectors.joining(", ")), true);
});
event.replyEmbeds(embedBuilder.build()).setEphemeral(true).queue();
}
}

Datei anzeigen

@ -1,67 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.commands.PunishmentCommand;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import java.sql.Timestamp;
public class MuteCommand extends BasicDiscordCommand {
public MuteCommand() {
super("mute", "Mute einen Nutzer, wenn du die Rechte hast.");
addOption(OptionType.STRING, "user", "Der Benutzer", true);
addOption(OptionType.STRING, "time", "Bis Wann", true);
addOption(OptionType.STRING, "reason", "Warum", true);
}
@Override
public void run(SlashCommandEvent event) {
if (!testPermission(event)) {
return;
}
SteamwarUser sender = SteamwarUser.get(event.getMember().getIdLong());
SteamwarUser target = PunishmentCommand.getOrCreateOfflinePlayer(event.getOption("user").getAsString());
if (target == null) {
event.reply("Angegebener User invalide").setEphemeral(true).complete();
return;
}
Timestamp time = PunishmentCommand.parseTime(null, event.getOption("time").getAsString());
if (time == null) {
event.reply("Angegebene Zeit invalide").setEphemeral(true).complete();
return;
}
String msg = event.getOption("reason").getAsString();
boolean isPerma = event.getOption("time").getAsString().equals("perma");
target.punish(Punishment.PunishmentType.Mute, time, msg, sender.getId(), isPerma);
Message.team("MUTE_TEAM", new Message("PREFIX"), target.getUserName(), sender.getUserName(), new Message((isPerma ? "BAN_PERMA" : "BAN_UNTIL"), time), msg);
event.reply("Erfolgreich " + target.getUserName() + (isPerma ? " permanent" : " bis " + time) + " gemutet").setEphemeral(true).queue();
}
}

Datei anzeigen

@ -1,96 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.commands;
import de.steamwar.sql.Event;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
import de.steamwar.sql.TeamTeilnahme;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Emoji;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.md_5.bungee.api.ProxyServer;
import java.awt.*;
import java.util.List;
import java.util.stream.Collectors;
public class TeamCommand extends BasicDiscordCommand {
public TeamCommand() {
super("team", "Alle Team bezogenen Befehle");
addSubcommands(new SubcommandData("info", "Infos über das Team oder deins")
.addOption(OptionType.STRING, "team", "Name oder Kuerzel", false)
);
}
private Emoji emoji = Emoji.fromUnicode("U+1F7E2");
@Override
public void run(SlashCommandEvent event) {
SteamwarUser steamwarUser = getSteamwarUser(event);
if (event.getSubcommandName() != null) {
switch (event.getSubcommandName()) {
case "info":
OptionMapping optionMapping = event.getOption("team");
Team team;
if (optionMapping == null) {
if (steamwarUser == null) {
event.reply("Dein Discord ist nicht verknüpft").setEphemeral(true).queue();
return;
}
if (steamwarUser.getTeam() == 0) {
event.reply("Du bist in keinem Team").setEphemeral(true).queue();
return;
}
team = Team.get(steamwarUser.getTeam());
} else {
team = Team.get(optionMapping.getAsString());
}
if (team == null) {
event.reply("Unbekanntes Team").setEphemeral(true).queue();
return;
}
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Team: " + team.getTeamName() + " [" + team.getTeamKuerzel() + "]");
embedBuilder.setColor(Color.GRAY);
List<SteamwarUser> members = team.getMembers().stream().map(SteamwarUser::get).collect(Collectors.toList());
embedBuilder.addField("Leader", members.stream().filter(SteamwarUser::isLeader).map(user -> "`" + (isOnline(user) ? emoji.getAsMention() : "") + user.getUserName() + "`").collect(Collectors.joining(" ")), false);
embedBuilder.addField("Member", members.stream().filter(user -> !user.isLeader()).map(user -> "`" + (isOnline(user) ? emoji.getAsMention() : "") + user.getUserName() + "`").collect(Collectors.joining(" ")), false);
embedBuilder.addField("Events", "`" + TeamTeilnahme.getEvents(team.getTeamId()).stream().map(Event::getEventName).collect(Collectors.joining("` `")) + "`", false);
event.replyEmbeds(embedBuilder.build()).setEphemeral(true).queue();
return;
default:
event.reply("Unbekannter Befehl").setEphemeral(true).queue();
return;
}
}
}
private boolean isOnline(SteamwarUser user) {
return ProxyServer.getInstance().getPlayer(user.getUUID()) != null;
}
}

Datei anzeigen

@ -1,62 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.commands;
import de.steamwar.bungeecore.commands.PunishmentCommand;
import de.steamwar.sql.BannedUserIPs;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import java.sql.Timestamp;
import java.util.Date;
public class UnbanCommand extends BasicDiscordCommand {
public UnbanCommand() {
super("unban", "Entbannt einen Nutzer, wenn du die Rechte hast.");
addOption(OptionType.STRING, "user", "Der Benutzer", true);
}
@Override
public void run(SlashCommandEvent event) {
if (!testPermission(event)) {
return;
}
SteamwarUser sender = SteamwarUser.get(event.getMember().getIdLong());
SteamwarUser target = PunishmentCommand.getOrCreateOfflinePlayer(event.getOption("user").getAsString());
if (target == null) {
event.reply("Angegebener User invalide").setEphemeral(true).queue();
return;
}
if (!target.isPunished(Punishment.PunishmentType.Ban)) {
event.reply("Angegebener User ist nicht gebannt").setEphemeral(true).queue();
return;
}
target.punish(Punishment.PunishmentType.Ban, Timestamp.from(new Date().toInstant()), "Unban", sender.getId(), false);
BannedUserIPs.unbanIPs(target.getId());
event.reply("Erfolgreich " + target.getUserName() + " entbannt").setEphemeral(true).queue();
}
}

Datei anzeigen

@ -1,94 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.commands;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.List;
public class WhoisCommand extends BasicDiscordCommand {
public WhoisCommand() {
super("whois", "Der whois Befehl");
addOption(OptionType.STRING, "user", "Der Benutzer", true);
}
@Override
public void run(SlashCommandEvent event) {
if (!testPermission(event)) {
return;
}
String s = event.getOption("user").getAsString();
SteamwarUser user = SteamwarUser.get(s);
if (user == null) {
try {
int id = Integer.parseInt(s);
user = SteamwarUser.get(id);
} catch (NumberFormatException ignored) {
// Ignored
}
}
if (user == null) {
try {
long id = Long.parseLong(s);
user = SteamwarUser.get(id);
} catch (NumberFormatException ignored) {
// Ignored
}
}
if (user == null) {
event.reply("Der angegebene Spieler ist unbekannt").setEphemeral(true).complete();
return;
}
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Whois: " + user.getUserName());
StringBuilder st = new StringBuilder();
st.append("UUID: ").append(user.getUUID()).append("\n");
st.append("ID: ").append(user.getId()).append("\n");
if (user.getDiscordId() != null) {
st.append("DiscordID: ").append(user.getDiscordId()).append("\n");
}
Timestamp timestamp = user.getFirstjoin();
st.append("Beigetreten am: ").append(timestamp == null ? "0000-00-00 00:00:00" : timestamp.toString()).append("\n");
st.append("Online Time: ").append(new DecimalFormat("###.##").format(user.getOnlinetime() / (double) 3600)).append("h\n");
Team team = Team.get(user.getTeam());
st.append("Team: [").append(team.getTeamKuerzel()).append("] ").append(team.getTeamName());
embedBuilder.addField("Daten:", st.toString(), false);
List<Punishment> punishmentList = Punishment.getAllPunishmentsOfPlayer(user.getId());
for (Punishment punishment : punishmentList) {
embedBuilder.addField(punishment.getType().name() + " von " + SteamwarUser.get(punishment.getPunisher()).getUserName(), "Von: " + punishment.getBantime(punishment.getStartTime(), false) + "\nBis: " + punishment.getBantime(punishment.getEndTime(), punishment.isPerma()) + "\nGrund: " + punishment.getReason(), true);
}
event.replyEmbeds(embedBuilder.build()).setEphemeral(true).queue();
}
}

Datei anzeigen

@ -1,39 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import net.dv8tion.jda.api.entities.Emoji;
import net.dv8tion.jda.api.interactions.components.Button;
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
@Data
@AllArgsConstructor
public class DiscordRole {
private String emoji;
private String label;
private String roleId;
public Button toButton() {
return Button.of(ButtonStyle.SECONDARY, roleId, label, Emoji.fromUnicode(emoji));
}
}

Datei anzeigen

@ -1,36 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import net.dv8tion.jda.api.interactions.components.Button;
@Data
@AllArgsConstructor
public class DiscordRulesLink {
private String label;
private String link;
public Button toButton() {
return Button.link(link, label);
}
}

Datei anzeigen

@ -1,41 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import net.dv8tion.jda.api.entities.Emoji;
import net.dv8tion.jda.api.interactions.components.Button;
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
@Data
@AllArgsConstructor
public class DiscordTicketType {
private String key;
private String emoji;
private String label;
private String color;
private String preMessage;
public Button toButton() {
return Button.of(ButtonStyle.valueOf(color), key, Emoji.fromUnicode(emoji)).withLabel(label);
}
}

Datei anzeigen

@ -1,116 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.config;
import de.steamwar.sql.UserPerm;
import net.md_5.bungee.config.Configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SteamwarDiscordBotConfig {
public static boolean loaded = false;
public static String TOKEN;
public static String GUILD;
public static String ANNOUNCEMENTS_CHANNEL;
public static String EVENTS_CHANNEL;
public static String INGAME_CHANNEL;
public static String SERVER_TEAM_CHANNEL;
public static String SCHEMATICS_CHANNEL;
public static String ROLES_CHANNEL;
public static String ROLES_BASE_MESSAGE;
public static String ROLES_ADDED;
public static String ROLES_REMOVED;
public static List<DiscordRole> ROLES;
public static String RULES_CHANNEL;
public static String RULES_TITLE;
public static List<String> RULES_RULES;
public static List<DiscordRulesLink> RULES_LINKS;
public static String TICKET_CATEGORY;
public static String TICKET_CHANNEL;
public static String TICKET_MESSAGE;
public static String TICKET_CREATED;
public static String TICKET_LOG;
public static Map<String, DiscordTicketType> TICKET_TYPES;
public static Map<UserPerm, String> RANKS;
public static void loadConfig(Configuration config) {
TOKEN = config.getString("token");
GUILD = config.getString("guild");
ANNOUNCEMENTS_CHANNEL = config.getString("announcements-channel");
EVENTS_CHANNEL = config.getString("events-channel");
INGAME_CHANNEL = config.getString("ingame-channel");
SERVER_TEAM_CHANNEL = config.getString("server-team-channel");
SCHEMATICS_CHANNEL = config.getString("schematics-channel");
Configuration rolesSection = config.getSection("roles-claim");
ROLES_CHANNEL = rolesSection.getString("channel");
ROLES_BASE_MESSAGE = rolesSection.getString("base");
ROLES_ADDED = rolesSection.getString("added");
ROLES_REMOVED = rolesSection.getString("removed");
ROLES = new ArrayList<>();
for (String roles : rolesSection.getSection("roles").getKeys()) {
Configuration role = rolesSection.getSection("roles").getSection(roles);
ROLES.add(new DiscordRole(role.getString("emoji"),
role.getString("label"),
role.getString("roleId")));
}
Configuration rulesSection = config.getSection("rules");
RULES_CHANNEL = rulesSection.getString("channel");
RULES_TITLE = rulesSection.getString("title");
RULES_RULES = rulesSection.getStringList("rules");
RULES_LINKS = new ArrayList<>();
for (String links : rulesSection.getSection("links").getKeys()) {
Configuration link = rulesSection.getSection("links").getSection(links);
RULES_LINKS.add(new DiscordRulesLink(link.getString("label"),
link.getString("url")));
}
Configuration ticketSection = config.getSection("tickets");
TICKET_CATEGORY = ticketSection.getString("category");
TICKET_CHANNEL = ticketSection.getString("channel");
TICKET_MESSAGE = ticketSection.getString("message");
TICKET_CREATED = ticketSection.getString("created");
TICKET_LOG = ticketSection.getString("log");
TICKET_TYPES = new HashMap<>();
for (String types : ticketSection.getSection("types").getKeys()) {
Configuration type = ticketSection.getSection("types").getSection(types);
TICKET_TYPES.put(types, new DiscordTicketType(types,
type.getString("emoji"),
type.getString("label"),
type.getString("color"),
type.getString("pre")));
}
RANKS = new HashMap<>();
Configuration ranksSections = config.getSection("ranks");
for (String type : ranksSections.getKeys()) {
RANKS.put(UserPerm.valueOf(type.toUpperCase()), ranksSections.getString(type));
}
loaded = true;
}
}

Datei anzeigen

@ -1,73 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.events;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.bungeecore.commands.CheckCommand;
import de.steamwar.sql.SteamwarUser;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import java.awt.*;
@UtilityClass
public class SchematicsManager {
private Message message;
private TextChannel textChannel;
static {
textChannel = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).getTextChannelById(SteamwarDiscordBotConfig.SCHEMATICS_CHANNEL);
assert textChannel != null;
if(textChannel.hasLatestMessage()) {
message = textChannel.getIterableHistory().complete().stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null);
}
}
public void update() {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setColor(Color.GRAY);
embedBuilder.setTitle("Check List");
embedBuilder.setAuthor("SteamWar", "https://www.steamwar.de");
CheckCommand.getSchemsToCheck().forEach(schematic -> {
StringBuilder st = new StringBuilder();
st.append("Typ: ").append(schematic.getSchemtype().getKuerzel());
st.append("\nVon: ").append(SteamwarUser.get(schematic.getOwner()).getUserName());
String checker = CheckCommand.getChecker(schematic);
if (checker != null) {
st.append("\nWird Geprüft von: ").append(checker);
}
embedBuilder.addField(schematic.getName(), st.toString(), true);
});
MessageBuilder messageBuilder = new MessageBuilder();
messageBuilder.setEmbeds(embedBuilder.build());
if (message == null) {
textChannel.sendMessage(messageBuilder.build()).queue(message1 -> message = message1);
} else {
message.editMessage(messageBuilder.build()).queue();
}
}
}

Datei anzeigen

@ -1,50 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.listeners;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import org.jetbrains.annotations.NotNull;
public class AnnouncementListener extends BasicDiscordListener {
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
if (!event.getChannel().getId().equals(SteamwarDiscordBotConfig.ANNOUNCEMENTS_CHANNEL)) {
return;
}
if (event.getAuthor().isBot()) {
return;
}
Message.broadcast("ALERT", event.getMessage().getContentDisplay());
}
public void announce(String message) {
TextChannel textChannel = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).getTextChannelById(SteamwarDiscordBotConfig.ANNOUNCEMENTS_CHANNEL);
assert textChannel != null;
MessageBuilder messageBuilder = new MessageBuilder();
messageBuilder.append(message.replace("&", ""));
textChannel.sendMessage(messageBuilder.build()).queue();
}
}

Datei anzeigen

@ -1,59 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.listeners;
import de.steamwar.bungeecore.bot.AuthManager;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.sql.SteamwarUser;
import net.dv8tion.jda.api.entities.ChannelType;
import net.dv8tion.jda.api.events.interaction.GenericComponentInteractionCreateEvent;
import net.dv8tion.jda.api.interactions.InteractionType;
import org.jetbrains.annotations.NotNull;
public class DiscordAuthListener extends BasicDiscordListener {
@Override
public void onGenericComponentInteractionCreate(@NotNull GenericComponentInteractionCreateEvent event) {
if(event.getType() == InteractionType.COMPONENT) {
if(event.getChannel().getId().equals(SteamwarDiscordBotConfig.RULES_CHANNEL) && event.getComponentId().equals("auth")) {
String authMessage = AuthManager.createDiscordAuthToken(event.getMember());
if(authMessage != null) {
event.reply("Gebe innerhalb der nächsten 10 Minuten ``/verify " + authMessage + "`` auf dem Minecraft Server ein").setEphemeral(true).queue();
} else {
event.reply("Du hast bereits einen Code am laufen").setEphemeral(true).queue();
}
}
if(event.getComponentId().equals("tada") && event.getChannelType() == ChannelType.PRIVATE) {
event.reply(":tada:").setEphemeral(false).queue();
}
if(event.getComponentId().equals("invalid") && event.getChannelType() == ChannelType.PRIVATE) {
SteamwarUser user = SteamwarUser.get(event.getUser().getIdLong());
if(user == null) {
event.reply(":question: Da ist keine verknüpfung?").setEphemeral(false).queue();
} else {
user.setDiscordId(null);
event.reply(":x: Die Verknüpfung wurde beendet").setEphemeral(false).queue();
}
}
}
}
}

Datei anzeigen

@ -1,71 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.listeners;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.bungeecore.listeners.ChatListener;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.messages.ChatSender;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class DiscordChatListener extends BasicDiscordListener {
private final String channel;
private final String format;
private final Supplier<Stream<ChatSender>> targets;
public DiscordChatListener(String channel, String format, Supplier<Stream<ChatSender>> targets) {
this.channel = channel;
this.format = format;
this.targets = targets;
}
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
if (!event.getChannel().getId().equals(channel) || event.getAuthor().isBot())
return;
Member member = event.getMember();
SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong());
if (steamwarUser == null || event.getMessage().getContentRaw().length() > 250 || steamwarUser.isPunished(Punishment.PunishmentType.Ban)) {
event.getMessage().delete().queue();
} else {
ChatListener.sendChat(ChatSender.of(event.getMessage(), steamwarUser), targets.get(), format, null, event.getMessage().getContentDisplay().replace('§', '&').replace('\n', ' '));
}
}
public void send(String message) {
TextChannel textChannel = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).getTextChannelById(channel);
assert textChannel != null;
MessageBuilder messageBuilder = new MessageBuilder();
messageBuilder.append(message.replace("&", "").replace("@everyone", "`@everyone`").replace("@here", "`@here`").replaceAll("<[@#]!?\\d+>", "`$0`"));
textChannel.sendMessage(messageBuilder.build()).queue();
}
}

Datei anzeigen

@ -1,93 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.listeners;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.bungeecore.bot.events.EventManager;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
import de.steamwar.sql.TeamTeilnahme;
import de.steamwar.sql.Event;
import net.dv8tion.jda.api.events.interaction.SelectionMenuEvent;
import net.dv8tion.jda.api.interactions.components.Component;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
public class DiscordEventListener extends BasicDiscordListener {
@Override
public void onSelectionMenu(@NotNull SelectionMenuEvent event) {
if(event.getChannel().getId().equals(SteamwarDiscordBotConfig.EVENTS_CHANNEL) && event.getComponentType() == Component.Type.SELECTION_MENU) {
if(event.getSelectedOptions().isEmpty()) {
event.deferReply(true).queue();
return;
}
if(event.getSelectedOptions().get(0).getValue().matches("([0-9]+)")) {
SteamwarUser user = SteamwarUser.get(event.getUser().getIdLong());
if(user == null) {
event.reply("Du hast dein Minecraft nicht verknüpft").setEphemeral(true).queue();
return;
}
if(user.getTeam() == 0) {
event.reply("Du bist in keinem Team").setEphemeral(true).queue();
return;
}
if(!user.isLeader()) {
event.reply("Du bist kein Leader in deinem Team").setEphemeral(true).queue();
return;
}
if(Event.get() != null) {
event.reply("Du kannst dich nicht während einem Event an einem Event anmelden").setEphemeral(true).queue();
return;
}
Event swEvent = Event.get(Integer.decode(event.getSelectedOptions().get(0).getValue()));
if(swEvent == null){
event.reply("Das Event gibt es nicht").setEphemeral(true).queue();
return;
}
if(Instant.now().isAfter(swEvent.getDeadline().toInstant())){
event.reply("Du kannst dich nicht mehr an diesen Event anmelden").setEphemeral(true).queue();
return;
}
Team team = Team.get(user.getTeam());
if(TeamTeilnahme.nimmtTeil(team.getTeamId(), swEvent.getEventID())){
TeamTeilnahme.notTeilnehmen(team.getTeamId(), swEvent.getEventID());
event.reply("Dein Team **" + team.getTeamName() + "** nimmt nun nicht mehr an **" + swEvent.getEventName() + "** teil!").setEphemeral(true).queue();
}else{
TeamTeilnahme.teilnehmen(team.getTeamId(), swEvent.getEventID());
event.reply("Dein Team **" + team.getTeamName() + "** nimmt nun an **" + swEvent.getEventName() + "** teil!").setEphemeral(true).queue();
}
EventManager.update();
} else {
event.reply("Lefuq?").setEphemeral(true).queue();
}
}
}
}

Datei anzeigen

@ -1,157 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.listeners;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.bot.config.DiscordTicketType;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.interaction.GenericComponentInteractionCreateEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.interactions.InteractionType;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button;
import net.md_5.bungee.api.chat.ClickEvent;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.time.Instant;
import java.util.LinkedList;
public class DiscordTicketListener extends BasicDiscordListener {
@Override
public void onGenericComponentInteractionCreate(@NotNull GenericComponentInteractionCreateEvent event) {
if(event.getType() == InteractionType.COMPONENT && event.getChannelType() == ChannelType.TEXT && event.getTextChannel().getParent() != null && event.getTextChannel().getParent().getId().equals(SteamwarDiscordBotConfig.TICKET_CATEGORY)) {
if(event.getTextChannel().getId().equals(SteamwarDiscordBotConfig.TICKET_CHANNEL) && SteamwarDiscordBotConfig.TICKET_TYPES.containsKey(event.getComponentId())) {
DiscordTicketType ticketType = SteamwarDiscordBotConfig.TICKET_TYPES.get(event.getComponentId());
Category ct = event.getGuild().getCategoryById(SteamwarDiscordBotConfig.TICKET_CATEGORY);
SteamwarUser swUser = SteamwarUser.get(event.getUser().getIdLong());
TextChannel ticketChannel = ct.createTextChannel((swUser == null?event.getUser().getName():swUser.getUserName()) + "-" + event.getComponentId() + "-" + System.currentTimeMillis() % 1000).complete();
ticketChannel.createPermissionOverride(event.getMember()).setAllow(Permission.VIEW_CHANNEL,
Permission.MESSAGE_WRITE,
Permission.MESSAGE_ATTACH_FILES,
Permission.MESSAGE_ADD_REACTION,
Permission.MESSAGE_READ,
Permission.MESSAGE_EMBED_LINKS,
Permission.MESSAGE_HISTORY).complete();
ticketChannel.getManager().setTopic(event.getUser().getId()).complete();
MessageBuilder messageBuilder = new MessageBuilder();
EmbedBuilder builder = new EmbedBuilder();
builder.setDescription(ticketType.getPreMessage());
builder.setTitle("Steamwar Ticket");
builder.setColor(Color.GREEN);
Button closeButton = Button.danger("close-" + ticketChannel.getName(), "Schließen").withEmoji(Emoji.fromUnicode("U+26A0"));
messageBuilder.setEmbeds(builder.build());
messageBuilder.setActionRows(ActionRow.of(closeButton));
ticketChannel.sendMessage(messageBuilder.build()).complete();
event.reply(SteamwarDiscordBotConfig.TICKET_CREATED.replace("%channel%", ticketChannel.getAsMention())).setEphemeral(true).complete();
Message.team("DISCORD_TICKET_NEW", ticketChannel.getName());
} else if(event.getComponentId().startsWith("close-")) {
TextChannel logChannel = event.getGuild().getTextChannelById(SteamwarDiscordBotConfig.TICKET_LOG);
LinkedList<StringBuilder> stringBuilders = new LinkedList<>();
stringBuilders.add(new StringBuilder());
new LinkedList<>(event.getTextChannel().getIterableHistory().complete()).descendingIterator().forEachRemaining(message -> {
if(message.getAuthor().isSystem() || message.getAuthor().isBot()) return;
StringBuilder currentBuilder = new StringBuilder();
currentBuilder.append("<t:").append(message.getTimeCreated().toInstant().getEpochSecond()).append("> ")
.append("**")
.append(message.getAuthor().getName())
.append("**: ")
.append(message.getContentRaw());
if(!message.getAttachments().isEmpty()) {
currentBuilder.append("\n")
.append("Files: ").append("\n");
message.getAttachments().forEach(attachment -> currentBuilder.append(attachment.getUrl()).append("\n"));
}
currentBuilder.append("\n");
if(currentBuilder.length() >= 4096) {
stringBuilders.getLast().append(currentBuilder.substring(0, 4090));
stringBuilders.add(new StringBuilder(currentBuilder.substring(4090, currentBuilder.length() - 1)));
} else if (currentBuilder.length() + stringBuilders.getLast().length() >= 4096) {
stringBuilders.add(new StringBuilder(currentBuilder.toString()));
} else {
stringBuilders.getLast().append(currentBuilder);
}
});
String footer = "<t:" + Instant.now().getEpochSecond() + "> **" + event.getUser().getName() + "**: Ticket geschlossen";
if(stringBuilders.getLast().length() + footer.length() > 4090) {
stringBuilders.add(new StringBuilder(footer));
} else {
stringBuilders.getLast().append(footer);
}
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setColor(Color.GREEN);
User user = event.getJDA().retrieveUserById(event.getTextChannel().getTopic()).complete();
SteamwarUser swuser = SteamwarUser.get(user.getIdLong());
embedBuilder.setAuthor(user.getName(), swuser==null?"https://steamwar.de/":("https://steamwar.de/users/" + swuser.getUserName().toLowerCase() + "/"), user.getAvatarUrl());
embedBuilder.setTimestamp(Instant.now());
embedBuilder.setTitle(event.getTextChannel().getName());
stringBuilders.forEach(stringBuilder -> {
embedBuilder.setDescription(stringBuilder.toString());
MessageBuilder builder = new MessageBuilder();
builder.setEmbeds(embedBuilder.build());
logChannel.sendMessage(builder.build()).queue();
});
Message.team("DISCORD_TICKET_CLOSED", event.getTextChannel().getName());
event.getTextChannel().delete().reason("Closed").queue();
}
}
}
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
if(event.getChannel().getParent() != null && event.getChannel().getParent().getId().equals(SteamwarDiscordBotConfig.TICKET_CATEGORY)) {
if(!event.getChannel().getId().equals(SteamwarDiscordBotConfig.TICKET_CHANNEL) && !event.getChannel().getId().equals(SteamwarDiscordBotConfig.TICKET_LOG)) {
BungeeCore.get().getProxy().getPlayers().forEach(player -> {
if(event.getAuthor().isBot() || event.getAuthor().isSystem()) return;
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
boolean sendMessage;
if(user.getDiscordId() == null) {
sendMessage = user.hasPerm(UserPerm.CHECK);
} else {
if(event.getAuthor().getId().equals(user.getDiscordId())) return;
sendMessage = user.getDiscordId().equals(event.getChannel().getTopic()) || user.hasPerm(UserPerm.CHECK);
}
if(sendMessage) {
Message.sendPrefixless("DISCORD_TICKET_MESSAGE", player, "Zur nachricht", new ClickEvent(ClickEvent.Action.OPEN_URL, event.getMessage().getJumpUrl()), event.getChannel().getName(), event.getAuthor().getName(), event.getMessage().getContentRaw());
}
});
}
}
}
}

Datei anzeigen

@ -1,80 +0,0 @@
/*
* This file is a part of the SteamWar software.
* <p>
* Copyright (C) 2021 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.
* <p>
* 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.
* <p>
* 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.bot.listeners;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.sql.NodeData;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent;
import java.io.InputStream;
public class PrivateMessageListener extends BasicDiscordListener {
@Override
public void onPrivateMessageReceived(PrivateMessageReceivedEvent event) {
if(!event.getMessage().getAttachments().isEmpty()) {
SteamwarUser user = SteamwarUser.get(event.getAuthor().getIdLong());
if (user == null) {
event.getMessage().reply("Du must dein Minecraft Account mit dem Bot verbinden, gehe dazu auf dem SteamWar Discord in den `regeln-infos` Channel und Klicke auf `Minecraft Verknüpfen`").complete();
return;
}
if(user.isPunished(Punishment.PunishmentType.NoSchemReceiving)) {
event.getMessage().reply("Du darfst keine Schematics hochladen").complete();
return;
}
for (Message.Attachment attachment : event.getMessage().getAttachments()) {
if(attachment.getFileExtension() == null ||
(!attachment.getFileExtension().equalsIgnoreCase("schem") &&
!attachment.getFileExtension().equalsIgnoreCase("schematic"))) {
event.getMessage().reply("`" + attachment.getFileName() + "` wird ignoriert, da die Datei keine Schematic ist").queue();
continue;
}
boolean newFormat = attachment.getFileExtension().equalsIgnoreCase("schem");
int dot = attachment.getFileName().lastIndexOf(".");
String name = attachment.getFileName().substring(0, dot);
if(SchematicNode.invalidSchemName(new String[] {name})) {
event.getMessage().reply("`" + name + "` hat nicht zugelassene Zeichen im Namen").queue();
continue;
}
SchematicNode node = SchematicNode.getSchematicNode(user.getId(), name, (Integer) null);
if(node == null) {
node = SchematicNode.createSchematic(user.getId(), name, null);
}
try {
InputStream in = attachment.retrieveInputStream().get();
NodeData.get(node).saveFromStream(in, newFormat);
in.close();
event.getMessage().reply("`" + name + "` wurde erfolgreich hochgeladen").queue();
} catch (Exception e) {
event.getMessage().reply("`" + name + "` konnte nicht hochgeladen werden, bitte versuche es später nochmal oder wende dich an einen Developer").queue();
BungeeCore.log("Could not Upload Schem \"" + name + "\" from User \"" + user.getUserName() + "\"", e);
}
}
}
}
}

Datei anzeigen

@ -1,42 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.listeners;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import net.dv8tion.jda.api.entities.ChannelType;
import net.dv8tion.jda.api.events.interaction.GenericComponentInteractionCreateEvent;
import net.dv8tion.jda.api.interactions.InteractionType;
import org.jetbrains.annotations.NotNull;
public class RolesInteractionButtonListener extends BasicDiscordListener {
@Override
public void onGenericComponentInteractionCreate(@NotNull GenericComponentInteractionCreateEvent event) {
if(event.getType() == InteractionType.COMPONENT && event.getChannelType() == ChannelType.TEXT && event.getTextChannel().getId().equals(SteamwarDiscordBotConfig.ROLES_CHANNEL) && SteamwarDiscordBotConfig.ROLES.stream().anyMatch(discordRole -> discordRole.getRoleId().equals(event.getComponentId()))) {
if (event.getMember().getRoles().stream().anyMatch(role -> role.getId().equals(event.getComponentId()))) {
event.getGuild().removeRoleFromMember(event.getMember(), event.getGuild().getRoleById(event.getComponentId())).complete();
event.reply(SteamwarDiscordBotConfig.ROLES_REMOVED.replace("%role%", event.getGuild().getRoleById(event.getComponentId()).getAsMention())).setEphemeral(true).queue();
} else {
event.getGuild().addRoleToMember(event.getMember(), event.getGuild().getRoleById(event.getComponentId())).complete();
event.reply(SteamwarDiscordBotConfig.ROLES_ADDED.replace("%role%", event.getGuild().getRoleById(event.getComponentId()).getAsMention())).setEphemeral(true).queue();
}
}
}
}

Datei anzeigen

@ -1,32 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.listeners;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import org.jetbrains.annotations.NotNull;
public class SlashCommandListener extends BasicDiscordListener {
@Override
public void onSlashCommand(@NotNull SlashCommandEvent event) {
SteamwarDiscordBot.getDiscordCommandMap().get(event.getName()).run(event);
}
}

Datei anzeigen

@ -1,69 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.util;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.sql.SteamwarUser;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@UtilityClass
public class DiscordRanks {
public void update(SteamwarUser steamwarUser) {
if (steamwarUser.getDiscordId() == null) {
return;
}
Guild guild = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD);
guild.retrieveMemberById(steamwarUser.getDiscordId()).queue(member -> {
List<Role> roleList = member.getRoles();
Set<String> strings = new HashSet<>(SteamwarDiscordBotConfig.RANKS.values());
String needed = SteamwarDiscordBotConfig.RANKS.get(steamwarUser.prefix());
for (Role role : roleList) {
if (!strings.contains(role.getId())) {
continue;
}
if (role.getId().equals(needed)) {
needed = "";
continue;
}
guild.removeRoleFromMember(member, role).complete();
}
if (needed != null && !needed.isEmpty()) {
guild.addRoleToMember(member, guild.getRoleById(needed)).complete();
}
}, throwable -> {
if(throwable instanceof ErrorResponseException) {
ErrorResponseException e = (ErrorResponseException) throwable;
if(e.getErrorCode() == 10007) {
steamwarUser.setDiscordId(null);
}
}
});
}
}

Datei anzeigen

@ -1,61 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.util;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button;
import java.util.ArrayList;
import java.util.List;
@UtilityClass
public class DiscordRolesMessage {
public void sendMessage() {
TextChannel channel = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).getTextChannelById(SteamwarDiscordBotConfig.ROLES_CHANNEL);
assert channel != null;
MessageBuilder builder = new MessageBuilder();
builder.setContent(SteamwarDiscordBotConfig.ROLES_BASE_MESSAGE);
List<Button> buttons = new ArrayList<>();
SteamwarDiscordBotConfig.ROLES.forEach(discordRole -> buttons.add(discordRole.toButton()));
builder.setActionRows(ActionRow.of(buttons));
if(channel.hasLatestMessage()) {
channel.getIterableHistory().queue(messages -> {
Message message = messages.stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null);
if (message != null) {
message.editMessage(builder.build()).queue();
} else {
channel.sendMessage(builder.build()).queue();
}
});
} else {
channel.sendMessage(builder.build()).queue();
}
}
}

Datei anzeigen

@ -1,68 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.util;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Emoji;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
@UtilityClass
public class DiscordRulesMessage {
public void sendMessage() {
TextChannel channel = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).getTextChannelById(SteamwarDiscordBotConfig.RULES_CHANNEL);
assert channel != null;
Message message = null;
if(channel.hasLatestMessage()) {
message = channel.getIterableHistory().complete().stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null);
}
EmbedBuilder builder = new EmbedBuilder();
builder.setDescription(SteamwarDiscordBotConfig.RULES_RULES.stream().reduce((s, s2) -> s + "\n" + s2).get());
builder.setColor(Color.GRAY);
builder.setAuthor("SteamWar", "https://www.steamwar.de");
builder.setTitle(SteamwarDiscordBotConfig.RULES_TITLE);
List<Button> buttons = new ArrayList<>();
SteamwarDiscordBotConfig.RULES_LINKS.forEach(discordRulesLink -> buttons.add(discordRulesLink.toButton()));
Button authButton = Button.primary("auth", Emoji.fromUnicode("U+2705")).withLabel("Minecraft verknüpfen");
MessageBuilder messageBuilder = new MessageBuilder();
messageBuilder.setEmbeds(builder.build());
messageBuilder.setActionRows(ActionRow.of(buttons), ActionRow.of(authButton));
if (message != null) {
message.editMessage(messageBuilder.build()).queue();
} else {
channel.sendMessage(messageBuilder.build()).queue();
}
}
}

Datei anzeigen

@ -1,79 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.util;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Emoji;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button;
import java.awt.*;
import java.time.Instant;
@UtilityClass
public class DiscordSchemAlert {
public void sendDecline(SchematicNode schematic, SteamwarUser user, String reason) {
if(user.getDiscordId() != null) {
User dcUser = SteamwarDiscordBot.instance().getJda().retrieveUserById(user.getDiscordId()).complete();
EmbedBuilder builder = new EmbedBuilder();
builder.setAuthor("SteamWar", "https://steamwar.de", "https://cdn.discordapp.com/app-icons/869606970099904562/60c884000407c02671d91d8e7182b8a1.png");
builder.setColor(Color.RED);
builder.setTitle("SteamWar-Schematic Info");
builder.setDescription("Deine Schematic **" + schematic.getName() + "** wurde abgelehnt. **Grund:** \n" + reason);
builder.setTimestamp(Instant.now());
MessageBuilder messageBuilder = new MessageBuilder();
messageBuilder.setEmbeds(builder.build());
try {
dcUser.openPrivateChannel().complete().sendMessage(messageBuilder.build()).queue();
} catch (Exception e) {
// Ignored
}
}
}
public void sendAccept(SchematicNode schematic, SteamwarUser user) {
if(user.getDiscordId() != null) {
User dcUser = SteamwarDiscordBot.instance().getJda().retrieveUserById(user.getDiscordId()).complete();
EmbedBuilder builder = new EmbedBuilder();
builder.setAuthor("SteamWar", "https://steamwar.de", "https://cdn.discordapp.com/app-icons/869606970099904562/60c884000407c02671d91d8e7182b8a1.png");
builder.setColor(Color.GREEN);
builder.setTitle("SteamWar-Schematic Info");
builder.setDescription("Deine Schematic **" + schematic.getName() + "** wurde angenommen.");
builder.setTimestamp(Instant.now());
MessageBuilder messageBuilder = new MessageBuilder();
messageBuilder.setEmbeds(builder.build());
messageBuilder.setActionRows(ActionRow.of(Button.success("tada", Emoji.fromUnicode("U+1F389"))));
try {
dcUser.openPrivateChannel().complete().sendMessage(messageBuilder.build()).queue();
} catch (Exception e) {
// Ignored
}
}
}
}

Datei anzeigen

@ -1,76 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.bot.util;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.bot.config.DiscordTicketType;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@UtilityClass
public class DiscordTicketMessage {
public void sendMessage() {
TextChannel channel = SteamwarDiscordBot.instance().getJda().getGuildById(SteamwarDiscordBotConfig.GUILD).getTextChannelById(SteamwarDiscordBotConfig.TICKET_CHANNEL);
assert channel != null;
Message message = null;
if(channel.hasLatestMessage()) {
message = channel.getIterableHistory().complete().stream().filter(m -> m.getAuthor().isBot()).findFirst().orElse(null);
}
EmbedBuilder builder = new EmbedBuilder();
builder.setDescription(SteamwarDiscordBotConfig.TICKET_MESSAGE);
builder.setTitle("Steamwar-Tickets");
builder.setColor(Color.RED);
List<List<Button>> buttons = new ArrayList<>();
chunked(new ArrayList<>(SteamwarDiscordBotConfig.TICKET_TYPES.values()), 5).forEach(discordTicketTypes -> {
buttons.add(discordTicketTypes.stream().map(DiscordTicketType::toButton).collect(Collectors.toList()));
});
MessageBuilder messageBuilder = new MessageBuilder();
messageBuilder.setEmbeds(builder.build());
messageBuilder.setActionRows(buttons.stream().map(ActionRow::of).collect(Collectors.toList()));
if (message != null) {
message.editMessage(messageBuilder.build()).queue();
} else {
channel.sendMessage(messageBuilder.build()).queue();
}
}
private static <T> List<List<T>> chunked(List<T> list, int chunkSize) {
List<List<T>> chunks = new ArrayList<>();
for (int i = 0; i < list.size(); i += chunkSize) {
chunks.add(list.subList(i, Math.min(i + chunkSize, list.size())));
}
return chunks;
}
}

Datei anzeigen

@ -1,340 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.inventory.SWInventory;
import de.steamwar.bungeecore.inventory.SWItem;
import de.steamwar.bungeecore.network.NetworkSender;
import de.steamwar.bungeecore.util.BauLock;
import de.steamwar.bungeecore.util.BauLockState;
import de.steamwar.bungeecore.util.Chat19;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.command.TypeValidator;
import de.steamwar.network.packets.server.BaumemberUpdatePacket;
import de.steamwar.sql.BauweltMember;
import de.steamwar.sql.SteamwarUser;
import net.md_5.bungee.api.CommandSender;
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.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class BauCommand extends SWCommand {
private final HelpCommand command;
public BauCommand(HelpCommand command){
super("bau", null, "b", "build", "gs");
this.command = command;
}
@Register(noTabComplete = true)
public void genericHelp(ProxiedPlayer p, String... args) {
this.command.sendBauHelp(p);
}
@Register
public void toBau(ProxiedPlayer p, @Mapper("version") @OptionalValue(value = "", onlyUINIG = true) ServerStarter.Version version) {
new ServerStarter().build(version, p.getUniqueId()).send(p).start();
}
@Mapper(value = "version", local = true)
public TypeMapper<ServerStarter.Version> versionMapper() {
Map<String, ServerStarter.Version> versionMap = new HashMap<>();
versionMap.put("20", ServerStarter.Version.PAPER_20);
versionMap.put("1.20", ServerStarter.Version.PAPER_20);
versionMap.put("as", ServerStarter.Version.PAPER_20);
versionMap.put("airship", ServerStarter.Version.PAPER_20);
versionMap.put("wg", ServerStarter.Version.PAPER_20);
versionMap.put("wargear", ServerStarter.Version.PAPER_20);
versionMap.put("ws", ServerStarter.Version.PAPER_20);
versionMap.put("warship", ServerStarter.Version.PAPER_20);
versionMap.put("19", ServerStarter.Version.PAPER_19);
versionMap.put("1.19", ServerStarter.Version.PAPER_19);
versionMap.put("mwg", ServerStarter.Version.PAPER_19);
versionMap.put("miniwargear", ServerStarter.Version.PAPER_19);
versionMap.put("15", ServerStarter.Version.SPIGOT_15);
versionMap.put("1.15", ServerStarter.Version.SPIGOT_15);
versionMap.put("12", ServerStarter.Version.SPIGOT_12);
versionMap.put("1.12", ServerStarter.Version.SPIGOT_12);
return new TypeMapper<ServerStarter.Version>() {
@Override
public ServerStarter.Version map(CommandSender commandSender, String[] previousArguments, String s) {
if (commandSender == null) return null;
ProxiedPlayer player = (ProxiedPlayer) commandSender;
if (s.isEmpty()) {
int version = player.getPendingConnection().getVersion();
if (version > 762) { // Version > 1.19.4
return ServerStarter.Version.PAPER_20;
} else if (version > 578) { // Version > 1.15.2
return ServerStarter.Version.PAPER_19;
} else if (version > 340) { // Version > 1.12.2
return ServerStarter.Version.SPIGOT_15;
} else {
return ServerStarter.Version.SPIGOT_12;
}
}
return versionMap.get(s.toLowerCase());
}
@Override
public Collection<String> tabCompletes(CommandSender sender, String[] previousArguments, String s) {
return versionMap.keySet();
}
};
}
@Register(value = "addmember", description = "BAU_ADDMEMBER_USAGE")
public void addmember(ProxiedPlayer p, @Validator("addMemberTarget") SteamwarUser target) {
BauweltMember.addMember(p.getUniqueId(), target.getUUID());
Message.send("BAU_ADDMEMBER_ADDED", p);
ProxiedPlayer z = ProxyServer.getInstance().getPlayer(target.getUUID());
if(z != null)
Message.send("BAU_ADDMEMBER_ADDED_TARGET", z, p.getName());
}
@Validator(value = "addMemberTarget", local = true)
public TypeValidator<SteamwarUser> addMemberTargetValidator() {
return (sender, value, messageSender) -> {
if (value == null) {
messageSender.send("UNKNOWN_PLAYER");
return false;
}
if (((ProxiedPlayer) sender).getUniqueId().equals(value.getUUID())) {
messageSender.send("BAU_ADDMEMBER_SELFADD");
return false;
}
if (BauweltMember.getBauMember(((ProxiedPlayer) sender).getUniqueId(), value.getUUID()) != null) {
messageSender.send("BAU_ADDMEMBER_ISADDED");
return false;
}
return true;
};
}
@Register(value = "tp", description = "BAU_TP_USAGE")
@Register("teleport")
public void teleport(ProxiedPlayer p, @Validator("teleportTarget") SteamwarUser worldOwner, @Mapper("version") @OptionalValue(value = "", onlyUINIG = true) ServerStarter.Version version) {
new ServerStarter().build(version, worldOwner.getUUID()).send(p).start();
}
@Validator(value = "teleportTarget", local = true)
public TypeValidator<SteamwarUser> teleportTargetValidator() {
return (sender, value, messageSender) -> {
if (value == null) {
messageSender.send("UNKNOWN_PLAYER");
return false;
}
ProxiedPlayer p = (ProxiedPlayer) sender;
if (!p.getUniqueId().equals(value.getUUID()) && BauweltMember.getBauMember(value.getUUID(), p.getUniqueId()) == null) {
SubserverSystem.sendDeniedMessage(p, value.getUUID());
messageSender.send("BAU_TP_NOALLOWED");
return false;
}
return !BauLock.checkNotifyLocked(value, p);
};
}
@Register("info")
public void info(ProxiedPlayer p) {
Chat19.chat(p, "/bauinfo");
}
@Register("setspectator")
public void setSpectator(ProxiedPlayer p, @Mapper("addedUsers") @AllowNull @OptionalValue("") SteamwarUser user) {
if (user == null) {
Message.send("BAU_MEMBER_SET_USAGE", p, "setspectator");
return;
}
BauweltMember target = member(p, user);
if (target == null)
return;
target.setBuild(false);
target.setSupervisor(false);
clearMembercache(p);
sendPermissionUpdate(p, target, "BAU_MEMBER_SET_SPECTATOR");
}
@Register("setbuild")
public void setBuild(ProxiedPlayer p, @Mapper("addedUsers") @AllowNull @OptionalValue("") SteamwarUser user) {
if (user == null) {
Message.send("BAU_MEMBER_SET_USAGE", p, "setbuild");
return;
}
BauweltMember target = member(p, user);
if (target == null)
return;
target.setBuild(true);
target.setSupervisor(false);
clearMembercache(p);
sendPermissionUpdate(p, target, "BAU_MEMBER_SET_BUILDER");
}
@Register("setsupervisor")
public void setSupervisor(ProxiedPlayer p, @Mapper("addedUsers") @AllowNull @OptionalValue("") SteamwarUser user) {
if (user == null) {
Message.send("BAU_MEMBER_SET_USAGE", p, "setsupervisor");
return;
}
BauweltMember target = member(p, user);
if (target == null)
return;
target.setBuild(true);
target.setSupervisor(true);
clearMembercache(p);
sendPermissionUpdate(p, target, "BAU_MEMBER_SET_SUPERVISOR");
}
private static void clearMembercache(ProxiedPlayer p){
for(ServerInfo info : ProxyServer.getInstance().getServers().values()){
Subserver server = Subserver.getSubserver(info);
if(server != null && server.getType() == Servertype.BAUSERVER && ((Bauserver)server).getOwner().equals(p.getUniqueId())){
info.getPlayers().stream().findAny().ifPresent(player -> NetworkSender.send(player, new BaumemberUpdatePacket()));
break;
}
}
}
@Register(value = "delmember", description = "BAU_DELMEMBER_USAGE")
public void delmember(ProxiedPlayer p, @Mapper("addedUsers") SteamwarUser user) {
BauweltMember target = member(p, user);
if (target == null)
return;
if(SteamwarUser.get(target.getMemberID()).getUUID().equals(p.getUniqueId())) {
Message.send("BAU_DELMEMBER_SELFDEL", p);
return;
}
target.remove();
ProxiedPlayer toRemove = ProxyServer.getInstance().getPlayer(SteamwarUser.get(target.getMemberID()).getUUID());
if(toRemove != null){
Message.send("BAU_DELMEMBER_DELETED_TARGET", toRemove, p.getName());
Subserver currentServer = Subserver.getSubserver(toRemove.getServer().getInfo());
if (currentServer != null && currentServer.getType() == Servertype.BAUSERVER && ((Bauserver) currentServer).getOwner().equals(p.getUniqueId())) {
toRemove.connect(ProxyServer.getInstance().getServerInfo(BungeeCore.LOBBY_SERVER));
}
}
Message.send("BAU_DELMEMBER_DELETED", p);
}
@Mapper(value = "addedUsers", local = true)
public TypeMapper<SteamwarUser> addedUsers() {
return new TypeMapper<SteamwarUser>() {
@Override
public SteamwarUser map(CommandSender commandSender, String[] previousArguments, String s) {
return SteamwarUser.get(s);
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
if (!(sender instanceof ProxiedPlayer)) return Collections.emptyList();
return BauweltMember.getMembers(((ProxiedPlayer) sender).getUniqueId()).stream()
.map(bauweltMember -> SteamwarUser.get(bauweltMember.getMemberID()))
.map(steamwarUser -> steamwarUser.getUserName())
.collect(Collectors.toList());
}
};
}
@Register("resetall")
@Register("delete")
public void delete(ProxiedPlayer p, @Mapper("version") @OptionalValue(value = "", onlyUINIG = true) ServerStarter.Version version) {
deleteConfirmation(p, () -> deleteWorld(p, version.getWorldFolder(ServerStarter.WORLDS_BASE_PATH) + (version != ServerStarter.Version.SPIGOT_12 ? SteamwarUser.get(p.getUniqueId()).getId() : p.getUniqueId().toString())));
}
private static void deleteConfirmation(ProxiedPlayer p, Runnable worldDeletion) {
SWInventory inventory = new SWInventory(p, 9, Message.parse("BAU_DELETE_GUI_NAME", p));
inventory.addItem(8, new SWItem(Message.parse("BAU_DELETE_GUI_CANCEL", p), 1), click ->
inventory.close()
);
inventory.addItem(0, new SWItem(Message.parse("BAU_DELETE_GUI_DELETE", p), 10), click -> {
worldDeletion.run();
inventory.close();
});
inventory.open();
}
private static void deleteWorld(ProxiedPlayer player, String world) {
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
Bauserver subserver = Bauserver.get(player.getUniqueId());
if(subserver != null)
subserver.stop();
SubserverSystem.deleteFolder(BungeeCore.local, world);
Message.send("BAU_DELETE_DELETED", player);
});
}
@Register("test")
@Register("testarena")
public void testarena(ProxiedPlayer p, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
FightCommand.createArena(p, "/bau testarena ", false, arenaMode, map, false, (player, mode, m) -> {
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> new ServerStarter().test(mode, m, p).start());
});
}
@Register(value = "lock", description = "BAU_LOCKED_OPTIONS")
public void lock(ProxiedPlayer p, BauLockState bauLockState) {
BauLock.setLocked(p, bauLockState);
}
@Register("unlock")
public void unlock(ProxiedPlayer p) {
BauLock.setLocked(p, BauLockState.OPEN);
}
private static BauweltMember member(ProxiedPlayer p, SteamwarUser member){
if (member == null) {
Message.send("UNKNOWN_PLAYER", p);
return null;
}
BauweltMember target = BauweltMember.getBauMember(p.getUniqueId(), member.getUUID());
if (target == null) {
Message.send("BAU_MEMBER_NOMEMBER", p);
return null;
}
return target;
}
private static void sendPermissionUpdate(ProxiedPlayer p, BauweltMember target, String what){
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(SteamwarUser.get(target.getMemberID()).getUUID());
if(player != null)
Message.send("BAU_MEMBER_SET_TARGET", player, p.getName(), Message.parse(what, player));
Message.send("BAU_MEMBER_SET", p, Message.parse(what, p));
}
}

Datei anzeigen

@ -1,174 +0,0 @@
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.ServerStarter;
import de.steamwar.bungeecore.listeners.ConnectionListener;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.messages.ChatSender;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;
public class BuilderCloudCommand extends SWCommand {
private final Map<String, ServerStarter.Version> versionMap = new HashMap<>();
public BuilderCloudCommand() {
super("buildercloud", ConnectionListener.BUILDERCLOUD_PERMISSION, "builder");
versionMap.put("15", ServerStarter.Version.SPIGOT_15);
versionMap.put("1.15", ServerStarter.Version.SPIGOT_15);
versionMap.put("1.15.2", ServerStarter.Version.SPIGOT_15);
versionMap.put("19", ServerStarter.Version.PAPER_19);
versionMap.put("1.19", ServerStarter.Version.PAPER_19);
versionMap.put("1.19.2", ServerStarter.Version.PAPER_19);
versionMap.put("20", ServerStarter.Version.PAPER_20);
versionMap.put("1.20", ServerStarter.Version.PAPER_20);
versionMap.put("1.20.1", ServerStarter.Version.PAPER_20);
}
@Register(value = "create", description = "BUILDERCLOUD_CREATE_USAGE")
public void create(ProxiedPlayer player, @ErrorMessage("BUILDERCLOUD_VERSION") ServerStarter.Version version, @Mapper("map") String map, @OptionalValue("") @Mapper("generator") @AllowNull File generator) {
mapFile(version, map).mkdir();
new ServerStarter().builder(version, map, generator).send(player).start();
}
@Register(description = "BUILDERCLOUD_USAGE")
public void start(ProxiedPlayer player, @ErrorMessage("BUILDERCLOUD_VERSION") ServerStarter.Version version, @Mapper("map") String map) {
if(!mapFile(version, map).exists()) {
ChatSender.of(player).system("BUILDERCLOUD_UNKNOWN_MAP");
return;
}
new ServerStarter().builder(version, map, null).send(player).start();
}
@Register(value = "rename", description = "BUILDERCLOUD_RENAME_USAGE")
public void rename(ProxiedPlayer player, @ErrorMessage("BUILDERCLOUD_VERSION") ServerStarter.Version version, @Mapper("map") String oldName, String newName) {
File oldMap = mapFile(version, oldName);
if(!oldMap.exists()) {
ChatSender.of(player).system("BUILDERCLOUD_UNKNOWN_MAP");
return;
}
File newMap = mapFile(version, newName);
if(newMap.exists()) {
ChatSender.of(player).system("BUILDERCLOUD_EXISTING_MAP");
return;
}
try {
Files.move(oldMap.toPath(), newMap.toPath());
} catch (IOException e) {
throw new SecurityException(e);
}
ChatSender.of(player).system("BUILDERCLOUD_RENAMED");
}
@Register(value = "deploy", description = "BUILDERCLOUD_DEPLOY_USAGE")
public void deploy(ProxiedPlayer player, @Mapper("nonHistoricArenaMode") ArenaMode arenaMode, @ErrorMessage("BUILDERCLOUD_VERSION") ServerStarter.Version version, @Mapper("map") String map) {
if(!mapFile(version, map).exists()) {
ChatSender.of(player).system("BUILDERCLOUD_UNKNOWN_MAP");
return;
}
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
BungeeCore.local.execute("/binarys/deployarena.py", arenaMode.getConfig(), Integer.toString(version.getVersionSuffix()), map);
ArenaMode.init();
ChatSender.of(player).system("BUILDERCLOUD_DEPLOY_FINISHED");
});
}
@ClassMapper(value = ServerStarter.Version.class, local = true)
private TypeMapper<ServerStarter.Version> versionTypeMapper() {
return new TypeMapper<ServerStarter.Version>() {
@Override
public ServerStarter.Version map(CommandSender commandSender, String[] previousArguments, String s) {
return versionMap.get(s);
}
@Override
public Collection<String> tabCompletes(CommandSender sender, String[] previousArguments, String s) {
return versionMap.keySet();
}
};
}
@Cached(global = true)
@Mapper(value = "map", local = true)
private TypeMapper<String> mapTypeMapper() {
return new TypeMapper<String>() {
@Override
public String map(CommandSender commandSender, String[] previousArguments, String s) {
return s;
}
@Override
public Collection<String> tabCompletes(CommandSender sender, String[] previousArguments, String s) {
File folder = getWorldFolder(previousArguments, 1);
String[] files;
if(folder == null || (files = folder.list()) == null)
return Collections.emptyList();
return Arrays.stream(files).filter(file -> new File(folder, file).isDirectory()).filter(file -> s.startsWith(".") || !file.startsWith(".")).collect(Collectors.toList());
}
};
}
@Cached(global = true)
@Mapper(value = "generator", local = true)
private TypeMapper<File> generatorTypeMapper() {
return new TypeMapper<File>() {
@Override
public File map(CommandSender commandSender, String[] previousArguments, String s) {
if(s.equals(""))
return null;
File folder = getWorldFolder(previousArguments, 2);
if(folder == null)
throw new SecurityException();
File generator = new File(folder, s + ".dat");
if(!generator.exists() || !generator.isFile())
throw new SecurityException();
return generator;
}
@Override
public Collection<String> tabCompletes(CommandSender sender, String[] previousArguments, String s) {
File folder = getWorldFolder(previousArguments, 2);
String[] files;
if(folder == null || (files = folder.list()) == null)
return Collections.emptyList();
return Arrays.stream(files).filter(file -> new File(folder, file).isFile()).filter(file -> file.endsWith(".dat")).map(file -> file.substring(0, file.length() - 4)).collect(Collectors.toList());
}
};
}
private File mapFile(ServerStarter.Version version, String map) {
return new File(version.getWorldFolder(ServerStarter.BUILDER_BASE_PATH), map);
}
private File getWorldFolder(String[] previousArguments, int offset) {
ServerStarter.Version v = versionMap.get(previousArguments[previousArguments.length - offset]);
if(v == null)
return null;
return new File(v.getWorldFolder(ServerStarter.BUILDER_BASE_PATH));
}
}

Datei anzeigen

@ -1,340 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.bot.util.DiscordSchemAlert;
import de.steamwar.bungeecore.listeners.ConnectionListener;
import de.steamwar.sql.*;
import de.steamwar.command.SWCommand;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.config.Configuration;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public class CheckCommand extends SWCommand {
private static final Map<SchematicType, SchematicType> fightTypes = new HashMap<>();
private static Map<SchematicType, List<String>> checkQuestions = new HashMap<>();
private static Map<SchematicType, List<String>> ranks = new HashMap<>();
private static Map<UUID, CheckSession> currentCheckers = new HashMap<>();
private static Map<Integer, CheckSession> currentSchems = new HashMap<>();
public static void setCheckQuestions(SchematicType checkType, Configuration config) {
checkQuestions.put(checkType, config.getStringList("CheckQuestions"));
if(!config.getStringList("Ranks").isEmpty())
ranks.put(checkType, config.getStringList("Ranks"));
}
public static void addFightType(SchematicType checkType, SchematicType fightType) {
fightTypes.put(checkType, fightType);
}
public static boolean isChecking(ProxiedPlayer player){
return currentCheckers.containsKey(player.getUniqueId());
}
public static SchematicNode getCheckingSchem(ProxiedPlayer player) {
return currentCheckers.get(player.getUniqueId()).schematic;
}
public CheckCommand() {
super("check", ConnectionListener.CHECK_PERMISSION);
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> {
List<SchematicNode> schematics = getSchemsToCheck();
if(schematics.size() != currentCheckers.size())
Message.team("CHECK_REMINDER", "CHECK_REMINDER_HOVER", new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/check list"), schematics.size() - currentCheckers.size());
}, 10, 10, TimeUnit.MINUTES);
}
public static void sendReminder(ProxiedPlayer player) {
List<SchematicNode> schematics = getSchemsToCheck();
if(schematics.size() != currentCheckers.size())
Message.send("CHECK_REMINDER", player, Message.parse("CHECK_REMINDER_HOVER", player), new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/check list"), schematics.size() - currentCheckers.size());
}
@Register(value = "list", description = "CHECK_HELP_LIST")
public void list(ProxiedPlayer player) {
List<SchematicNode> schematicList = getSchemsToCheck();
Message.sendPrefixless("CHECK_LIST_HEADER", player, schematicList.size());
for (SchematicNode schematic : schematicList) {
CheckSession current = currentSchems.get(schematic.getId());
long waitedMillis = Timestamp.from(Instant.now()).getTime() - schematic.getLastUpdate().getTime();
String color = waitedMillis > 14400000 ? (waitedMillis > 86400000 ? "§c" : "§e") : "§a";
long hours = waitedMillis / 3600000;
long minutes = (waitedMillis - hours * 3600000) / 60000;
String waitTime = color + Message.parse("CHECK_LIST_WAIT", player, hours, (minutes < 10) ? "0" + minutes : minutes);
if (current == null) {
Message.sendPrefixless("CHECK_LIST_TO_CHECK", player,
Message.parse("CHECK_LIST_TO_CHECK_HOVER", player),
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/check schematic " + schematic.getId()),
waitTime,
schematic.getSchemtype().getKuerzel(), SteamwarUser.get(schematic.getOwner()).getUserName(), schematic.getName());
} else {
Message.sendPrefixless("CHECK_LIST_CHECKING", player,
Message.parse("CHECK_LIST_CHECKING_HOVER", player),
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/join " + current.checker.getName()),
waitTime,
schematic.getSchemtype().getKuerzel(), SteamwarUser.get(schematic.getOwner()).getUserName(), schematic.getName(), current.checker.getName());
}
}
}
@Register(value = "schematic", noTabComplete = true)
public void schematic(ProxiedPlayer player, String schemID) {
if(isChecking(player)){
Message.send("CHECK_SCHEMATIC_ALREADY_CHECKING", player);
return;
}
SteamwarUser checkingUser = SteamwarUser.get(player.getUniqueId());
SchematicNode schem = SchematicNode.getSchematicNode(Integer.parseInt(schemID));
if(!schem.getSchemtype().check()){
ProxyServer.getInstance().getLogger().log(Level.SEVERE, player.getName() + " tried to check an uncheckable schematic!");
return;
}else if(schem.getOwner() == checkingUser.getId()) {
Message.send("CHECK_SCHEMATIC_OWN", player);
return;
}
int playerTeam = checkingUser.hasPerm(UserPerm.MODERATION) ? 0 : checkingUser.getTeam();
if (playerTeam != 0 && SteamwarUser.get(schem.getOwner()).getTeam() == playerTeam) {
Message.send("CHECK_SCHEMATIC_OWN_TEAM", player);
return;
}
new CheckSession(player, schem);
}
@Register(value = "cancel", description = "CHECK_HELP_CANCEL")
@Register("abort")
public void abortCommand(ProxiedPlayer player) {
abort(player);
}
public static void abort(ProxiedPlayer player) {
if(notChecking(player))
return;
Message.send("CHECK_ABORT", player);
currentCheckers.get(player.getUniqueId()).abort();
}
@Register(value = "next", description = "CHECK_HELP_NEXT")
public void next(ProxiedPlayer player) {
next(player, new String[0]);
}
@Register(value = "accept")
public void accept(ProxiedPlayer player, @OptionalValue("") String rank) {
if (rank.equals("")) {
next(player, new String[0]);
} else {
next(player, new String[]{rank});
}
}
@Register(value = "decline", description = "CHECK_HELP_DECLINE")
public void decline(ProxiedPlayer player, String... message) {
if(notChecking(player))
return;
currentCheckers.get(player.getUniqueId()).decline(String.join(" ", message));
}
public static List<SchematicNode> getSchemsToCheck(){
List<SchematicNode> schematicList = new LinkedList<>();
for (SchematicType type : SchematicType.values()) {
if (type.check())
schematicList.addAll(SchematicNode.getAllSchematicsOfType(type.toDB()));
}
return schematicList;
}
public static String getChecker(SchematicNode schematic) {
if (currentSchems.get(schematic.getId()) == null) return null;
return currentSchems.get(schematic.getId()).checker.getName();
}
private static boolean notChecking(ProxiedPlayer player){
if(!isChecking(player)){
Message.send("CHECK_NOT_CHECKING", player);
return true;
}
return false;
}
private void next(ProxiedPlayer player, String[] args){
if(notChecking(player))
return;
int rank = 0;
if(args.length > 0){
try{
rank = Integer.parseInt(args[0]);
}catch(NumberFormatException e){
Message.send("CHECK_INVALID_RANK", player);
return;
}
}
currentCheckers.get(player.getUniqueId()).next(rank);
}
private static class CheckSession{
private final ProxiedPlayer checker;
private final SchematicNode schematic;
private final Timestamp startTime;
private final ListIterator<String> checkList;
private CheckSession(ProxiedPlayer checker, SchematicNode schematic){
this.checker = checker;
this.schematic = schematic;
this.startTime = Timestamp.from(Instant.now());
this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator();
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
ArenaMode mode = ArenaMode.getBySchemType(fightTypes.get(schematic.getSchemtype()));
if(!new ServerStarter().test(mode, mode.getRandomMap(), checker).check(schematic.getId()).start()) {
remove();
return;
}
currentCheckers.put(checker.getUniqueId(), this);
currentSchems.put(schematic.getId(), this);
for(CheckedSchematic previous : CheckedSchematic.previousChecks(schematic))
Message.sendPrefixless("CHECK_SCHEMATIC_PREVIOUS", checker, previous.getEndTime(), SteamwarUser.get(previous.getValidator()).getUserName(), previous.getDeclineReason());
next(0);
});
}
private void next(int rank) {
if(!checkList.hasNext()){
accept(rank);
return;
}
checker.sendMessage(TextComponent.fromLegacyText(checkList.next()));
TextComponent next = new TextComponent();
next.setColor(ChatColor.GREEN);
if(checkList.hasNext()){
next.setText(Message.parse("CHECK_NEXT", checker));
next.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/check next"));
}else if(ranks.containsKey(schematic.getSchemtype())){
List<String> r = ranks.get(schematic.getSchemtype());
for(int i = 0; i < r.size(); i++){
Message.sendPrefixless("CHECK_RANK", checker,
Message.parse("CHECK_RANK_HOVER", checker),
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/check accept " + (i+1)),
i+1, r.get(i));
Message.sendPrefixless("SPACER", checker);
}
}else{
next.setText(Message.parse("CHECK_ACCEPT", checker));
next.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/check accept"));
}
TextComponent decline = new TextComponent(" " + Message.parse("CHECK_DECLINE", checker));
decline.setColor(ChatColor.RED);
decline.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/check decline "));
next.addExtra(decline);
checker.sendMessage(next);
}
private void accept(int rank){
if(createLog("freigegeben")) {
if(ranks.containsKey(schematic.getSchemtype())){
if(rank <= 0 || ranks.get(schematic.getSchemtype()).size() < rank){
Message.send("CHECK_INVALID_RANK", checker);
return;
}
schematic.setRank(rank);
}
schematic.setType(fightTypes.get(schematic.getSchemtype()).toDB());
SteamwarUser user = SteamwarUser.get(schematic.getOwner());
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(user.getUUID());
if(player != null) {
Message.send("CHECK_ACCEPTED", player, schematic.getSchemtype().name(), schematic.getName());
} else {
DiscordSchemAlert.sendAccept(schematic, user);
}
Message.team("CHECK_ACCEPTED_TEAM", schematic.getName(), user.getUserName());
}
stop();
}
private void decline(String reason){
if(createLog(reason)) {
SteamwarUser user = SteamwarUser.get(schematic.getOwner());
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(user.getUUID());
if(player != null) {
Message.send("CHECK_DECLINED", player, schematic.getSchemtype().name(), schematic.getName(), reason);
} else {
DiscordSchemAlert.sendDecline(schematic, user, reason);
}
Message.team("CHECK_DECLINED_TEAM", schematic.getName(), user.getUserName(), reason);
schematic.setType(SchematicType.Normal.toDB());
}
stop();
}
private void abort(){
createLog("Prüfvorgang abgebrochen");
stop();
}
private void stop(){
currentCheckers.remove(checker.getUniqueId());
currentSchems.remove(schematic.getId());
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
Bauserver subserver = Bauserver.get(checker.getUniqueId());
if(subserver != null)
subserver.stop();
});
}
private void remove() {
currentCheckers.remove(checker.getUniqueId());
currentSchems.remove(schematic.getId());
}
private boolean createLog(String reason) {
if(SchematicNode.getSchematicNode(schematic.getId()) == null) // Schematic was deleted
return false;
CheckedSchematic.create(schematic, SteamwarUser.get(checker.getUniqueId()).getId(), startTime, Timestamp.from(Instant.now()), reason);
return true;
}
}
}

Datei anzeigen

@ -1,138 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.*;
import de.steamwar.messages.ChatSender;
import de.steamwar.sql.*;
import de.steamwar.command.SWCommand;
import de.steamwar.command.SWCommandUtils;
import de.steamwar.command.TypeMapper;
import de.steamwar.command.TypeValidator;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class EventCommand extends SWCommand {
public EventCommand() {
super("event");
}
@Validator("noEvent")
public TypeValidator<ProxiedPlayer> noEventValidator() {
return (sender, value, messageSender) -> Event.get() == null;
}
@Register
public void noCurrentEvent(@Validator("noEvent") ProxiedPlayer player){
Message.send("EVENT_NO_CURRENT", player);
List<Event> coming = Event.getComing();
Instant now = Instant.now();
if(!coming.isEmpty()){
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(Message.parse("EVENT_DATE_FORMAT", player));
Message.send("EVENT_COMING", player);
for(Event e : coming){
Message.send("EVENT_COMING_EVENT", player, e.getStart().toLocalDateTime().format(dateFormat), e.getEnd().toLocalDateTime().format(dateFormat), e.getEventName());
Set<Team> teams = TeamTeilnahme.getTeams(e.getEventID());
if(now.isBefore(e.getDeadline().toInstant())) {
Message.send("EVENT_COMING_DEADLINE", player, e.getDeadline());
}
SchematicType schemType = e.getSchematicType();
if (schemType != null) {
if (schemType.getDeadline() != null && now.isBefore(schemType.getDeadline().toInstant())) {
Message.send("EVENT_COMING_SCHEM_DEADLINE", player, e.getDeadline());
}
}
if(!teams.isEmpty()){
StringBuilder tline = new StringBuilder();
for(Team t : teams){
tline.append(' ').append(Message.parse("EVENT_COMING_TEAM", player, t.getTeamColor(), t.getTeamKuerzel()));
}
Message.send("EVENT_COMING_TEAMS", player, tline.toString());
}
}
}
}
@Register
public void eventOverview(@Validator(value = "noEvent", invert = true) ProxiedPlayer player) {
Event currentEvent = Event.get();
Message.send("EVENT_USAGE", player);
List<EventFight> fights = EventFight.getEvent(currentEvent.getEventID());
Message.send("EVENT_CURRENT_EVENT", player, currentEvent.getEventName());
DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern(Message.parse("EVENT_TIME_FORMAT", player));
for(EventFight fight : fights){
Team blue = Team.get(fight.getTeamBlue());
Team red = Team.get(fight.getTeamRed());
StringBuilder fline = new StringBuilder(Message.parse("EVENT_CURRENT_FIGHT", player, fight.getStartTime().toLocalDateTime().format(timeFormat), blue.getTeamColor(), blue.getTeamKuerzel(),
red.getTeamColor(), red.getTeamKuerzel()));
if(fight.hasFinished()){
switch(fight.getErgebnis()){
case 1:
fline.append(Message.parse("EVENT_CURRENT_FIGHT_WIN", player, blue.getTeamColor(), blue.getTeamKuerzel()));
break;
case 2:
fline.append(Message.parse("EVENT_CURRENT_FIGHT_WIN", player, red.getTeamColor(), red.getTeamKuerzel()));
break;
default:
fline.append(Message.parse("EVENT_CURRENT_FIGHT_DRAW", player));
}
}
BungeeCore.send(player, fline.toString());
}
}
@Register
public void eventWithTeam(@Validator(value = "noEvent", invert = true) ProxiedPlayer player, @ErrorMessage("EVENT_NO_TEAM") Team team) {
Subserver eventArena = EventStarter.getEventServer().get(team.getTeamId());
if(eventArena == null || !Subserver.getServerList().contains(eventArena)){
Message.send("EVENT_NO_FIGHT_TEAM", player);
return;
}
ChatSender sender = ChatSender.of(player);
if (!PunishmentCommand.isPunishedWithMessage(sender, Punishment.PunishmentType.NoFightServer)) {
SubserverSystem.sendPlayer(eventArena, player);
}
}
@ClassMapper(Team.class)
@Cached(cacheDuration = 10, global = true)
public TypeMapper<Team> teamMapper() {
return SWCommandUtils.createMapper(Team::get, s -> EventStarter.getEventServer()
.keySet()
.stream()
.map(Team::get)
.map(t -> Arrays.asList(t.getTeamKuerzel(), t.getTeamColor()))
.flatMap(Collection::stream)
.collect(Collectors.toList()));
}
}

Datei anzeigen

@ -1,175 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.inventory.SWInventory;
import de.steamwar.bungeecore.inventory.SWItem;
import de.steamwar.command.SWCommand;
import de.steamwar.messages.ChatSender;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
import net.md_5.bungee.api.connection.ProxiedPlayer;
/**
* Jeder Fightcommand (auch bau testarena und challenge) haben folgende Optionskette:
*
* [ArenaMode] [Map]
*
* Sollte der ArenaMode fehlen, kann er mit getMode() bestimmt werden.
* Sollte die Map fehlen, kann sie mit getMap() bestimmt werden.
*/
public class FightCommand extends SWCommand {
public FightCommand() {
super("fight", "", "f");
}
private static ArenaMode getMode(ChatSender sender, String arg){
ArenaMode mode = ArenaMode.getByChat(arg);
if(mode != null)
return mode;
sender.system("FIGHT_UNKNOWN_GAMEMODE", arg);
return null;
}
private static String getMap(ChatSender sender, ArenaMode mode, String arg){
String realMap = mode.hasMap(arg.toLowerCase());
if(realMap != null)
return realMap;
if(arg.equalsIgnoreCase("Random"))
return mode.getRandomMap();
sender.system("FIGHT_UNKNOWN_ARENA");
return null;
}
private static void getModes(ChatSender sender, String precommand, boolean historic){
TextComponent start = new TextComponent();
TextComponent current = start;
for(ArenaMode mode : ArenaMode.getAllModes()){
if(mode.withoutChatName() || mode.isHistoric() != historic)
continue;
String command = precommand + mode.getChatName();
current.setBold(true);
current.setColor(ChatColor.GRAY);
current.setText(mode.getChatName() + " ");
current.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§e" + command)));
current.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command));
if(current != start)
start.addExtra(current);
current = new TextComponent();
}
sender.sendMessage(ChatMessageType.SYSTEM, start);
}
private static boolean alreadyInArena(ProxiedPlayer player){
Subserver subserver = Subserver.getSubserver(player);
if(subserver != null && subserver.getType() == Servertype.ARENA){
Message.send("FIGHT_IN_ARENA", player);
return true;
}
return false;
}
static void createArena(ProxiedPlayer player, String precommand, boolean allowMerging, ArenaMode arenaMode, String map, boolean historic, FightCallback callback) {
ChatSender sender = ChatSender.of(player);
if(alreadyInArena(player))
return;
if (arenaMode == null) {
getModes(sender, precommand, historic);
return;
}
if (map == null)
map = arenaMode.getRandomMap();
if (!allowMerging) {
callback.run(player, arenaMode, map);
} else {
suggestMerging(player, arenaMode, map, callback);
}
}
public static void suggestMerging(ProxiedPlayer player, ArenaMode mode, String map, FightCallback declineMerge) {
Arenaserver mergable = null;
synchronized (Subserver.getServerList()) {
for (Subserver subserver : Subserver.getServerList()) {
if(subserver instanceof Arenaserver) {
Arenaserver arenaserver = (Arenaserver) subserver;
if(mode.getInternalName().equals(arenaserver.getMode()) && arenaserver.isAllowMerge() && arenaserver.getServer().getPlayers().size() == 1) {
mergable = arenaserver;
break;
}
}
}
}
if(mergable == null) {
declineMerge.run(player, mode, map);
return;
}
SWInventory inventory = new SWInventory(player, 9, Message.parse("FIGHT_MERGE_TITLE", player));
inventory.addItem(0, new SWItem(Message.parse("FIGHT_MERGE_DECLINE", player), 1), click -> {
inventory.close();
declineMerge.run(player, mode, map);
});
Arenaserver finalMergable = mergable;
SWItem item = new SWItem(Message.parse("FIGHT_MERGE_INFO", player, mode.getDisplayName(), finalMergable.getMap()), 11);
item.addLore(Message.parse("FIGHT_MERGE_INFO_LORE_1", player, finalMergable.getServer().getPlayers().toArray(new ProxiedPlayer[1])[0].getName()));
inventory.addItem(4, item, click -> {});
inventory.addItem(8, new SWItem(Message.parse("FIGHT_MERGE_ACCEPT", player), 10), click -> {
if(Subserver.getServerList().contains(finalMergable)) {
finalMergable.sendPlayer(player);
} else {
Message.send("FIGHT_MERGE_OFFLINE", player);
declineMerge.run(player, mode, map);
}
});
inventory.open();
}
@Register
public void fight(@Validator("arenaPlayer") ProxiedPlayer player, @Mapper("nonHistoricArenaMode") @OptionalValue("") @AllowNull ArenaMode arenaMode, @Mapper("arenaMap") @OptionalValue("") @AllowNull String map) {
createArena(player, "/fight ", true, arenaMode, map, false,
(p, mode, m) -> new ServerStarter().arena(mode, m).blueLeader(p).callback(
arena -> Message.broadcast("FIGHT_BROADCAST", "FIGHT_BROADCAST_HOVER", new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/arena " + arena.getServer().getName()), mode.getDisplayName(), p.getName())
).start()
);
}
/**
* Is called when arena parameters are clear.
*/
interface FightCallback {
void run(ProxiedPlayer player, ArenaMode mode, String map);
}
}

Datei anzeigen

@ -1,68 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Subserver;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class JoinmeCommand extends SWCommand {
public JoinmeCommand() {
super("joinme");
}
@Register(description = "JOINME_USAGE")
public void genericCommand(ProxiedPlayer player) {
if (!SteamwarUser.get(player.getUniqueId()).hasPerm(UserPerm.TEAM)) {
Message.send("JOINME_USAGE", player);
return;
}
Message.broadcast("JOINME_BROADCAST", "JOINME_BROADCAST_HOVER",
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/join " + player.getName()), player.getName(), player.getServer().getInfo().getName());
}
@Register
public void genericCommand(ProxiedPlayer player, @Validator ProxiedPlayer target) {
if (target.equals(player)){
Message.send("JOINME_PLAYER_SELF", player);
return;
}
Subserver subserver = Subserver.getSubserver(target);
TpCommand.teleport(player, subserver != null ? subserver.getServer() : target.getServer().getInfo());
}
@ClassValidator(ProxiedPlayer.class)
public TypeValidator<ProxiedPlayer> playerMapper() {
return (sender, value, messageSender) -> {
if (value == null || !value.isConnected()) {
messageSender.send("JOINME_PLAYER_OFFLINE", sender);
return false;
}
return true;
};
}
}

Datei anzeigen

@ -1,75 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Servertype;
import de.steamwar.bungeecore.Subserver;
import de.steamwar.command.SWCommand;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class ListCommand extends SWCommand {
public ListCommand() {
super("list", "");
}
public static synchronized TreeMap<String, List<ProxiedPlayer>> getCustomTablist(){
TreeMap<String, List<ProxiedPlayer>> playerMap = new TreeMap<>();
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
Server pserver = player.getServer();
if (pserver == null) //Happens temporarily
continue;
ServerInfo server = pserver.getInfo();
String serverName = server.getName();
Subserver subserver = Subserver.getSubserver(server);
if (subserver != null && subserver.getType() == Servertype.BAUSERVER) {
playerMap.computeIfAbsent("Bau", s -> new ArrayList<>()).add(player);
} else {
playerMap.computeIfAbsent(serverName, s -> new ArrayList<>()).add(player);
}
}
playerMap.forEach((server, players) -> players.sort((proxiedPlayer, t1) -> proxiedPlayer.getName().compareToIgnoreCase(t1.getName())));
return playerMap;
}
@Register
public void genericCommand(CommandSender commandSender) {
TreeMap<String, List<ProxiedPlayer>> playerMap = getCustomTablist();
for (String server : playerMap.navigableKeySet()) {
String serverName = server;
if (server.equals("Bau")) {
serverName = Message.parse("TABLIST_BAU", commandSender);
}
Message.send("LIST_COMMAND", commandSender, serverName, playerMap.get(server).stream().map(CommandSender::getName).collect(Collectors.joining(", ")));
}
}
}

Datei anzeigen

@ -1,148 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2023 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.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.inventory.SWInventory;
import de.steamwar.bungeecore.inventory.SWItem;
import de.steamwar.bungeecore.inventory.SWListInv;
import de.steamwar.bungeecore.inventory.SWStreamInv;
import de.steamwar.bungeecore.listeners.ConnectionListener;
import de.steamwar.command.SWCommand;
import de.steamwar.sql.Mod;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class ModCommand extends SWCommand {
public ModCommand() {
super("mod", ConnectionListener.MOD_PERMISSION, "mods");
}
public static final Map<ProxiedPlayer, Mod.ModType> playerFilterType = new HashMap<>();
@Register
public void genericCommand(ProxiedPlayer p) {
playerFilterType.putIfAbsent(p,Mod.ModType.UNKLASSIFIED);
openGui(p);
}
private void openGui(ProxiedPlayer p) {
SWStreamInv<Mod> swStreamInv = new SWStreamInv<>(p,Message.parse("MOD_COMMAND_GUI_TITLE",p), (click, element) -> {
openClassificationGui(p,element);
},page -> {
Mod.ModType filtertype = playerFilterType.get(p);
return Mod.getAllModsFiltered(page,45, filtertype).stream().map(mod -> new SWListInv.SWListEntry<>(getModItem(mod),mod)).collect(Collectors.toList());
});
swStreamInv.addItem(52,new SWItem("NAME_TAG","Filter"), click -> {
swStreamInv.close();
openFilterGui(p);
});
swStreamInv.open();
}
public void updateAndCloseGui(Mod.ModType modType, Mod mod, SWInventory toClose, ProxiedPlayer p) {
mod.setModType(modType);
toClose.close();
openGui(p);
}
private void openFilterGui(ProxiedPlayer p) {
SWInventory inv = new SWInventory(p, 9, "Filter");
inv.addItem(1, new SWItem(Message.parse("MOD_UNCLASSIFIED",p),8), click -> playerFilterType.replace(p, Mod.ModType.UNKLASSIFIED));
inv.addItem(2, new SWItem(Message.parse("MOD_ALLOWED",p),2), click -> playerFilterType.replace(p, Mod.ModType.GREEN));
inv.addItem(3, new SWItem(Message.parse("MOD_FORBIDDEN",p), 11), click -> playerFilterType.replace(p, Mod.ModType.YELLOW));
inv.addItem(4, new SWItem(Message.parse("MOD_AUTOBAN",p),1), click -> playerFilterType.replace(p, Mod.ModType.RED));
inv.addItem(5, new SWItem(Message.parse("MOD_YT",p),13), click -> playerFilterType.replace(p, Mod.ModType.YOUTUBER_ONLY));
inv.addItem(8, new SWItem("ARROW", Message.parse("MOD_ITEM_BACK",p)), click -> {
inv.close();
openGui(p);
});
inv.open();
}
private void openClassificationGui(ProxiedPlayer p,Mod element) {
SWInventory swInventory = new SWInventory(p,9,Message.parse("MOD_COMMAND_CLASSICIATION_GUI",p));
swInventory.addItem(2, new SWItem(Message.parse("MOD_UNCLASSIFIED",p),8), (click1 -> updateAndCloseGui(Mod.ModType.UNKLASSIFIED,element,swInventory,p)));
swInventory.addItem(3, new SWItem(Message.parse("MOD_ALLOWED",p), 2), (click1 -> updateAndCloseGui(Mod.ModType.GREEN,element,swInventory,p)));
swInventory.addItem(4, new SWItem(Message.parse("MOD_FORBIDDEN",p), 11), (click1 -> updateAndCloseGui(Mod.ModType.YELLOW,element,swInventory,p)));
swInventory.addItem(5, new SWItem(Message.parse("MOD_AUTOBAN",p),1), (click1 -> updateAndCloseGui(Mod.ModType.RED,element,swInventory,p)));
swInventory.addItem(6, new SWItem(Message.parse("MOD_YT",p), 13), (click1 -> updateAndCloseGui(Mod.ModType.YOUTUBER_ONLY,element,swInventory,p)));
swInventory.addItem(8,new SWItem("ARROW",Message.parse("MOD_ITEM_BACK",p)), click1 -> {
swInventory.close();
openGui(p);
});
swInventory.open();
}
private SWItem getModItem(Mod modEntry) {
SWItem item = new SWItem("NAME_TAG", modEntry.getModName());
item.addLore(modEntry.getPlatform().name());
return item;
}
@Register(value = {"set"},description = "MOD_COMMAND_SET_USAGE")
public void set(ProxiedPlayer p,String modName,Mod.Platform platform,Mod.ModType newModType) {
Mod mod = Mod.get(modName, platform);
if(mod == null) {
Message.send("MOD_COMMAND_NOT_FOUND_IN_DATABASE",p,modName, platform.name());
return;
}
mod.setModType(newModType);
Message.send("MOD_CHANGED_TYPE",p,modName,platform.name(),newModType.name());
}
@Register(value = {"get"},description = "MOD_COMMAND_GET_USAGE")
public void get(ProxiedPlayer p,String modName,Mod.Platform platform) {
Mod mod = Mod.get(modName, platform);
if(mod == null) {
Message.send("MOD_COMMAND_NOT_FOUND_IN_DATABASE", p, modName, platform.name());
return;
}
Message.send("MOD_COMMAND_INFO", p, modName, platform.name(), mod.getModType().name());
}
@Register(value = {"next"})
public void next(ProxiedPlayer p) {
Mod mod = Mod.findFirstMod();
if(mod == null) {
Message.send("MOD_NO_MORE_UNCLASSIFIED_MODS",p);
return;
}
Message.send("MOD_FOUND_NEXT_MOD",p,"MOD_OPEN_GUI",new ClickEvent(ClickEvent.Action.RUN_COMMAND,""),mod.getModName(),mod.getPlatform().name());
}
}

Datei anzeigen

@ -1,42 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.command.SWCommand;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class RegelnCommand extends SWCommand {
public RegelnCommand() {
super("regeln", null, "rules");
}
@Register
public void genericCommand(ProxiedPlayer player) {
Message.send("REGELN_RULES", player);
Message.sendPrefixless("REGELN_AS", player, Message.parse("REGELN_AS_HOVER", player), new ClickEvent(ClickEvent.Action.OPEN_URL, Message.parse("REGELN_AS_URL", player)));
Message.sendPrefixless("REGELN_MWG", player, Message.parse("REGELN_MWG_HOVER", player), new ClickEvent(ClickEvent.Action.OPEN_URL, Message.parse("REGELN_MWG_URL", player)));
Message.sendPrefixless("REGELN_WG", player, Message.parse("REGELN_WG_HOVER", player), new ClickEvent(ClickEvent.Action.OPEN_URL, Message.parse("REGELN_WG_URL", player)));
Message.sendPrefixless("REGELN_WS", player, Message.parse("REGELN_WS_HOVER", player), new ClickEvent(ClickEvent.Action.OPEN_URL, Message.parse("REGELN_WS_URL", player)));
Message.sendPrefixless("REGELN_QG", player, Message.parse("REGELN_QG_HOVER", player), new ClickEvent(ClickEvent.Action.OPEN_URL, Message.parse("REGELN_QG_URL", player)));
Message.sendPrefixless("REGELN_CONDUCT", player, Message.parse("REGELN_CONDUCT_HOVER", player), new ClickEvent(ClickEvent.Action.OPEN_URL, Message.parse("REGELN_CONDUCT_URL", player)));
}
}

Datei anzeigen

@ -1,725 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Storage;
import de.steamwar.bungeecore.inventory.SWItem;
import de.steamwar.bungeecore.inventory.SWListInv;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.command.TypeValidator;
import de.steamwar.messages.ChatSender;
import de.steamwar.sql.*;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ServerConnectRequest;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerConnectEvent;
import java.net.*;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static de.steamwar.bungeecore.Storage.teamInvitations;
public class TeamCommand extends SWCommand {
private static final List<SWListInv.SWListEntry<String>> COLOR_CODES = new ArrayList<>();
static {
addColor("4", 1);
addColor("c", 15);
addColor("6", 14);
addColor("e", 11);
addColor("2", 2);
addColor("a", 10);
addColor("b", 12);
addColor("3", 6);
addColor("1", 4);
addColor("9", 6);
addColor("d", 9);
addColor("5", 5);
addColor("f", 15);
addColor("7", 7);
addColor("8", 8);
addColor("0", 16);
}
private static void addColor(String color, int colorCode) {
COLOR_CODES.add(new SWListInv.SWListEntry(new SWItem("§" + color, colorCode), color));
}
public TeamCommand() {
super("team");
}
@Register(noTabComplete = true)
public void help(CommandSender sender, String... args){
Message.send("TEAM_HELP_HEADER", sender);
Message.send("TEAM_HELP_LIST", sender);
Message.send("TEAM_HELP_INFO", sender);
if(!(sender instanceof ProxiedPlayer))
return;
Message.send("TEAM_HELP_TP", sender);
ProxiedPlayer player = (ProxiedPlayer) sender;
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
if(user.getTeam() == 0) {
Message.send("TEAM_HELP_CREATE", sender);
Message.send("TEAM_HELP_JOIN", sender);
}else{
Message.send("TEAM_HELP_CHAT", sender);
Message.send("TEAM_HELP_EVENT", sender);
Message.send("TEAM_HELP_LEAVE", sender);
if(user.isLeader()){
Message.send("TEAM_HELP_INVITE", sender);
Message.send("TEAM_HELP_REMOVE", sender);
Message.send("TEAM_HELP_KUERZEL", sender);
Message.send("TEAM_HELP_NAME", sender);
Message.send("TEAM_HELP_COLOR", sender);
Message.send("TEAM_HELP_LEADER", sender);
Message.send("TEAM_HELP_STEP_BACK", sender);
Message.send("TEAM_HELP_SERVER", sender);
}
}
}
@Register(value = "create", description = "TEAM_CREATE_USAGE")
public void create(@Validator("isNotInTeam") ProxiedPlayer player, @Length(min = 2, max = 4) @ErrorMessage("TEAM_KUERZEL_LENGTH") String kuerzel, @Length(min = 4, max = 15) @ErrorMessage("TEAM_NAME_LENGTH") String name){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if(checkTeamKuerzel(player, team, kuerzel))
return;
if(checkTeamName(player, team, name))
return;
Team.create(kuerzel, name);
user.setTeam(Team.get(kuerzel).getTeamId());
user.setLeader(true);
Message.send("TEAM_CREATE_CREATED", player, name);
}
@Register("join")
public void join(@Validator("isNotInTeam") ProxiedPlayer player, String... args){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
if(notDuringEvent(player))
return;
if(!teamInvitations.containsKey(user.getId())){
Message.send("TEAM_JOIN_NO_INVITE", player);
return;
}
List<Integer> invs = teamInvitations.get(user.getId());
Integer t = null;
if(invs.size() == 1){
t = invs.get(0);
}else{
if(args.length != 1){
Message.send("TEAM_JOIN_USAGE", player);
StringBuilder sb = new StringBuilder();
for(int inv : invs){
Team team = Team.get(inv);
sb.append(team.getTeamName()).append(" ");
}
Message.send("TEAM_JOIN_INVITED", player, sb.toString());
return;
}
for(int inv : invs){
Team team = Team.get(inv);
if(team.getTeamKuerzel().equalsIgnoreCase(args[0]) || team.getTeamName().equalsIgnoreCase(args[0])){
t = inv;
break;
}
}
if(t == null){
Message.send("TEAM_JOIN_NOT_BY_TEAM", player);
return;
}
}
user.setTeam(t);
teamInvitations.remove(user.getId());
Message.send("TEAM_JOIN_JOINED", player, Team.get(t).getTeamName());
}
@Register("stepback")
public void stepBack(@Validator("isLeader") ProxiedPlayer player) {
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if(noRemainingLeaders(team, user)){
Message.send("TEAM_OTHER_LEADER_REQUIRED", player);
return;
}
user.setLeader(false);
Message.send("TEAM_STEP_BACK", player);
}
@Register("leave")
public void leave(@Validator("isInTeam") ProxiedPlayer player){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
int teamSize = team.size();
if(teamSize > 1 && user.isLeader() && noRemainingLeaders(team, user)) {
Message.send("TEAM_OTHER_LEADER_REQUIRED", player);
return;
}
user.setTeam(0);
if(teamSize == 1){
team.disband(user);
}
Message.send("TEAM_LEAVE_LEFT", player);
}
private boolean noRemainingLeaders(Team team, SteamwarUser except) {
return SteamwarUser.getTeam(team.getTeamId()).stream().filter(member -> except.getId() != member.getId()).noneMatch(SteamwarUser::isLeader);
}
@Register(value = "invite", description = "TEAM_INVITE_USAGE")
public void invite(@Validator("isLeader") ProxiedPlayer player, @AllowNull SteamwarUser target){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if(notDuringEvent(player))
return;
if(target == null){
Message.send("TEAM_INVITE_NO_PLAYER", player);
return;
}else if(target.getTeam() != 0){
Message.send("TEAM_INVITE_IN_TEAM", player);
return;
}
if(!teamInvitations.containsKey(target.getId()))
teamInvitations.put(target.getId(), new LinkedList<>());
if(teamInvitations.get(target.getId()).contains(team.getTeamId())){
Message.send("TEAM_INVITE_ALREADY_INVITED", player);
return;
}
teamInvitations.get(target.getId()).add(team.getTeamId());
Message.send("TEAM_INVITE_INVITED", player, target.getUserName());
ProxiedPlayer p = ProxyServer.getInstance().getPlayer(target.getUUID());
if(p != null)
Message.send("TEAM_INVITE_INVITED_TARGET", p, team.getTeamColor(), team.getTeamName());
}
@Register(value = "remove", description = "TEAM_REMOVE_USAGE")
public void remove(@Validator("isLeader") ProxiedPlayer player, @AllowNull @Mapper("memberList") SteamwarUser target){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if(target == null){
Message.send("TEAM_REMOVE_NOT_PLAYER", player);
return;
}
if (target.isLeader()) {
Message.send("TEAM_REMOVE_NOT_LEADER", player);
return;
}
if(teamInvitations.containsKey(target.getId())){
if(teamInvitations.get(target.getId()).remove((Integer) team.getTeamId())){
Message.send("TEAM_REMOVE_INVITE", player);
if(teamInvitations.get(target.getId()).isEmpty())
teamInvitations.remove(target.getId());
}else{
Message.send("TEAM_REMOVE_NO_INVITE", player);
}
return;
}
if(target.getTeam() != user.getTeam()){
Message.send("TEAM_REMOVE_NOT_IN_TEAM", player);
return;
}
target.setTeam(0);
Message.send("TEAM_REMOVE_REMOVED", player);
ProxiedPlayer p = ProxyServer.getInstance().getPlayer(target.getUUID());
if(p != null)
Message.send("TEAM_REMOVE_REMOVED_TARGET", player);
}
@Mapper(value = "memberList", local = true)
public TypeMapper<SteamwarUser> memberList() {
return new TypeMapper<SteamwarUser>() {
@Override
public SteamwarUser map(CommandSender commandSender, String[] previousArguments, String s) {
return SteamwarUser.get(s);
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
if (!(sender instanceof ProxiedPlayer)) return Collections.emptyList();
ProxiedPlayer player = (ProxiedPlayer) sender;
Team team = Team.get(SteamwarUser.get(player.getUniqueId()).getTeam());
return team.getMembers().stream()
.map(SteamwarUser::get)
.map(SteamwarUser::getUserName)
.collect(Collectors.toList());
}
};
}
@Register(value = "changekurzel", description = "TEAM_KUERZEL_USAGE")
public void changekuerzel(@Validator("isLeader") ProxiedPlayer player, @Length(min = 2, max = 4) @ErrorMessage("TEAM_KUERZEL_LENGTH") String kuerzel){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if(notDuringEvent(player))
return;
if(checkTeamKuerzel(player, team, kuerzel))
return;
team.setTeamKuerzel(kuerzel);
Message.send("TEAM_KUERZEL_CHANGED", player);
}
@Register(value = "changename", description = "TEAM_NAME_USAGE")
public void changename(@Validator("isLeader") ProxiedPlayer player, @Length(min = 4, max = 15) @ErrorMessage("TEAM_NAME_LENGTH") String name){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if(notDuringEvent(player))
return;
if(checkTeamName(player, team, name))
return;
team.setTeamName(name);
Message.send("TEAM_NAME_CHANGED", player);
}
@Register(value = "promote", description = "TEAM_LEADER_USAGE")
public void promote(@Validator("isLeader") ProxiedPlayer player, @AllowNull @Mapper("memberList") SteamwarUser target){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
if(notDuringEvent(player))
return;
if(target == null){
Message.send("TEAM_LEADER_NOT_USER", player);
return;
}
if(target.getTeam() != user.getTeam()){
Message.send("TEAM_LEADER_NOT_MEMBER", player);
return;
}
target.setLeader(true);
Message.send("TEAM_LEADER_PROMOTED", player, target.getUserName());
}
private String playerName(SteamwarUser user){
return ProxyServer.getInstance().getPlayer(user.getUUID()) != null ? "§a" + user.getUserName() : "§e" + user.getUserName();
}
@Register("info")
public void info(@Validator("isInTeam") ProxiedPlayer player){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
info(player, team);
}
@Register(value = "info", description = "TEAM_INFO_USAGE")
public void info(ProxiedPlayer player, @ErrorMessage("UNKNOWN_TEAM") Team team){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Message.sendPrefixless("TEAM_INFO_TEAM", player, team.getTeamName(), team.getTeamColor(), team.getTeamKuerzel());
List<SteamwarUser> users = team.getMembers().stream().map(SteamwarUser::get).collect(Collectors.toList());
Message.sendPrefixless("TEAM_INFO_LEADER", player, users.stream().filter(SteamwarUser::isLeader).count(), getMemberList(users, true));
String members = getMemberList(users, false);
if(members.length() > 0) {
Message.sendPrefixless("TEAM_INFO_MEMBER", player, users.stream().filter(u -> !u.isLeader()).count(), members);
}
Set<Event> events = TeamTeilnahme.getEvents(team.getTeamId());
if(!events.isEmpty()){
Message.sendPrefixless("TEAM_INFO_EVENTS", player, events.stream().map(Event::getEventName).collect(Collectors.joining(", ")));
}
}
private String getMemberList(List<SteamwarUser> users, boolean leaders) {
StringBuilder sb = new StringBuilder();
for(SteamwarUser user : users) {
if(user.isLeader() == leaders) {
sb.append(playerName(user)).append(" ");
}
}
return sb.toString();
}
@Register("list")
public void list(ProxiedPlayer player, @Min(intValue = 1) @OptionalValue("1") @ErrorMessage("TEAM_LIST_NOT_PAGE") int page){
final int TEAMS_PER_PAGE = 10;
List<Team> all = Team.getAll();
final int lastPage = ((all.size() - 1) / 10) + 1;
if(page < 1 || page > lastPage){
Message.send("TEAM_LIST_UNKNOWN_PAGE", player);
return;
}
Message.sendPrefixless("TEAM_LIST_HEADER", player, page, lastPage);
for(int i = (page-1) * TEAMS_PER_PAGE; i < (page-1) * TEAMS_PER_PAGE + TEAMS_PER_PAGE && i < all.size(); i++){
Team tm = all.get(i);
Message.sendPrefixless("TEAM_LIST_TEAM", player, Message.parse("TEAM_LIST_TEAM_HOVER", player),
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/team info " + tm.getTeamKuerzel()), tm.getTeamColor(), tm.getTeamKuerzel(), tm.getTeamName());
}
TextComponent beforePage = new TextComponent("««");
if(page > 1){
beforePage.setColor(ChatColor.YELLOW);
beforePage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(Message.parse("TEAM_LIST_PREV", player)).create()));
beforePage.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/team list " + (page - 1)));
}else
beforePage.setColor(ChatColor.DARK_GRAY);
TextComponent nextPage = new TextComponent(" " + Message.parse("TEAM_LIST_PAGE", player) +" »»");
if(page < lastPage){
nextPage.setColor(ChatColor.YELLOW);
nextPage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(Message.parse("TEAM_LIST_NEXT", player)).create()));
nextPage.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/team list " + (page + 1)));
}else
nextPage.setColor(ChatColor.DARK_GRAY);
beforePage.addExtra(nextPage);
player.sendMessage(beforePage);
}
@Register("event")
public void event(@Validator("isInTeam") ProxiedPlayer player) {
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
Message.send("TEAM_EVENT_USAGE", player);
Set<Event> events = TeamTeilnahme.getEvents(team.getTeamId());
if(!events.isEmpty()){
Message.send("TEAM_EVENT_HEADER", player);
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(Message.parse("EVENT_DATE_FORMAT", player));
for(Event e : events)
Message.sendPrefixless("TEAM_EVENT_EVENT", player, e.getStart().toLocalDateTime().format(dateFormat), e.getEventName());
}
}
@Register("event")
public void event(@Validator("isLeader") ProxiedPlayer player, Event event){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if(notDuringEvent(player))
return;
if(Instant.now().isAfter(event.getDeadline().toInstant())){
Message.send("TEAM_EVENT_OVER", player);
return;
}
if(TeamTeilnahme.nimmtTeil(team.getTeamId(), event.getEventID())){
TeamTeilnahme.notTeilnehmen(team.getTeamId(), event.getEventID());
Message.send("TEAM_EVENT_LEFT", player);
}else{
TeamTeilnahme.teilnehmen(team.getTeamId(), event.getEventID());
Message.send("TEAM_EVENT_JOINED", player, event.getEventName());
Message.sendPrefixless("TEAM_EVENT_HOW_TO_LEAVE", player);
}
}
@Register("tp")
public void tp(@Validator("isInTeam") ProxiedPlayer player) {
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
tp(player, team);
}
@Register("tp")
public void tp(ProxiedPlayer player, @ErrorMessage("TEAM_TP_NO_TEAM") @Mapper("teamWithTeamServer") Team targetTeam) {
if (targetTeam.getAddress() == null || targetTeam.getAddress().isEmpty()) {
Message.send("TEAM_NO_ADDRESS", player);
return;
}
InetSocketAddress address = new InetSocketAddress(targetTeam.getAddress(), targetTeam.getPort());
ServerInfo serverInfo = Storage.teamServers.computeIfAbsent(targetTeam.getTeamId(), integer -> {
ServerInfo info = ProxyServer.getInstance().constructServerInfo("Team " + targetTeam.getTeamKuerzel(), address, "SteamWar.de - Teamserver", false);
ProxyServer.getInstance().getServers().put(info.getName(), info);
return info;
});
if (!address.equals(serverInfo.getSocketAddress())) {
serverInfo = Storage.teamServers.remove(targetTeam.getTeamId());
ProxyServer.getInstance().getServers().remove(serverInfo.getName());
tp(player, targetTeam);
return;
}
player.connect(ServerConnectRequest.builder()
.target(serverInfo)
.connectTimeout(BungeeCord.getInstance().getConfig().getServerConnectTimeout())
.retry(false)
.reason(ServerConnectEvent.Reason.PLUGIN)
.callback((success, error) -> {
if (error != null) {
Message.send("TEAM_OFFLINE", player);
}
})
.build());
/*
((UserConnection) player).connect(serverInfo, (success, error) -> {
if (error != null) {
Message.send("TEAM_OFFLINE", player);
}
}, false, ServerConnectEvent.Reason.PLUGIN, BungeeCord.getInstance().getConfig().getServerConnectTimeout(), false);
*/
}
@Register(value = "server", description = "TEAM_SERVER_USAGE")
public void server(@Validator("isLeader") ProxiedPlayer player, String server, @Min(intValue = 1) @Max(intValue = 65535) @ErrorMessage("TEAM_SERVER_PORT_INVALID") int port){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if (PunishmentCommand.isPunishedWithMessage(ChatSender.of(player), Punishment.PunishmentType.NoTeamServer)) {
return;
}
try {
if (isLocalhost(InetAddress.getByName(server))) {
Message.send("TEAM_SERVER_ADDRESS_INVALID", player);
return;
}
} catch (UnknownHostException e) {
Message.send("TEAM_SERVER_ADDRESS_INVALID", player);
return;
}
team.setAddress(server);
team.setPort(port);
Storage.teamServers.remove(team.getTeamId());
Message.send("TEAM_SERVER_SET", player);
}
public static boolean isLocalhost(InetAddress addr) {
// Check if the address is a valid special local or loop back
if (addr.isAnyLocalAddress() || addr.isLoopbackAddress())
return true;
// Check if the address is defined on any interface
try {
return NetworkInterface.getByInetAddress(addr) != null;
} catch (SocketException e) {
return false;
}
}
@Register("color")
public void changeColor(@Validator("isLeader") ProxiedPlayer player) {
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
Team team = Team.get(user.getTeam());
if(notDuringEvent(player))
return;
List<SWListInv.SWListEntry<String>> colors = new ArrayList<>();
COLOR_CODES.forEach(stringSWListEntry -> {
SWItem item = stringSWListEntry.getItem().clone();
item.setName(stringSWListEntry.getItem().getTitle() + Team.get(user.getTeam()).getTeamKuerzel());
colors.add(new SWListInv.SWListEntry<>(item, stringSWListEntry.getObject()));
});
SWListInv<String> inv = new SWListInv<>(player, Message.parse("TEAM_COLOR_TITLE", player), colors, (click, element) -> {});
inv.setCallback((click, element) -> {
inv.close();
team.setTeamColor(element);
});
inv.open();
}
@ClassMapper(Event.class)
public TypeMapper<Event> eventTypeMapper() {
return new TypeMapper<Event>() {
@Override
public Event map(CommandSender commandSender, String[] previousArguments, String s) {
return Event.get(s);
}
@Override
public boolean validate(CommandSender sender, Event value, MessageSender messageSender) {
if (value == null) {
messageSender.send("TEAM_EVENT_NO_EVENT", sender);
return false;
} else {
return true;
}
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
return Event.getComing().stream().map(Event::getEventName).collect(Collectors.toList());
}
};
}
@Validator(value = "isNotInTeam", local = true)
public TypeValidator<ProxiedPlayer> isNotInTeamValidator() {
return (sender, value, messageSender) -> {
if (!(sender instanceof ProxiedPlayer)) return false;
ProxiedPlayer player = (ProxiedPlayer) sender;
SteamwarUser steamwarUser = SteamwarUser.get(player.getUniqueId());
if (steamwarUser.getTeam() != 0) {
messageSender.send("TEAM_IN_TEAM");
return false;
}
return true;
};
}
@Validator(value = "isInTeam", local = true)
public TypeValidator<ProxiedPlayer> isInTeamValidator() {
return (sender, value, messageSender) -> {
if (!(sender instanceof ProxiedPlayer)) return false;
ProxiedPlayer player = (ProxiedPlayer) sender;
SteamwarUser steamwarUser = SteamwarUser.get(player.getUniqueId());
if (steamwarUser.getTeam() == 0) {
messageSender.send("TEAM_NOT_IN_TEAM");
return false;
}
return true;
};
}
@Validator(value = "isLeader", local = true)
public TypeValidator<ProxiedPlayer> isLeaderValidator() {
return (sender, value, messageSender) -> {
if (!(sender instanceof ProxiedPlayer)) return false;
ProxiedPlayer player = (ProxiedPlayer) sender;
SteamwarUser steamwarUser = SteamwarUser.get(player.getUniqueId());
if (steamwarUser.getTeam() == 0) {
messageSender.send("TEAM_NOT_IN_TEAM");
return false;
}
if (!steamwarUser.isLeader()) {
messageSender.send("TEAM_NOT_LEADER");
return false;
}
return true;
};
}
@ClassMapper(Team.class)
@Cached(global = true, cacheDuration = 60)
public TypeMapper<Team> team() {
return new TypeMapper<Team>() {
@Override
public Team map(CommandSender commandSender, String[] previousArguments, String s) {
return Team.get(s);
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
return Team.getAll().stream()
.flatMap(team -> Stream.of(team.getTeamName(), team.getTeamKuerzel()))
.collect(Collectors.toList());
}
};
}
@Mapper(value = "teamWithTeamServer", local = true)
@Cached(global = true, cacheDuration = 60)
public TypeMapper<Team> teamWithTeamServer() {
return new TypeMapper<Team>() {
@Override
public Team map(CommandSender commandSender, String[] previousArguments, String s) {
return Team.get(s);
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
return Team.getAll().stream()
.filter(team -> team.getAddress() != null && !team.getAddress().isEmpty())
.flatMap(team -> Stream.of(team.getTeamName(), team.getTeamKuerzel()))
.collect(Collectors.toList());
}
};
}
private boolean checkTeamName(ProxiedPlayer player, Team team, String arg){
Team t = Team.get(arg);
if(t != null && t.getTeamId() != team.getTeamId()){
Message.send("TEAM_NAME_TAKEN", player);
return true;
}
return false;
}
private boolean checkTeamKuerzel(ProxiedPlayer player, Team team, String arg){
Team t = Team.get(arg);
if(t != null && (team == null || t.getTeamId() != team.getTeamId())){
Message.send("TEAM_KUERZEL_TAKEN", player);
return true;
}
return false;
}
private boolean notDuringEvent(ProxiedPlayer player){
if(Event.get() != null){
Message.send("TEAM_NOT_IN_EVENT", player);
return true;
}
return false;
}
}

Datei anzeigen

@ -1,168 +0,0 @@
/*
* 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.commands;
import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.inventory.SWInventory;
import de.steamwar.bungeecore.inventory.SWItem;
import de.steamwar.bungeecore.inventory.SWListInv;
import de.steamwar.bungeecore.inventory.SWStreamInv;
import de.steamwar.bungeecore.util.Chat19;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Tutorial;
import de.steamwar.sql.UserPerm;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class TutorialCommand extends SWCommand {
public TutorialCommand() {
super("tutorial", null);
}
@Register
public void genericCommand(ProxiedPlayer player) {
openInventory(player, true, false);
}
@Register("rate")
public void rate(ProxiedPlayer player) {
Chat19.chat(player, "/tutorial rate");
}
@Register("rate")
public void rate(ProxiedPlayer player, int id) {
Tutorial tutorial = Tutorial.get(id);
if(tutorial == null) {
Chat19.chat(player, "/tutorial rate"); // Catch players manually entering numbers
return;
}
rate(player, tutorial);
}
@Register(value = "create", description = "TUTORIAL_CREATE_HELP")
public void create(ProxiedPlayer player, String material, String... name) {
create(player, String.join(" ", name), material.toUpperCase());
}
@Register("own")
public void own(ProxiedPlayer player) {
openInventory(player, false, true);
}
@Register("unreleased")
public void unreleased(@Validator("unreleased") ProxiedPlayer player) {
openInventory(player, false, false);
}
@Validator("unreleased")
public TypeValidator<ProxiedPlayer> unreleasedChecker() {
return (sender, value, messageSender) -> (SteamwarUser.get((value).getUniqueId()).hasPerm(UserPerm.TEAM));
}
private void openInventory(ProxiedPlayer player, boolean released, boolean own) {
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
new SWStreamInv<>(
player,
Message.parse("TUTORIAL_TITLE", player),
(click, tutorial) -> {
if(!released && click.isShiftClick() && user.hasPerm(UserPerm.TEAM) && user.getId() != tutorial.getCreator()) {
tutorial.release();
openInventory(player, released, own);
return;
} else if(own && click.isShiftClick() && click.isRightClick()) {
tutorial.delete();
SubserverSystem.deleteFolder(BungeeCore.local, world(tutorial).getPath());
openInventory(player, released, own);
return;
}
new ServerStarter().tutorial(player, tutorial).start();
},
page -> (own ? Tutorial.getOwn(user.getId(), page, 45) : Tutorial.getPage(page, 45, released)).stream().map(tutorial -> new SWListInv.SWListEntry<>(getTutorialItem(player, tutorial, own), tutorial)).collect(Collectors.toList())
).open();
}
private SWItem getTutorialItem(ProxiedPlayer player, Tutorial tutorial, boolean personalHighlights) {
SWItem item = new SWItem(tutorial.getItem(), Message.parse("TUTORIAL_NAME", player, tutorial.getName()));
item.setHideAttributes(true);
List<String> lore = new ArrayList<>();
lore.add(Message.parse("TUTORIAL_BY", player, SteamwarUser.get(tutorial.getCreator()).getUserName()));
lore.add(Message.parse("TUTORIAL_STARS", player, String.format("%.1f", tutorial.getStars())));
if (personalHighlights)
lore.add(Message.parse("TUTORIAL_DELETE", player));
item.setLore(lore);
if (personalHighlights && tutorial.isReleased())
item.setEnchanted(true);
return item;
}
private void rate(ProxiedPlayer player, Tutorial tutorial) {
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
int[] rates = new int[]{1, 2, 3, 4, 5};
new SWListInv<>(player, Message.parse("TUTORIAL_RATE_TITLE", player), Arrays.stream(rates).mapToObj(rate -> new SWListInv.SWListEntry<>(new SWItem("NETHER_STAR", Message.parse("TUTORIAL_RATE", player, rate)), rate)).collect(Collectors.toList()), (click, rate) -> {
tutorial.rate(user.getId(), rate);
SWInventory.close(player);
}).open();
}
private void create(ProxiedPlayer player, String name, String item) {
Subserver subserver = Subserver.getSubserver(player);
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
File tempWorld = new File(ServerStarter.TEMP_WORLD_PATH, ServerStarter.serverToWorldName(ServerStarter.bauServerName(user)));
if(subserver == null || !subserver.hasStarted() || subserver.getType() != Servertype.BAUSERVER || !tempWorld.exists()) {
Message.send("TUTORIAL_CREATE_MISSING", player);
return;
}
subserver.execute("save-all");
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> {
Tutorial tutorial = Tutorial.create(user.getId(), name, item);
File tutorialWorld = world(tutorial);
if (tutorialWorld.exists())
SubserverSystem.deleteFolder(BungeeCore.local, tutorialWorld.getPath());
ServerStarter.copyWorld(BungeeCore.local, tempWorld.getPath(), tutorialWorld.getPath());
Message.send("TUTORIAL_CREATED", player);
}, 1, TimeUnit.SECONDS);
}
private File world(Tutorial tutorial) {
return new File(ServerStarter.TUTORIAL_PATH, String.valueOf(tutorial.getTutorialId()));
}
}

Datei anzeigen

@ -1,158 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.inventory;
import de.steamwar.bungeecore.network.NetworkSender;
import de.steamwar.bungeecore.network.handlers.InventoryCallbackHandler;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.network.packets.server.CloseInventoryPacket;
import de.steamwar.network.packets.server.InventoryPacket;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiFunction;
public class SWInventory {
private final Map<Integer, SWItem> itemMap;
private InvCallback close;
private ProxiedPlayer player;
private int size;
private String title;
private boolean next;
private final AtomicBoolean processingClick = new AtomicBoolean();
public SWInventory(ProxiedPlayer proxiedPlayer, int size, String title) {
itemMap = new HashMap<>();
InventoryCallbackHandler.inventoryHashMap.put(SteamwarUser.get(proxiedPlayer.getUniqueId()).getId(), this);
this.player = proxiedPlayer;
this.size = size;
this.title = title;
next = false;
}
public void addItem(int pos, SWItem item, InvCallback callback) {
addItem(pos, item, new ArrayList<>(), callback);
}
public void addItem(int pos, SWItem item, List<String> lore, InvCallback callback) {
item.setCallback(callback);
item.setLore(lore);
itemMap.put(pos, item);
}
public void addItem(int pos, SWItem item) {
itemMap.put(pos, item);
}
public void addItem(int pos, SWItem item, String name, InvCallback callback) {
item.setName(name);
item.setCallback(callback);
itemMap.put(pos, item);
}
public void removeItem(int position) {
itemMap.remove(position);
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void setTitle(String title) {
this.title = title;
}
public void setCallback(int pos, InvCallback callback) {
itemMap.get(pos).setCallback(callback);
}
public void setNext(boolean next) {
this.next = next;
}
public boolean isNext() {
return next;
}
public Map<Integer, SWItem> getItems() {
return itemMap;
}
public void handleCallback(InvCallback.ClickType type, int pos) {
if(processingClick.compareAndSet(false, true)) {
itemMap.get(pos).getCallback().clicked(type);
processingClick.set(false);
}
}
public void handleClose() {
if(processingClick.compareAndSet(false, true)) {
InventoryCallbackHandler.inventoryHashMap.remove(SteamwarUser.get(player.getUniqueId()).getId(), this);
if(close != null)
close.clicked(null);
processingClick.set(false);
}
}
public void open() {
InventoryPacket inv = new InventoryPacket(title, SteamwarUser.get(player.getUniqueId()).getId(), size, map(itemMap, (integer, swItem) -> swItem.writeToString(integer).toString()));
NetworkSender.send(player, inv);
}
private static <T, K, J> Map<T, J> map(Map<T, K> map, BiFunction<T, K, J> function) {
Map<T, J> result = new HashMap<>();
map.forEach((key, value) -> result.put(key, function.apply(key, value)));
return result;
}
public void close() {
close(player);
}
public static void close(ProxiedPlayer player) {
NetworkSender.send(player, new CloseInventoryPacket(SteamwarUser.get(player.getUniqueId()).getId()));
}
public void setClose(InvCallback close) {
this.close = close;
}
public ProxiedPlayer getPlayer() {
return player;
}
public void setPlayer(ProxiedPlayer player) {
this.player = player;
}
public String getTitle() {
return title;
}
}

Datei anzeigen

@ -1,173 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.inventory;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.List;
public class SWItem {
private String material, title, skullOwner;
private boolean enchanted, hideAttributes;
private List<String> lore;
private InvCallback callback;
private int color;
public SWItem(String material, String title) {
this.material = material.toUpperCase();
lore = new ArrayList<>();
this.title = title;
color = 0;
}
public SWItem(String title, int color) {
this.material = "DYE";
lore = new ArrayList<>();
this.title = title;
this.color = color;
}
public static SWItem getSkull(String skullOwner) {
SWItem item = new SWItem("SKULL", skullOwner);
item.setSkullOwner(skullOwner);
return item;
}
public void setCallback(InvCallback callback) {
this.callback = callback;
}
public void setColor(int color) {
this.color = color;
}
public InvCallback getCallback() {
return callback;
}
public String getMaterial() {
return material;
}
public void setMaterial(String material) {
this.material = material.toUpperCase();
}
public String getSkullOwner() {
return skullOwner;
}
public void setSkullOwner(String skullOwner) {
this.skullOwner = skullOwner;
}
public boolean isEnchanted() {
return enchanted;
}
public void setEnchanted(boolean enchanted) {
this.enchanted = enchanted;
}
public boolean isHideAttributes() {
return hideAttributes;
}
public void setHideAttributes(boolean hideAttributes) {
this.hideAttributes = hideAttributes;
}
public SWItem setName(String name) {
title = name;
return this;
}
public String getTitle() {
return title;
}
public void addLore(String lore) {
this.lore.add(lore);
}
public JsonObject writeToString(int position) {
JsonObject object = new JsonObject();
object.addProperty("material", material);
object.addProperty("position", position);
object.addProperty("title", title);
if(skullOwner != null)
object.addProperty("skullOwner", skullOwner);
if(enchanted)
object.addProperty("enchanted", true);
if(hideAttributes)
object.addProperty("hideAttributes", true);
if(color != 0)
object.addProperty("color", color);
if(lore != null) {
JsonArray array = new JsonArray();
for (String lores:
lore) {
array.add(lores);
}
object.add("lore", array);
}
return object;
}
@Override
public boolean equals(Object o) {
if(!(o instanceof SWItem))
return false;
SWItem item = (SWItem) o;
if(item.enchanted != enchanted)
return false;
if(item.hideAttributes != hideAttributes)
return false;
if(!item.material.equals(material))
return false;
if(!item.lore.equals(lore))
return false;
if(!item.skullOwner.equals(skullOwner))
return false;
return true;
}
public void setLore(List<String> lore) {
this.lore = lore;
}
public SWItem clone() {
SWItem item;
if(color != 0) {
item = new SWItem(title, color);
}else {
item = new SWItem(material, title);
}
item.setLore(lore);
item.setCallback(callback);
item.setEnchanted(enchanted);
item.setHideAttributes(hideAttributes);
return item;
}
}

Datei anzeigen

@ -1,121 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.inventory;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.*;
public class SWListInv<T> extends SWInventory {
private ListCallback<T> callback;
private List<SWListEntry<T>> elements;
private int page;
public SWListInv(ProxiedPlayer p, String t, List<SWListEntry<T>> l, ListCallback<T> c){
super(p, (l.size()>45) ? 54 : (l.size() + 9-l.size()%9), t);
callback = c;
elements = l;
page = 0;
}
@Override
public void open(){
if(elements.size() > 54){
if(page != 0)
addItem(45, new SWItem("§eSeite zurück", 10), (InvCallback.ClickType click) -> {
page--;
open();
});
else
addItem(45, new SWItem("§7Seite zurück", 8), (InvCallback.ClickType click) -> {});
if(page < elements.size()/45)
addItem(53, new SWItem("§eSeite vor", 10), "§eSeite vor", (InvCallback.ClickType click) -> {
page++;
open();
});
else
addItem(53, new SWItem("§eSeite vor", 8), (InvCallback.ClickType click) -> {});
}
int ipageLimit = elements.size() - page*45;
if(ipageLimit > 45 && elements.size() > 54){
ipageLimit = 45;
}
int i = page*45;
for(int ipage=0; ipage < ipageLimit; ipage++ ){
SWItem e = elements.get(i).getItem();
final int pos = i;
addItem(ipage, e);
setCallback(ipage, (InvCallback.ClickType click) -> callback.clicked(click, elements.get(pos).getObject()));
i++;
}
super.open();
}
public void setCallback(ListCallback<T> c){
callback = c;
}
public interface ListCallback<T>{
void clicked(InvCallback.ClickType click, T element);
}
public static List<SWListEntry<UUID>> createPlayerList(UUID without){
List<SWListEntry<UUID>> onlinePlayers = new ArrayList<>();
for(ProxiedPlayer player : BungeeCord.getInstance().getPlayer(without).getServer().getInfo().getPlayers()){
if(without != null && player.getUniqueId().equals(without))
continue;
onlinePlayers.add(new SWListEntry<>(SWItem.getSkull(player.getName()), player.getUniqueId()));
}
return onlinePlayers;
}
public static List<SWListEntry<UUID>> createGlobalPlayerList(UUID without){
List<SWListEntry<UUID>> onlinePlayers = new ArrayList<>();
for(ProxiedPlayer player : BungeeCord.getInstance().getPlayers()){
if(without != null && player.getUniqueId().equals(without))
continue;
onlinePlayers.add(new SWListEntry<>(SWItem.getSkull(player.getName()), player.getUniqueId()));
}
return onlinePlayers;
}
public static class SWListEntry<T>{
final SWItem item;
final T object;
public SWListEntry(SWItem item, T object){
this.item = item;
this.object = object;
}
public SWItem getItem(){
return item;
}
public T getObject(){
return object;
}
}
}

Datei anzeigen

@ -1,51 +0,0 @@
package de.steamwar.bungeecore.inventory;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.List;
import java.util.function.Function;
public class SWStreamInv<T> extends SWInventory {
private final SWListInv.ListCallback<T> callback;
private final Function<Integer, List<SWListInv.SWListEntry<T>>> constructor;
private int page;
public SWStreamInv(ProxiedPlayer proxiedPlayer, String title, SWListInv.ListCallback<T> callback, Function<Integer, List<SWListInv.SWListEntry<T>>> constructor) {
super(proxiedPlayer, 54, title);
this.callback = callback;
this.constructor = constructor;
page = 0;
}
@Override
public void open(){
List<SWListInv.SWListEntry<T>> entries = constructor.apply(page);
if(page != 0)
addItem(45, new SWItem("§eSeite zurück", 10), (InvCallback.ClickType click) -> {
page--;
open();
});
else
addItem(45, new SWItem("§7Seite zurück", 8), (InvCallback.ClickType click) -> {});
if(entries.size() == 45)
addItem(53, new SWItem("§eSeite vor", 10), (InvCallback.ClickType click) -> {
page++;
open();
});
else
addItem(53, new SWItem("§7Seite vor", 8), (InvCallback.ClickType click) -> {});
for(int i = 0; i < entries.size(); i++) {
SWListInv.SWListEntry<T> item = entries.get(i);
addItem(i, item.getItem());
setCallback(i, (InvCallback.ClickType click) -> {
close();
callback.clicked(click, item.getObject());
});
}
super.open();
}
}

Datei anzeigen

@ -1,94 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.listeners;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.commands.PunishmentCommand;
import de.steamwar.bungeecore.commands.WebpasswordCommand;
import de.steamwar.messages.ChatSender;
import de.steamwar.sql.BannedUserIPs;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.event.EventHandler;
import java.sql.Timestamp;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
public class BanListener extends BasicListener {
@EventHandler
public void onLogin(LoginEvent event) {
event.registerIntent(BungeeCore.get());
ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> {
PendingConnection connection = event.getConnection();
SteamwarUser user = SteamwarUser.getOrCreate(connection.getUniqueId(), connection.getName(), ConnectionListener::newPlayer, WebpasswordCommand::changeUsername);
String ip = IPSanitizer.getTrueAddress(connection).getHostAddress();
if (user.isPunished(Punishment.PunishmentType.Ban)) {
event.setCancelled(true);
BannedUserIPs.banIP(user.getId(), ip);
ChatSender.of(event).system(PunishmentCommand.punishmentMessage(user, Punishment.PunishmentType.Ban));
event.completeIntent(BungeeCore.get());
return;
}
List<BannedUserIPs> ips = BannedUserIPs.get(ip);
if(!ips.isEmpty()){
Timestamp highestBan = ips.get(0).getTimestamp();
boolean perma = false;
for(BannedUserIPs banned : ips) {
SteamwarUser bannedUser = SteamwarUser.get(banned.getUserID());
if (bannedUser.isPunished(Punishment.PunishmentType.Ban)) {
Punishment ban = bannedUser.getPunishment(Punishment.PunishmentType.Ban);
if(ban.isPerma()) {
perma = true;
break;
}
if(ban.getEndTime().after(highestBan))
highestBan = ban.getEndTime();
}
}
ClickEvent clickEvent = new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/ban " + user.getUserName() + " "
+ (perma?"perma":highestBan.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd.MM.yyyy_HH:mm")))
+ " Ban Evasion - Bannumgehung");
ChatSender.serverteamReceivers().forEach(sender -> sender.system(
"BAN_AVOIDING_ALERT",
new Message("BAN_AVOIDING_BAN_HOVER"),
clickEvent,
user.getUserName(),
ips.stream().map(banned -> {
SteamwarUser bannedUser = SteamwarUser.get(banned.getUserID());
return sender.parseToLegacy("BAN_AVOIDING_LIST", bannedUser.getUserName(),
banned.getTimestamp().toLocalDateTime().format(DateTimeFormatter.ofPattern(sender.parseToPlain("TIMEFORMAT"))));
}).collect(Collectors.joining(" "))
));
}
event.completeIntent(BungeeCore.get());
});
}
}

Datei anzeigen

@ -1,162 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.listeners;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Servertype;
import de.steamwar.bungeecore.Subserver;
import de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig;
import de.steamwar.bungeecore.bot.util.DiscordRanks;
import de.steamwar.bungeecore.commands.ChallengeCommand;
import de.steamwar.bungeecore.commands.CheckCommand;
import de.steamwar.bungeecore.commands.ModCommand;
import de.steamwar.bungeecore.commands.MsgCommand;
import de.steamwar.bungeecore.mods.ModUtils;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import net.md_5.bungee.api.AbstractReconnectHandler;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.event.ServerKickEvent;
import net.md_5.bungee.event.EventHandler;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
public class ConnectionListener extends BasicListener {
public static final String ALERT_PERMISSION = "bungeecore.alert";
public static final String BAN_PERMISSION = "bungeecore.ban";
public static final String BUILDERCLOUD_PERMISSION = "bungeecore.buildercloud";
public static final String CHECK_PERMISSION = "bungeecore.check";
public static final String EVENTRELOAD_PERMISSION = "bungeecore.eventreload";
public static final String KICK_PERMISSION = "bungeecore.kick";
public static final String POLLRESULT_PERMISSION = "bungeecore.pollresult";
public static final String SOFTRELOAD_PERMISSION = "bungeecore.softreload";
public static final String TEAMCHAT_PERMISSION = "bungeecore.teamchat";
public static final String MOD_PERMISSION = "bungeecore.mod";
private static final Set<UUID> newPlayers = new HashSet<>();
public static void newPlayer(UUID player){
newPlayers.add(player);
}
@EventHandler
public void onPostLogin(PostLoginEvent event) {
ProxiedPlayer player = event.getPlayer();
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
if(user.hasPerm(UserPerm.ADMINISTRATION)) {
player.setPermission("bungeecord.command.end", true);
player.setPermission("bungeecord.command.reload", true);
player.setPermission("bungeecord.command.ip", true);
player.setPermission(SOFTRELOAD_PERMISSION, true);
}
if(user.hasPerm(UserPerm.MODERATION)) {
player.setPermission(ALERT_PERMISSION, true);
player.setPermission(KICK_PERMISSION, true);
player.setPermission(POLLRESULT_PERMISSION, true);
player.setPermission(EVENTRELOAD_PERMISSION, true);
player.setPermission(MOD_PERMISSION, true);
}
if(user.hasPerm(UserPerm.TEAM)) {
player.setPermission("bungeecord.command.list", true);
player.setPermission("bungeecord.command.send", true);
player.setPermission("bungeecord.command.server", true);
player.setPermission(TEAMCHAT_PERMISSION, true);
player.setPermission(BAN_PERMISSION, true);
}
if(user.hasPerm(UserPerm.CHECK)) {
CheckCommand.sendReminder(player);
player.setPermission(CHECK_PERMISSION, true);
}
if(user.hasPerm(UserPerm.BUILD)) {
player.setPermission(BUILDERCLOUD_PERMISSION, true);
}
for(Subserver subserver : Subserver.getServerList()){
if(subserver.getType() == Servertype.ARENA){
Iterator<ProxiedPlayer> it = subserver.getServer().getPlayers().iterator();
if(it.hasNext()){
Message.send("JOIN_ARENA", player, Message.parse("JOIN_ARENA_HOVER", player),
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/join " + it.next().getName()), subserver.getServer().getName());
}
}
}
if(newPlayers.contains(player.getUniqueId())){
Message.broadcast("JOIN_FIRST", player.getName());
newPlayers.remove(player.getUniqueId());
}
if(SteamwarDiscordBotConfig.loaded)
DiscordRanks.update(user);
}
/** To redirect players to the lobby in case of server closure. */
@EventHandler
public void onServerKickEvent(ServerKickEvent ev)
{
if(!ev.getPlayer().isConnected())
return;
ServerInfo kickedFrom;
if (ev.getPlayer().getServer() != null){
kickedFrom = ev.getPlayer().getServer().getInfo();
}else if (ProxyServer.getInstance().getReconnectHandler() != null){
kickedFrom = ProxyServer.getInstance().getReconnectHandler().getServer(ev.getPlayer());
}else{
kickedFrom = AbstractReconnectHandler.getForcedHost(ev.getPlayer().getPendingConnection());
if (kickedFrom == null){
kickedFrom = ProxyServer.getInstance().getServerInfo(ev.getPlayer().getPendingConnection().getListener().getDefaultServer());
}
}
ServerInfo kickTo = ProxyServer.getInstance().getServerInfo(BungeeCore.LOBBY_SERVER);
if (kickedFrom != null && kickedFrom.equals(kickTo)) {
return;
}
ev.setCancelled(true);
ev.setCancelServer(kickTo);
}
@EventHandler
public void onDisconnect(PlayerDisconnectEvent e){
ChallengeCommand.remove(e.getPlayer());
MsgCommand.remove(e.getPlayer());
ModUtils.getPlayerModMap().remove(e.getPlayer().getUniqueId());
ModCommand.playerFilterType.remove(e.getPlayer());
}
}

Datei anzeigen

@ -1,29 +0,0 @@
package de.steamwar.bungeecore.listeners;
import de.steamwar.bungeecore.Message;
import de.steamwar.sql.*;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.event.EventHandler;
public class EventModeListener extends BasicListener {
@EventHandler
public void onPostLogin(PostLoginEvent e) {
SteamwarUser user = SteamwarUser.get(e.getPlayer().getUniqueId());
Event event = Event.get();
if(event == null){
e.getPlayer().disconnect(TextComponent.fromLegacyText(Message.parse("EVENTMODE_KICK", e.getPlayer())));
return;
}
if(TeamTeilnahme.nimmtTeil(user.getTeam(), event.getEventID()))
return;
if(Referee.get(event.getEventID()).contains(user.getId()))
return;
e.getPlayer().disconnect(TextComponent.fromLegacyText(Message.parse("EVENTMODE_KICK", e.getPlayer())));
}
}

Datei anzeigen

@ -1,66 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.listeners;
import de.steamwar.bungeecore.BungeeCore;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.netty.ChannelWrapper;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.logging.Level;
public class IPSanitizer extends BasicListener {
private static final Field initialHandlerCh;
static {
try {
initialHandlerCh = InitialHandler.class.getDeclaredField("ch");
} catch (NoSuchFieldException e) {
throw new SecurityException("Could not initialize Reflection", e);
}
initialHandlerCh.setAccessible(true);
}
public static ChannelWrapper getChannelWrapper(PendingConnection connection) {
try {
return (ChannelWrapper) initialHandlerCh.get(connection);
} catch (IllegalAccessException e) {
throw new SecurityException("Could not get channel wrapper", e);
}
}
public static InetAddress getTrueAddress(PendingConnection connection) {
return ((InetSocketAddress) getChannelWrapper(connection).getHandle().remoteAddress()).getAddress();
}
private final InetSocketAddress sanitized = new InetSocketAddress("127.127.127.127", 25565);
@EventHandler
public void loginEvent(LoginEvent e) {
BungeeCore.get().getLogger().log(Level.INFO, e.getConnection().getSocketAddress() + " has logged in with user name " + e.getConnection().getName());
getChannelWrapper(e.getConnection()).setRemoteAddress(sanitized);
}
}

Datei anzeigen

@ -1,322 +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.listeners;
import com.lunarclient.apollo.ApolloManager;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.commands.TeamCommand;
import de.steamwar.bungeecore.mods.*;
import de.steamwar.bungeecore.network.ServerMetaInfo;
import de.steamwar.messages.ChatSender;
import de.steamwar.network.packets.NetworkPacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.Connection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.function.Consumer;
import java.util.logging.Level;
public class PluginMessage extends BasicListener {
public static void send(ProxiedPlayer player, String legacyChannel, String channel, byte[] data) {
// 1.12 format change
send(player, player.getPendingConnection().getVersion() > 340 ? channel : legacyChannel, data);
}
public static void send(ProxiedPlayer player, String channel, byte[] data) {
if(((InitialHandler)player.getPendingConnection()).getRegisteredChannels().contains(channel))
player.sendData(channel, data);
}
public static byte[] genBufPacket(Consumer<ByteBuf> generator) {
ByteBuf buf = Unpooled.buffer();
generator.accept(buf);
byte[] packet = new byte[buf.readableBytes()];
buf.readBytes(packet);
return packet;
}
public static byte[] genStreamPacket(StreamConsumer generator) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(stream);
try {
generator.accept(out);
} catch (IOException e) {
throw new SecurityException("Could not create PluginMessage packet", e);
}
return stream.toByteArray();
}
public interface StreamConsumer {
void accept(DataOutputStream out) throws IOException;
}
private static final Parser UNKNOWN = event -> BungeeCore.get().getLogger().log(Level.WARNING, () -> "Undefined PluginMessage on channel " + event.getTag() + " from " + event.getSender() + " received.\n" + new String(event.getData()) + "\n" + Arrays.toString(event.getData()));
private static final Parser PASS_THROUGH = event -> event.setCancelled(false);
private static final Parser DROP = event -> {};
private final Lunar lunar = new Lunar();
private final Set<String> knownBrands = new HashSet<>();
private final Map<String, Consumer<ProxiedPlayer>> channelRegisterHandlers = new HashMap<>();
private final Map<String, Parser> handlers = new HashMap<>();
public PluginMessage() {
//TODO interface generalisation
LabyMod labyMod = new LabyMod();
WorldDownloader wdl = new WorldDownloader();
knownBrands.addAll(Arrays.asList("vanilla", "fabric", "quilt", "forge", "optifine", "Geyser", "labymod", "Feather Fabric"));
for(String channel : Arrays.asList(
"fabric:container/open", "fabric:registry/sync/direct", "fabric:registry/sync",
"fabric-screen-handler-api-v1:open_screen",
FML.CHANNEL, "fml:loginwrapper", "fml:handshake", "fml:play", "forge:tier_sorting", "forge:split",
"forge:login", "forge:handshake",
"labymod3:main", "labymod:neo",
"floodgate:skin", "floodgate:form", "floodgate:transfer", "floodgate:packet",
"Replay|Restrict", "replaymod:restrict",
"WDL|CONTROL", "wdl:control",
"tpshud:handshake", "tpshud:tps", //https://github.com/mooziii/tpshud-fabric/tree/main
"methane_server:statepacket", //https://modrinth.com/mod/methane
"servux:structures", //https://modrinth.com/mod/servux
"architectury:spawn_entity_packet", //https://modrinth.com/mod/architectury-api
"jei:channel", //https://modrinth.com/mod/jei
"shulkerboxtooltip:s2c_handshake", "shulkerboxtooltip:ec_update", //https://modrinth.com/mod/shulkerboxtooltip
"owo:local_packet", "owo:sync_screen_handler_properties", //https://modrinth.com/mod/owo-lib
"essential:", //https://essential.gg/
"libgui:screen_message_s2c", //https://github.com/CottonMC/LibGui
"minecraft:intave", //https://intave.ac seems to be a client side integration of intave with labymod 4
"midnightcontrols:feature", "midnightcontrols:controls_mode", //https://modrinth.com/mod/midnightcontrols
"controlify:vibrate_from_origin", "controlify:vibration", "controlify:vibrate_from_entity",
"carpet:structures", //https://modrinth.com/mod/carpet
"appleskin:exhaustion_sync", "appleskin:saturation_sync", //https://modrinth.com/mod/appleskin
"puzzleslib:1/1", //https://modrinth.com/mod/puzzles-lib
"pickupnotifier:1/1", //https://modrinth.com/mod/pick-up-notifier
"plasmo:voice/v2/installed", "plasmo:voice/v2", //https://modrinth.com/plugin/plasmo-voice
"whereisit:s2c_founditem", //https://modrinth.com/mod/where-is-it (needs server side component to work)
"inventorysorter:sync_blacklist_packet", //https://github.com/cpw/inventorysorter (needs server side component to work)
//https://github.com/bernie-g/geckolib
"geckolib:block_entity_anim_trigger_sync", "geckolib:entity_anim_trigger_sync",
"geckolib:block_entity_anim_data_sync", "geckolib:anim_data_sync",
"geckolib:entity_anim_data_sync", "geckolib:anim_trigger_sync",
//https://github.com/Noxcrew/noxesium
"noxesium-v1:reset", "noxesium-v1:change_server_rules", "noxesium-v1:server_info",
"noxesium-v1:mcc_server", "noxesium-v1:mcc_game_state", "noxesium-v1:reset_server_rules",
"noxesium-v1:stop_sound", "noxesium-v1:start_sound", "noxesium-v1:modify_sound"
))
channelRegisterHandlers.put(channel, player -> {});
channelRegisterHandlers.put(ApolloManager.PLUGIN_MESSAGE_CHANNEL, lunar::sendRestrictions);
channelRegisterHandlers.put(Feather.CHANNEL, new Feather()::sendRestrictions);
channelRegisterHandlers.put("xaerominimap:main", player -> player.sendMessage(ChatMessageType.SYSTEM, new TextComponent("§n§o§m§i§n§i§m§a§p"))); //https://www.curseforge.com/minecraft/mc-mods/xaeros-minimap
channelRegisterHandlers.put("litemoretica:init_easy_place", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "litematica")))); //https://github.com/Earthcomputer/litemoretica/tree/master
channelRegisterHandlers.put("voxelmap:settings", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "voxelmap")))); //https://modrinth.com/mod/voxelmap-updated undocumented
channelRegisterHandlers.put("worldinfo:world_id", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "minimap")))); // JourneyMap and VoxelMap
channelRegisterHandlers.put(Controlify.CHANNEL, new Controlify()::onRegister);
registerBiDirPassthrough("worldedit:cui");
registerPassthroughToClient(
"axiom:enable", "axiom:initialize_hotbars",
"axiom:response_chunk_data", "axiom:register_world_properties", "axiom:set_world_property",
"axiom:ack_world_properties", "axiom:restrictions", "axiom:marker_data", "axiom:marker_nbt_response",
"axiom:custom_blocks", "axiom:editor_warning", "axiom:blueprint_manifest", "axiom:response_blueprint"
);
registerBiDirPassthrough("axiom:handle_big_payload", "axiom:set_editor_views");
registerPassthroughToServer(
"axiom:hello", "axiom:set_gamemode", "axiom:set_fly_speed", "axiom:set_world_time",
"axiom:set_world_property", "axiom:set_block", "axiom:set_hotbar_slot", "axiom:switch_active_hotbar",
"axiom:teleport", "axiom:request_chunk_data", "axiom:spawn_entity",
"axiom:manipulate_entity", "axiom:delete_entity", "axiom:marker_nbt_request", "axiom:set_buffer"
);
for(String channel : Arrays.asList(
"UNREGISTER", "minecraft:unregister", // used by carpet and servux
"WDL|REQUEST", "wdl:request",
"minecraft:intave", //undocumented, byte stringlength, clientconfig, byte length, json {"legacySneakHeight":false,"legacyOldRange":false,"legacyOldSlowdown":false}
"waila:entity", "waila:block",
"lambdacontrols:hello",
"midnightcontrols:controls_mode",
"inventorysorter:sync_settings_packet",
"voicechat:request_secret", "voicechat:update_state", //https://modrinth.com/plugin/simple-voice-chat
"shulkerboxtooltip:c2s_handshake"
))
register(channel, false, directional(UNKNOWN, DROP));
register("REGISTER", false, directional(this::serverRegistersChannel, this::clientRegistersChannel));
register("minecraft:register", false, directional(this::serverRegistersChannel, this::clientRegistersChannel));
register("BungeeCord", false, onlySWSource(PASS_THROUGH));
register("bungeecord:main", false, onlySWSource(PASS_THROUGH));
register("MC|Brand", false, directional(this::steamWarBrand, this::userBrand));
register("minecraft:brand", false, directional(this::steamWarBrand, this::userBrand));
//Needs to be registered cause paper refuses to send PluginMessages on unregistered channels...
register("sw:bridge", true, directional(onlySWSource(async(event -> NetworkPacket.handle(new ServerMetaInfo(((Server) event.getSender()).getInfo()), event.getData()))), UNKNOWN));
register("sw:hotkeys", false, directional(UNKNOWN, PASS_THROUGH));
register("fabricmodsender:mods", true, directional(UNKNOWN, async(new FabricModSender()::handlePluginMessage)));
register("WDL|INIT", true, directional(UNKNOWN, wdl::handlePluginMessage));
register("wdl:init", true, directional(UNKNOWN, wdl::handlePluginMessage));
register(ApolloManager.PLUGIN_MESSAGE_CHANNEL, true, async(lunar::handlePluginMessage));
register("LMC", true, directional(UNKNOWN, async(labyMod::handlePluginMessage)));
register("labymod3:main", true, directional(UNKNOWN, async(labyMod::handlePluginMessage)));
register("labymod:neo", false, directional(UNKNOWN, DROP)); //undocumented, JSON format "0" byte, packetlängen byte, {"version":"4.1.25"}
register(FML.CHANNEL, true, directional(UNKNOWN, async(new FML()::handlePluginMessage)));
//vanilla does not register any channels (sends only one minecraft:brand vanilla, nothing else (potential spoofed client detection))
//Forge interestingly registers all channels the server registers
//meteor https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/ServerSpoof.java https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/DiscordPresence.java
//litematica/malilib https://github.com/maruohon/litematica/issues/75 https://github.com/maruohon/malilib/blob/liteloader_1.12.2/src/main/java/malilib/network/message/ConfigLockPacketHandler.java#L65
// Hackclientlike modsuppressor for labymod: https://github.com/Neocraftr/LabyMod-NeoEssentials (Potentially recognizable from NO Addons/NO Mods?) https://github.com/Neocraftr/LabyMod-NeoEssentials/blob/master/src/main/java/de/neocraftr/neoessentials/utils/BytecodeMethods.java
}
@EventHandler
public void onPluginMessage(PluginMessageEvent event) {
event.setCancelled(true);
try {
handlers.getOrDefault(event.getTag(), UNKNOWN).handle(event);
} catch (Exception e) {
throw new SecurityException("PluginMessage handling exception: " + event + "\n" + Arrays.toString(event.getData()), e);
}
}
private void registerPassthroughToClient(String... channels) {
for(String channel : channels) {
channelRegisterHandlers.put(channel, player -> {});
register(channel, false, directional(PASS_THROUGH, UNKNOWN));
}
}
private void registerPassthroughToServer(String... channels) {
for(String channel : channels)
register(channel, false, directional(UNKNOWN, PASS_THROUGH));
}
private void registerBiDirPassthrough(String... channels) {
for(String channel : channels) {
channelRegisterHandlers.put(channel, player -> {});
register(channel, false, PASS_THROUGH);
}
}
private void register(String channel, boolean clientSideRegister, Parser handler) {
handlers.put(channel, handler);
if(clientSideRegister)
ProxyServer.getInstance().registerChannel(channel);
}
private void clientRegistersChannel(PluginMessageEvent event) {
ProxiedPlayer player = (ProxiedPlayer) event.getSender();
for(String channel : new String(event.getData()).split("\0")) {
channelRegisterHandlers.getOrDefault(channel, p -> BungeeCore.get().getLogger().log(Level.WARNING, () -> p.getName() + " registered unknown channel " + channel)).accept(player);
}
PASS_THROUGH.handle(event);
}
private void serverRegistersChannel(PluginMessageEvent event) {
ProxiedPlayer player = (ProxiedPlayer)event.getReceiver();
List<String> channels = new ArrayList<>(Arrays.asList(new String(event.getData()).split("\0")));
channels.removeIf(channel -> channel.equals("sw:bridge"));
player.sendData((player).getPendingConnection().getVersion() > 340 ? "minecraft:register" : "REGISTER", String.join("\0", channels).getBytes());
}
private void userBrand(PluginMessageEvent event) {
ProxiedPlayer player = (ProxiedPlayer) event.getSender();
ByteBuf buf = Unpooled.wrappedBuffer(event.getData());
String brand = DefinedPacket.readString(buf);
boolean lunarclient = brand.startsWith("lunarclient:");
BungeeCore.get().getLogger().log(knownBrands.contains(brand) || lunarclient ? Level.INFO : Level.WARNING, () -> player.getName() + " joins with brand: " + brand);
if(lunarclient)
lunar.sendRestrictions(player);
PASS_THROUGH.handle(event);
}
private void steamWarBrand(PluginMessageEvent event) {
ProxiedPlayer player = (ProxiedPlayer) event.getReceiver();
String brandString = ChatSender.of(player).parseToLegacy("STEAMWAR_BRAND", ProxyServer.getInstance().getName(), player.getServer().getInfo().getName(), new String(event.getData(), 1, event.getData().length - 1));
ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer();
DefinedPacket.writeString(brandString, brand);
player.sendData(event.getTag(), DefinedPacket.toArray(brand));
brand.release();
}
private Parser directional(Parser fromServer, Parser fromPlayer) {
return event -> {
if(event.getSender() instanceof ProxiedPlayer)
fromPlayer.handle(event);
else
fromServer.handle(event);
};
}
@SuppressWarnings("deprecation")
private Parser onlySWSource(Parser parser) {
return event -> {
Connection sender = event.getSender();
if(TeamCommand.isLocalhost(sender instanceof ProxiedPlayer ? IPSanitizer.getTrueAddress(((ProxiedPlayer) sender).getPendingConnection()) : sender.getAddress().getAddress()))
parser.handle(event);
else
UNKNOWN.handle(event);
};
}
private Parser async(Parser parser) {
return event -> ProxyServer.getInstance().getScheduler().runAsync(BungeeCore.get(), () -> parser.handle(event));
}
private interface Parser {
void handle(PluginMessageEvent event);
}
}

Datei anzeigen

@ -1,82 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.listeners;
import de.steamwar.bungeecore.Message;
import de.steamwar.sql.PollAnswer;
import de.steamwar.sql.SteamwarUser;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.event.EventHandler;
import java.util.List;
public class PollSystem extends BasicListener {
private static String question;
private static List<String> answers;
public static void init(String question, List<String> answers){
PollSystem.question = question;
PollSystem.answers = answers;
if(noCurrentPoll())
return;
PollAnswer.setCurrentPoll(question);
new PollSystem();
}
@EventHandler
public void onPostLogin(PostLoginEvent event){
ProxiedPlayer player = event.getPlayer();
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
PollAnswer answer = PollAnswer.get(user.getId());
if(answer.hasAnswered())
return;
sendPoll(player);
}
public static void sendPoll(ProxiedPlayer player){
Message.send("POLL_HEADER", player);
Message.sendPrefixless("POLL_HEADER2", player);
Message.sendPrefixless("POLL_QUESTION", player, question);
for(int i = 1; i <= answers.size(); i++){
Message.send("POLL_ANWSER", player, Message.parse("POLL_ANWSER_HOVER", player, answers.get(i-1)),
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/poll " + i), answers.get(i-1));
}
}
public static boolean noCurrentPoll(){
return question == null || question.equals("");
}
public static int answers(){
return answers.size();
}
public static String getAnswer(int i) {
return answers.get(i);
}
}

Datei anzeigen

@ -1,183 +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.mods;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.listeners.BasicListener;
import de.steamwar.bungeecore.listeners.IPSanitizer;
import de.steamwar.bungeecore.listeners.PluginMessage;
import de.steamwar.sql.Mod;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.packet.LoginPayloadRequest;
import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
public class FML2 extends BasicListener {
// FML2: https://wiki.vg/Minecraft_Forge_Handshake#FML2_protocol_.281.13_-_Current.29
// FML3: https://github.com/adde0109/Ambassador/tree/non-api/src/main/java/org/adde0109/ambassador/forge
// FORGE: https://github.com/MinecraftForge/MinecraftForge/blob/1.20.x/src/main/java/net/minecraftforge/network/NetworkInitialization.java
// FORGE: https://github.com/MinecraftForge/MinecraftForge/blob/1.20.x/src/main/java/net/minecraftforge/network/ForgePacketHandler.java
// FORGE: https://github.com/MinecraftForge/MinecraftForge/blob/1.20.x/src/main/java/net/minecraftforge/network/packets/ModVersions.java
private final byte[] fml2ModListPacket;
private final byte[] fml3ModListPacket;
private final byte[] forgeModListPacket;
public FML2() {
fml2ModListPacket = generateModListPacket(false);
fml3ModListPacket = generateModListPacket(true);
forgeModListPacket = PluginMessage.genBufPacket(buf -> {
buf.writeByte(0); // Login wrapper packet
DefinedPacket.writeString("forge:handshake", buf);
ByteBuf packet = Unpooled.buffer();
packet.writeByte(1); // Mod list packet
DefinedPacket.writeVarInt(0, packet); // Mod amount
DefinedPacket.writeVarInt(packet.readableBytes(), buf);
buf.writeBytes(packet);
});
}
@EventHandler
public void onLogin(LoginEvent event) {
PendingConnection connection = event.getConnection();
boolean fml2 = FML.isFML(connection, "FML2\0");
boolean fml3 = FML.isFML(connection, "FML3\0");
boolean forge = FML.isFML(connection, "FORGE");
if(!fml2 && !fml3 && !forge)
return;
IPSanitizer.getChannelWrapper(connection).getHandle().pipeline().get(HandlerBoss.class).setHandler(new FML2LoginHandler(event));
event.registerIntent(BungeeCore.get());
if(forge)
connection.unsafe().sendPacket(new LoginPayloadRequest(1, "forge:login", forgeModListPacket));
else
connection.unsafe().sendPacket(new LoginPayloadRequest(1, "fml:loginwrapper", fml3 ? fml3ModListPacket : fml2ModListPacket));
}
private byte[] generateModListPacket(boolean fml3) {
return PluginMessage.genBufPacket(buf -> {
DefinedPacket.writeString("fml:handshake", buf);
ByteBuf packet = Unpooled.buffer();
packet.writeByte(1); // Mod list packet
DefinedPacket.writeVarInt(0, packet); // Mod amount
if(fml3) {
DefinedPacket.writeVarInt(1, packet); // Channel amount
DefinedPacket.writeString("forge:tier_sorting", packet);
DefinedPacket.writeString("1.0", packet);
} else {
DefinedPacket.writeVarInt(0, packet); // Channel amount
}
DefinedPacket.writeVarInt(0, packet); // Registries amount
if(fml3)
DefinedPacket.writeVarInt(0, packet); // DataPacks amount
DefinedPacket.writeVarInt(packet.readableBytes(), buf);
buf.writeBytes(packet);
});
}
private static class FML2LoginHandler extends PacketHandler {
private final LoginEvent event;
public FML2LoginHandler(LoginEvent event) {
this.event = event;
}
@Override
public String toString() {
return "SteamWar Forge Handler";
}
@Override
public void handle(LoginPayloadResponse response) {
boolean forge = FML.isFML(event.getConnection(), "FORGE");
byte[] data = response.getData();
if(data == null) {
abort(response, "Not FML2/3 client");
return;
}
ByteBuf buf = Unpooled.wrappedBuffer(data);
if(forge && buf.readByte() != 0) {
abort(response, "Not FORGE login wrapper");
return;
}
if(!DefinedPacket.readString(buf).equals(forge ? "forge:handshake" : "fml:handshake")) {
abort(response, "Not FML2/3/FORGE handshake response");
return;
}
if(DefinedPacket.readVarInt(buf) != buf.readableBytes()) {
abort(response, "FML2/3/FORGE packet size mismatch");
return;
}
if(DefinedPacket.readVarInt(buf) != (forge ? /* Mod Versions */ 1 : /* Mod List Reply */ 2)) {
abort(response, "Not FML2/3/FORGE mod list reply");
return;
}
List<Mod> mods = new ArrayList<>();
int modCount = DefinedPacket.readVarInt(buf);
for(int i = 0; i < modCount; i++) {
mods.add(Mod.getOrCreate(DefinedPacket.readString(buf), Mod.Platform.FORGE));
if(forge) {
DefinedPacket.readString(buf); // Human readable name
DefinedPacket.readString(buf); // Version
}
}
if(!ModUtils.handleMods(event.getConnection().getUniqueId(), Locale.getDefault(), event::setReason, mods))
event.setCancelled(true);
event.completeIntent(BungeeCore.get());
}
private void abort(LoginPayloadResponse response, String error) {
event.setReason(TextComponent.fromLegacy(error));
event.setCancelled(true);
event.completeIntent(BungeeCore.get());
BungeeCore.get().getLogger().log(Level.SEVERE, () -> error + "\n" + response);
}
}
}

Datei anzeigen

@ -1,66 +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.mods;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.listeners.BasicListener;
import net.md_5.bungee.api.event.PlayerHandshakeEvent;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.event.EventHandler;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
public class Hostname extends BasicListener {
private final Set<String> knownHostnames = new HashSet<>();
private final Set<String> knownExtraData = new HashSet<>();
public Hostname() {
knownHostnames.add("steamwar.de");
knownHostnames.add("78.31.71.136");
knownHostnames.add("memewar.de"); // Chaoscaot
knownHostnames.add("dampfkrieg.de"); // Chaoscaot
knownHostnames.add("127.0.0.1"); // Geyser
knownHostnames.add("@mat:matdoes.dev "); //https://github.com/mat-1/matscan
knownHostnames.add("wtf.mynx.lol"); //https://discord.com/invite/serverseeker
knownHostnames.add("masscan");
knownHostnames.add("aaa");
knownExtraData.add("");
knownExtraData.add("\0FML\0");
knownExtraData.add("\0FML2\0");
knownExtraData.add("\0FML3\0");
knownExtraData.add("\0FORGE");
}
@EventHandler
public void onHandshake(PlayerHandshakeEvent event) {
String hostname = event.getHandshake().getHost().toLowerCase();
String extraDataInHandshake = ((InitialHandler) event.getConnection()).getExtraDataInHandshake();
if (!knownHostnames.contains(hostname) && !hostname.endsWith(".steamwar.de")) {
BungeeCore.get().getLogger().log(Level.WARNING, () -> event.getConnection().getSocketAddress() + " connected with unknown hostname " + event.getHandshake() + " " + extraDataInHandshake);
} else if (!knownExtraData.contains(extraDataInHandshake)) {
BungeeCore.get().getLogger().log(Level.WARNING, () -> event.getConnection().getSocketAddress() + " connected with unknown extra data " + event.getHandshake() + " " + extraDataInHandshake);
}
}
}

Datei anzeigen

@ -1,63 +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.mods;
import com.google.gson.*;
import de.steamwar.bungeecore.listeners.BasicListener;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ServerPing;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
public class ServerListPing extends BasicListener implements JsonSerializer<ServerPing>, JsonDeserializer<ServerPing> {
// https://github.com/Aizistral-Studios/No-Chat-Reports/discussions/206
// https://github.com/Aizistral-Studios/No-Chat-Reports/wiki/How-to-Get-Safe-Server-Status
private final Gson gson;
public ServerListPing() {
BungeeCord bungeeCord = BungeeCord.getInstance();
gson = bungeeCord.gson;
try {
Field gsonField = BungeeCord.class.getDeclaredField("gson");
gsonField.setAccessible(true);
gsonField.set(bungeeCord, gson.newBuilder().registerTypeAdapter(ServerPing.class, this).create());
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
throw new SecurityException("Failed to inject ServerListPing", e);
}
}
@Override
public JsonElement serialize(ServerPing ping, Type type, JsonSerializationContext context) {
JsonElement element = gson.toJsonTree(ping, type);
JsonObject object = element.getAsJsonObject();
object.addProperty("preventsChatReports", true);
return element;
}
@Override
public ServerPing deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
return gson.fromJson(element, ServerPing.class);
}
}

Datei anzeigen

@ -1,36 +0,0 @@
/*
* 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.network;
import de.steamwar.bungeecore.network.handlers.*;
import lombok.experimental.UtilityClass;
@UtilityClass
public class BungeeNetworkHandler {
public static void register() {
new EloPlayerHandler().register();
new EloSchemHandler().register();
new ExecuteCommandHandler().register();
new FightInfoHandler().register();
new ImALobbyHandler().register();
new InventoryCallbackHandler().register();
new PrepareSchemHandler().register();
}
}

Datei anzeigen

@ -1,66 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.network.handlers;
import de.steamwar.bungeecore.network.NetworkSender;
import de.steamwar.bungeecore.network.ServerMetaInfo;
import de.steamwar.bungeecore.tablist.TablistManager;
import de.steamwar.network.packets.PacketHandler;
import de.steamwar.network.packets.common.FightInfoPacket;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class FightInfoHandler extends PacketHandler {
private static final Set<ServerInfo> lobbys = new HashSet<>();
public static void addLobby(ServerInfo lobby) {
lobbys.add(lobby);
}
public static boolean onLobby(ProxiedPlayer player) {
return lobbys.contains(player.getServer().getInfo());
}
@Handler
public void handle(FightInfoPacket packet) {
ServerInfo info = ((ServerMetaInfo) packet.getMetaInfos()).getSender();
FightInfoPacket lobbyPacket = packet.withServerName(info.getName());
TablistManager.newFightInfo(info, packet);
Iterator<ServerInfo> lobbyIt = lobbys.iterator();
while(lobbyIt.hasNext()) {
ServerInfo lobby = lobbyIt.next();
Iterator<ProxiedPlayer> it = lobby.getPlayers().iterator();
if(!it.hasNext()){
lobbyIt.remove();
continue;
}
NetworkSender.send(lobby, lobbyPacket);
}
}
}

Datei anzeigen

@ -1,369 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.tablist;
import de.steamwar.bungeecore.Storage;
import de.steamwar.messages.ChatSender;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.MessageToMessageDecoder;
import net.md_5.bungee.ServerConnection;
import net.md_5.bungee.UserConnection;
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.stream.Collectors;
import java.util.stream.IntStream;
@ChannelHandler.Sharable
public class Tablist extends MessageToMessageDecoder<PacketWrapper> {
private static final UUID[] uuids = IntStream.range(0, 80).mapToObj(i -> UUID.randomUUID()).toArray(UUID[]::new);
private static final String[] names = IntStream.range(0, 80).mapToObj(i -> " »SW« " + String.format("%02d", i)).toArray(String[]::new);
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 final Map<UUID, PlayerListItem.Item> directTabItems;
private final Set<UUID> npcs = new HashSet<>();
private final List<PlayerListItem.Item> current = new ArrayList<>();
private final ProxiedPlayer player;
private final ChatSender viewer;
private ServerConnection connection;
public Tablist(ProxiedPlayer player) {
this.player = player;
this.viewer = ChatSender.of(player);
this.directTabItems = Storage.directTabItems.computeIfAbsent(player, p -> new HashMap<>());
injection();
}
public void update(TablistPart global, int seconds) {
if (connection == null)
return;
player.setTabHeader(header(viewer, seconds), viewer.parse(false, "TABLIST_FOOTER", connection.getInfo().getName(), ping(), ProxyServer.getInstance().getPlayers().size()));
List<TablistPart.Item> tablist = new ArrayList<>();
List<TablistPart.Item> direct = new ArrayList<>();
global.print(viewer, player, tablist, direct);
// NPC handling
List<String> addNpc = new ArrayList<>();
List<String> removeNpc = new ArrayList<>();
List<PlayerListItem.Item> update = new ArrayList<>();
Set<UUID> nonNPCs = direct.stream().map(TablistPart.Item::getUuid).collect(Collectors.toSet());
synchronized (directTabItems) {
for (TablistPart.Item item : direct) {
PlayerListItem.Item tabItem = directTabItems.get(item.getUuid());
if(npcs.remove(item.getUuid()))
removeNpc.add(tabItem.getUsername());
if(tabItem == null) {
tablist.add(0, item);
} else if(!tabItem.getDisplayName().equals(item.getDisplayName())) {
tabItem.setDisplayName(item.getDisplayName());
tabItem.setListed(true);
update.add(tabItem);
}
}
boolean playerNotOnTeamserver = !Storage.teamServers.containsValue(player.getServer().getInfo());
for(PlayerListItem.Item item : directTabItems.values()) {
if(playerNotOnTeamserver && !nonNPCs.contains(item.getUuid()) && !npcs.contains(item.getUuid()) && !player.getUniqueId().equals(item.getUuid())) {
npcs.add(item.getUuid());
addNpc.add(item.getUsername());
}
}
}
sendNpcPacket(addNpc, false);
sendNpcPacket(removeNpc, true);
// Main list handling
int i = 0;
List<PlayerListItem.Item> add = new ArrayList<>();
List<PlayerListItem.Item> remove = new ArrayList<>();
for (; i < tablist.size() && i < 80; i++) {
PlayerListItem.Item tabItem;
if(current.size() > i) {
tabItem = current.get(i);
} else {
tabItem = new PlayerListItem.Item();
tabItem.setUuid(uuids[i]);
tabItem.setUsername(names[i]);
tabItem.setGamemode(1);
tabItem.setListed(true);
tabItem.setPing(1000);
current.add(tabItem);
}
TablistPart.Item item = tablist.get(i);
if(!Arrays.equals(tabItem.getProperties(), item.getProperties())) {
tabItem.setProperties(item.getProperties());
tabItem.setDisplayName(item.getDisplayName());
add.add(tabItem);
if(current.size() > i) {
remove.add(tabItem);
}
} else if(!item.getDisplayName().equals(tabItem.getDisplayName())) {
tabItem.setDisplayName(item.getDisplayName());
update.add(tabItem);
}
}
// Excess removal
while(i < current.size()) {
remove.add(current.remove(i));
}
sendTabPacket(remove, PlayerListItem.Action.REMOVE_PLAYER);
sendTabPacket(update, PlayerListItem.Action.UPDATE_DISPLAY_NAME);
sendTabPacket(add, PlayerListItem.Action.ADD_PLAYER);
}
public void onServerSwitch() {
injection();
synchronized (directTabItems) {
sendNpcPacket(npcs.stream().map(npc -> directTabItems.get(npc).getUsername()).collect(Collectors.toList()), true);
directTabItems.clear();
npcs.clear();
}
}
private void injection() {
connection = (ServerConnection) player.getServer();
if(connection != null) {
ChannelPipeline pipeline = connection.getCh().getHandle().pipeline();
if(pipeline.get("steamwar-tablist") != null) //Catch unclean exit
pipeline.remove("steamwar-tablist");
pipeline.addBefore(PipelineUtils.BOSS_HANDLER, "steamwar-tablist", this);
sendQueued(player, teamPacket);
}
}
public void disable() {
sendTabPacket(current, PlayerListItem.Action.REMOVE_PLAYER);
current.clear();
synchronized (directTabItems) {
sendNpcPacket(npcs.stream().map(npc -> directTabItems.get(npc).getUsername()).collect(Collectors.toList()), true);
npcs.clear();
}
if(connection != null)
connection.getCh().getHandle().pipeline().remove(this);
}
@Override
protected void decode(ChannelHandlerContext ctx, PacketWrapper packetWrapper, List<Object> out) {
if(!connection.isObsolete()) {
DefinedPacket packet = packetWrapper.packet;
if(packet instanceof PlayerListHeaderFooter) {
packetWrapper.trySingleRelease();
return;
}
if(packet instanceof PlayerListItem) {
PlayerListItem list = (PlayerListItem) packet;
PlayerListItem.Action action = list.getAction();
switch(action) {
case UPDATE_LATENCY:
case UPDATE_DISPLAY_NAME:
packetWrapper.trySingleRelease();
return;
case UPDATE_GAMEMODE:
for (PlayerListItem.Item item : list.getItems()) {
ProxiedPlayer p = ProxyServer.getInstance().getPlayer(item.getUuid());
if(p != null && p != player && item.getGamemode() == 3) {
item.setGamemode(1);
}
}
break;
case ADD_PLAYER:
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) {
directTabItems.put(item.getUuid(), item);
}
}
break;
case REMOVE_PLAYER:
List<String> names = new ArrayList<>();
for(PlayerListItem.Item item : list.getItems()) {
synchronized (directTabItems) {
PlayerListItem.Item directItem = directTabItems.remove(item.getUuid());
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))
names.add(directItem.getUsername());
}
}
sendNpcPacket(names, true);
} else if(packet instanceof PlayerListItemUpdate) {
PlayerListItemUpdate list = (PlayerListItemUpdate) packet;
EnumSet<PlayerListItemUpdate.Action> actions = list.getActions();
actions.remove(PlayerListItemUpdate.Action.INITIALIZE_CHAT);
actions.remove(PlayerListItemUpdate.Action.UPDATE_LATENCY);
actions.remove(PlayerListItemUpdate.Action.UPDATE_DISPLAY_NAME);
actions.remove(PlayerListItemUpdate.Action.UPDATE_LISTED);
if(actions.isEmpty()) {
packetWrapper.trySingleRelease();
return;
}
boolean playerNotOnTeamserver = !Storage.teamServers.containsValue(player.getServer().getInfo());
for(PlayerListItemUpdate.Action action : actions) {
switch (action) {
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) {
if(!names.isEmpty()) {
Team packet = new Team(TAB_TEAM);
packet.setMode((byte) (remove ? 4 : 3));
packet.setPlayers(names.toArray(new String[0]));
sendQueued(player, packet);
}
}
private BaseComponent[] header(ChatSender p, int seconds) {
int phase = (seconds % 10) / 5;
if (phase == 0)
return p.parse(false, "TABLIST_PHASE_DISCORD");
else
return p.parse(false, "TABLIST_PHASE_WEBSITE");
}
private String ping() {
int ping = player.getPing();
if (ping < 50) {
return "§a" + ping;
} else if (ping < 150) {
return "§e" + ping;
} else {
return "§c" + ping;
}
}
private static void sendQueued(ProxiedPlayer player, DefinedPacket packet) {
((UserConnection)player).sendPacketQueued(packet);
}
}

Datei anzeigen

@ -1,90 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.tablist;
import de.steamwar.messages.ChatSender;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
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.connection.InitialHandler;
import net.md_5.bungee.connection.LoginResult;
import net.md_5.bungee.protocol.Property;
import java.util.List;
import java.util.UUID;
interface TablistPart {
String sortKey();
void print(ChatSender viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct);
class Item {
public static Property[] playerProperties(ProxiedPlayer player) {
LoginResult loginResult = ((InitialHandler) player.getPendingConnection()).getLoginProfile();
if(loginResult == null)
return new Property[0];
return loginResult.getProperties();
}
private final UUID uuid;
private final BaseComponent displayName;
private final Property[] properties;
public Item(UUID uuid, String displayName, Property[] properties) {
this.uuid = uuid;
this.displayName = reformat(displayName);
this.properties = properties;
}
public Item(ProxiedPlayer player) {
this(player, false);
}
public Item(ProxiedPlayer player, boolean sameTeam) {
this.uuid = player.getUniqueId();
UserPerm.Prefix prefix = SteamwarUser.get(player.getUniqueId()).prefix();
if (prefix == UserPerm.emptyPrefix && sameTeam) {
this.displayName = reformat("§f" + player.getName());
} else {
this.displayName = reformat(prefix.getColorCode() + player.getName());
}
this.properties = playerProperties(player);
}
public UUID getUuid() {
return uuid;
}
public BaseComponent getDisplayName() {
return displayName;
}
public Property[] getProperties() {
return properties;
}
private BaseComponent reformat(String string) {
return TextComponent.fromArray(TextComponent.fromLegacyText(string));
}
}
}

Datei anzeigen

@ -1,103 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.tablist;
import de.steamwar.bungeecore.Servertype;
import de.steamwar.bungeecore.Subserver;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.messages.ChatSender;
import de.steamwar.network.packets.common.FightInfoPacket;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.protocol.Property;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TablistServer implements TablistPart {
public static final Property[] GRAY = new Property[]{new Property("textures", "eyJ0aW1lc3RhbXAiOjE0NTU1NzQxMTk0MzMsInByb2ZpbGVJZCI6ImIzYjE4MzQ1MzViZjRiNzU4ZTBjZGJmMGY4MjA2NTZlIiwicHJvZmlsZU5hbWUiOiIxMDExMTEiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzZlNzJkMzE0NzczMmQ5NzFkZWZhZTIzMWIzOGQ5NDI0MTRiMDU3YTcxNTFjNTNjNWZkNjI5NmEzYjllZGEwYWIifX19", "ro/ZKHt7278yhCr+CFTcPp/q6wAUlef//85k2DzkfRaZqy0CtGgwisDs2U4pVKvQ2pfXvitzWgbJvD0bLeQ12xWi4c1Fc29LCArosVJoFmrJDHz7N2MlstHT+ynQROb9d2aiFA6uOXfLjPKb1noUZ/YQoZjqcPIvD5oFZtD5DHV5O4hYz0IvgHbIjDqjz6ITsTcKiBlbxNg2loTFxSlW1ZfnNCO+kcAmeyB5NFY3j0e+/AqVANiNoiC3OKsECM/yEx/acf+vKWcT8mQn4wRoIGtxfEU7ZjNtgdh73NvXXBygW+K9AiJ242g8Y06Xxuk8kaNEGmT6H/mM7nbwjZmQQXpi/Pao2gYqyeIofeCPfr8RsGXoDX3nXDAw8/LyhTCHgx+sp6IQYSfGcSMJtoNeTJ0liIFxqn1V9/zKmzOZAPzR6qrQPOjoRFljLAlv7rfzotaEqh/1ldd40GdS8tstczn7f29OQerNDaqvbDb00Gy0STdUr1bVyCDptA54XKjT9WFv7QpBikEculxqSppAXPxD2Fb/ZmphbZx8WEGfG6bVFhf6fQdDAUXlcv8BxjElNPwlolF86M2KJd5VquLluhrCjwID7OK/pffNultAVH+Lxw4QOAXmJqjUrA1KHgyG1S0Cwj/f4E2hdxZJBvkfVtq9qPkd9nignhEoTCTOHf0=")};
public static final Property[] LIGHT_GRAY = new Property[]{new Property("textures", "eyJ0aW1lc3RhbXAiOjE0NTU2MjU1OTM5NjIsInByb2ZpbGVJZCI6ImIzYjE4MzQ1MzViZjRiNzU4ZTBjZGJmMGY4MjA2NTZlIiwicHJvZmlsZU5hbWUiOiIxMDExMTEiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzc4Y2I3ZmMyMDhiMzM4NTUwNGE4MTQ0MjA0NDI4ZmRjZDYzMjRiZWIzMWNhMmNlODZjYzQyNGI5NjNkODVjIn19fQ==", "R/wZUZRC1dishRdM9a2SSxxW3oYa0XSb/MxHbQpEUA791HxyqjaKLDu0wFX2r2a8ZTeVjzXpNzkg3+PkrA11o8h7lt86MTD1pi/rQqj/WRuoqf2LP+ypbssKV+LU15cYez2cj3QQVcJDXgWEnfSLNuBv6NG8BDUpUAjTWldvu99NCJHUoD0jNMHxY/fu4k5vCgOjaBaKgkjVk2bmUhegusmtMwco+3pYx+y8+gUW8ptx5SnePG+dOwTqLyBFiOt2AQ+gSvbU/jP9aAXgxOwz/b1pMaBWtzVhFU865NHlIdSpIHg/sh3uNah3a7gTgtTvxPQv1OzM/KtqYKiamsrRzAQMzRcs4A7Tp0GakLuxEaz401IwvQ7UGVYLFzGUVLB2MyqtPgifiqQSQxZpiqj9sM5QadhsUw00nfX7mTdW46U0MtNIbby1rLrvgQKoj08zt6LJlhI3yjyawy4iZkgF4oc+PCNwZc93GIbVL9LJaGkXk3RVA+JpGwfMJrGVbL7hl8ibbAcUv7uCEWdkAgZCd6w75jEE4tlhDSPDD4rXbn+FeTZRg2n/PGKtnoTZRzbniiFaNoSAHDZSVRG39xvBDFvtmL3SPaKhzKaifiYrgNn453WtR3kymqdAtPf1GN9d1VltGZ/+vMPwqPJb6thcrlcU64UGHbg1olRkiyZHvY8=")};
private final ServerInfo server;
private final List<Item> players;
public TablistServer(ServerInfo server) {
this(server, server.getPlayers().stream().sorted((p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName())).map(TablistPart.Item::new).collect(Collectors.toList()));
}
public TablistServer(ServerInfo server, FightInfoPacket info) {
this(server, new ArrayList<>());
Collection<ProxiedPlayer> onlinePlayers = server.getPlayers();
addPlayers(info.getBlueName().substring(0, 2), info.getBluePlayers(), onlinePlayers);
addPlayers(info.getRedName().substring(0, 2), info.getRedPlayers(), onlinePlayers);
addPlayers("§7", info.getSpectators(), onlinePlayers);
}
public TablistServer(ServerInfo server, List<Item> players) {
this.server = server;
this.players = players;
}
@Override
public String sortKey() {
return server.getName();
}
@Override
public void print(ChatSender viewer, ProxiedPlayer player, List<Item> tablist, List<Item> direct) {
boolean onServer = player.getServer().getInfo() == server;
List<Item> items = onServer ? direct : tablist;
if(!onServer) {
items.add(new Item(null, "", GRAY));
items.add(new Item(null, "§7§l" + server.getName(), LIGHT_GRAY));
}
teamify(players, player).forEach(items::add);
}
private void addPlayers(String prefix, List<Integer> teamPlayers, Collection<ProxiedPlayer> onlinePlayers){
teamPlayers.stream().map(SteamwarUser::get).map(
user -> onlinePlayers.stream().filter(player -> player.getUniqueId().equals(user.getUUID())).findAny()
).filter(Optional::isPresent).map(Optional::get).sorted(
(p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName())
).forEachOrdered(player -> players.add(new Item(player.getUniqueId(), prefix + player.getName(), Item.playerProperties(player))));
}
public static Stream<Item> teamify(List<Item> players, ProxiedPlayer player) {
int team = SteamwarUser.get(player.getUniqueId()).getTeam();
if (team == 0) return players.stream();
return players.stream().map(item -> {
ProxiedPlayer p = BungeeCord.getInstance().getPlayer(item.getUuid());
if (p == null) return item;
Subserver subserver = Subserver.getSubserver(p.getServer().getInfo());
if (subserver != null && subserver.getType() == Servertype.ARENA) return item;
if (SteamwarUser.get(p.getUniqueId()).getTeam() != team) return item;
return new Item(p, true);
});
}
}

Datei anzeigen

@ -1,48 +0,0 @@
/*
* 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.util;
import net.md_5.bungee.ServerConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.protocol.ChatChain;
import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.SeenMessages;
import net.md_5.bungee.protocol.packet.ClientChat;
import net.md_5.bungee.protocol.packet.ClientCommand;
import java.util.BitSet;
import java.util.Collections;
public class Chat19 {
private Chat19(){}
public static void chat(ProxiedPlayer p, String message) {
int version = p.getPendingConnection().getVersion();
if(version >= ProtocolConstants.MINECRAFT_1_19) {
if(message.startsWith("/")) {
((ServerConnection) p.getServer()).getCh().write(new ClientCommand(message.substring(1), System.currentTimeMillis(), 0, Collections.emptyMap(), false, new ChatChain(Collections.emptyList(), null), new SeenMessages(0, new BitSet(0))));
} else {
((ServerConnection) p.getServer()).getCh().write(new ClientChat(message, System.currentTimeMillis(), 0, version < ProtocolConstants.MINECRAFT_1_19_3 ? new byte[0] : null, false, new ChatChain(Collections.emptyList(), null), new SeenMessages(0, new BitSet(0))));
}
} else {
p.chat(message);
}
}
}

Datei anzeigen

@ -1,37 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.command;
import de.steamwar.bungeecore.BungeeCore;
import lombok.experimental.UtilityClass;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Command;
@UtilityClass
class CommandRegistering {
static void unregister(Command command) {
ProxyServer.getInstance().getPluginManager().unregisterCommand(command);
}
static void register(Command command) {
ProxyServer.getInstance().getPluginManager().registerCommand(BungeeCore.get(), command);
}
}

Datei anzeigen

@ -19,96 +19,115 @@
package de.steamwar.command; package de.steamwar.command;
import de.steamwar.bungeecore.BungeeCore; import com.velocitypowered.api.command.SimpleCommand;
import de.steamwar.bungeecore.Message; import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.messages.ChatSender; import de.steamwar.velocitycore.discord.DiscordBot;
import net.md_5.bungee.BungeeCord; import de.steamwar.messages.Chatter;
import net.md_5.bungee.api.CommandSender; import de.steamwar.messages.Message;
import net.md_5.bungee.api.chat.ClickEvent; import de.steamwar.sql.UserPerm;
import net.md_5.bungee.api.connection.ProxiedPlayer; import lombok.Getter;
import net.md_5.bungee.api.plugin.Command; import net.kyori.adventure.text.event.ClickEvent;
import net.md_5.bungee.api.plugin.TabExecutor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.logging.Level; import java.util.logging.Level;
public class SWCommand extends AbstractSWCommand<CommandSender> { public class SWCommand extends AbstractSWCommand<Chatter> {
static { static {
TypeUtils.init(); TypeUtils.init();
} }
private String permission; private final String name;
private Command command; @Getter
private final UserPerm permission;
private final String[] aliases;
private List<String> defaultHelpMessages = new ArrayList<>(); private SimpleCommand command;
protected SWCommand(String command) { private final List<String> defaultHelpMessages = new ArrayList<>();
this(command, null);
protected SWCommand(String command, String... aliases) {
this(command, null, aliases);
} }
protected SWCommand(String command, String permission) { protected SWCommand(String command, UserPerm permission, String... aliases) {
this(command, permission, new String[0]); super(Chatter.class, command, aliases);
} this.name = command;
protected SWCommand(String command, String permission, String... aliases) {
super(CommandSender.class, command, aliases);
this.permission = permission; this.permission = permission;
this.aliases = aliases;
create = true; create = true;
createAndSafeCommand(command, aliases); createAndSafeCommand(command, aliases);
unregister(); unregister();
register(); register();
} }
public void execute(Chatter sender, String[] args) {
execute(sender, null, args);
}
private boolean create = false; private boolean create = false;
@Override @Override
protected void createAndSafeCommand(String command, String[] aliases) { protected void createAndSafeCommand(String command, String[] aliases) {
if (!create) return; if (!create) return;
this.command = new TabCompletableCommand(command, permission, aliases) { this.command = new SimpleCommand() {
@Override @Override
public void execute(CommandSender commandSender, String[] strings) { public void execute(Invocation invocation) {
SWCommand.this.execute(commandSender, null, strings); SWCommand.this.execute(Chatter.of(invocation.source()), invocation.alias(), invocation.arguments());
} }
@Override @Override
public Iterable<String> onTabComplete(CommandSender commandSender, String[] strings) { public List<String> suggest(Invocation invocation) {
return SWCommand.this.tabComplete(commandSender, null, strings); if(invocation.arguments().length == 0)
return Collections.emptyList();
return SWCommand.this.tabComplete(Chatter.of(invocation.source()), invocation.alias(), invocation.arguments());
}
@Override
public boolean hasPermission(Invocation invocation) {
return permission == null || Chatter.of(invocation.source()).user().perms().contains(permission);
} }
}; };
} }
private abstract static class TabCompletableCommand extends Command implements TabExecutor {
public TabCompletableCommand(String name, String permission, String... aliases) {
super(name, permission, aliases);
}
}
@Override @Override
public void unregister() { public void unregister() {
if (command == null) return; if (command == null)
CommandRegistering.unregister(this.command); return;
VelocityCore.getProxy().getCommandManager().unregister(name);
DiscordBot.getCommands().remove(name);
for(String alias : aliases)
DiscordBot.getCommands().remove(alias);
} }
@Override @Override
public void register() { public void register() {
if (command == null) return; if (command == null)
CommandRegistering.register(this.command); return;
VelocityCore.getProxy().getCommandManager().register(VelocityCore.getProxy().getCommandManager().metaBuilder(name).aliases(aliases).plugin(VelocityCore.get()).build(), command);
DiscordBot.getCommands().put(name, this);
for(String alias : aliases)
DiscordBot.getCommands().put(alias, this);
} }
@Override @Override
protected void commandSystemError(CommandSender sender, CommandFrameworkException e) { protected void commandSystemError(Chatter sender, CommandFrameworkException e) {
BungeeCore.get().getLogger().log(Level.SEVERE, e.getMessage(), e); VelocityCore.getLogger().log(Level.SEVERE, e.getMessage(), e);
ChatSender.of(sender).prefixless("COMMAND_SYSTEM_ERROR"); sender.prefixless("COMMAND_SYSTEM_ERROR");
} }
@Override @Override
protected void commandSystemWarning(Supplier<String> message) { protected void commandSystemWarning(Supplier<String> message) {
BungeeCore.get().getLogger().log(Level.WARNING, message); VelocityCore.getLogger().log(Level.WARNING, message);
} }
public void addDefaultHelpMessage(String message) { public void addDefaultHelpMessage(String message) {
@ -116,24 +135,23 @@ public class SWCommand extends AbstractSWCommand<CommandSender> {
} }
@Override @Override
protected void sendMessage(CommandSender sender, String message, Object[] args) { protected void sendMessage(Chatter sender, String message, Object[] args) {
ChatSender.of(sender).system(message, args); sender.system(message, args);
} }
@Register(noTabComplete = true) @Register(noTabComplete = true)
public void internalHelp(ProxiedPlayer p, String... args) { public void internalHelp(Chatter sender, String... args) {
ChatSender chatSender = ChatSender.of(p);
try { try {
chatSender.prefixless("COMMAND_HELP_HEAD", command.getName()); sender.prefixless("COMMAND_HELP_HEAD", name);
defaultHelpMessages.forEach(chatSender::prefixless); defaultHelpMessages.forEach(sender::prefixless);
} catch (Exception e) { } catch (Exception e) {
BungeeCore.get().getLogger().log(Level.WARNING, "Failed to send help message", e); VelocityCore.getLogger().log(Level.WARNING, "Failed to send help message", e);
return; return;
} }
AtomicInteger atomicInteger = new AtomicInteger(); AtomicInteger atomicInteger = new AtomicInteger();
if (args.length != 0) { if (args.length != 0) {
commandList.forEach(subCommand -> { commandList.forEach(subCommand -> {
List<String> tabCompletes = subCommand.tabComplete(p, args); List<String> tabCompletes = subCommand.tabComplete(sender, args);
if (tabCompletes == null || tabCompletes.isEmpty()) { if (tabCompletes == null || tabCompletes.isEmpty()) {
atomicInteger.incrementAndGet(); atomicInteger.incrementAndGet();
return; return;
@ -141,7 +159,7 @@ public class SWCommand extends AbstractSWCommand<CommandSender> {
boolean hasTabCompletes = tabCompletes.stream() boolean hasTabCompletes = tabCompletes.stream()
.anyMatch(s -> s.toLowerCase().startsWith(args[args.length - 1].toLowerCase())); .anyMatch(s -> s.toLowerCase().startsWith(args[args.length - 1].toLowerCase()));
if (hasTabCompletes) { if (hasTabCompletes) {
send(chatSender, subCommand); send(sender, subCommand);
} else { } else {
atomicInteger.incrementAndGet(); atomicInteger.incrementAndGet();
} }
@ -149,22 +167,21 @@ public class SWCommand extends AbstractSWCommand<CommandSender> {
} }
if (args.length == 0 || atomicInteger.get() == commandList.size()) { if (args.length == 0 || atomicInteger.get() == commandList.size()) {
commandList.forEach(subCommand -> { commandList.forEach(subCommand -> {
if (subCommand.validator == null || subCommand.validator.validate(p, p, (s, args1) -> {})) { if (subCommand.validator == null || subCommand.validator.validate(sender, sender, (s, args1) -> {})) {
send(chatSender, subCommand); send(sender, subCommand);
} }
}); });
} }
} }
private void send(ChatSender chatSender, SubCommand<CommandSender> subCommand) { private void send(Chatter chatter, SubCommand<Chatter> subCommand) {
try { try {
for (String s : subCommand.description) { for (String s : subCommand.description) {
String hover = "§8/§e" + command.getName() + " " + String.join(" ", subCommand.subCommand); String hover = "§8/§e" + name + " " + String.join(" ", subCommand.subCommand);
String suggest = "/" + command.getName() + " " + String.join(" ", subCommand.subCommand); chatter.prefixless(s, new Message("PLAIN_STRING", hover), ClickEvent.suggestCommand("/" + name + " " + String.join(" ", subCommand.subCommand)));
chatSender.prefixless(s, new Message("PLAIN_STRING", hover), new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, suggest));
} }
} catch (Exception e) { } catch (Exception e) {
BungeeCore.get().getLogger().log(Level.WARNING, "Failed to send description of registered method '" + subCommand.method + "' with description '" + subCommand.description + "'", e); VelocityCore.getLogger().log(Level.WARNING, "Failed to send description of registered method '%s' with description '%s'".formatted(subCommand.method, Arrays.toString(subCommand.description)), e);
} }
} }
} }

Datei anzeigen

@ -19,11 +19,11 @@
package de.steamwar.command; package de.steamwar.command;
import net.md_5.bungee.api.CommandSender; import de.steamwar.messages.Chatter;
public interface TypeMapper<T> extends AbstractTypeMapper<CommandSender, T> { public interface TypeMapper<T> extends AbstractTypeMapper<Chatter, T> {
/** /**
* The CommandSender can be null! * The CommandSender can be null!
*/ */
T map(CommandSender commandSender, String[] previousArguments, String s); T map(Chatter sender, PreviousArguments previousArguments, String s);
} }

Datei anzeigen

@ -19,20 +19,56 @@
package de.steamwar.command; package de.steamwar.command;
import de.steamwar.bungeecore.commands.TypeMappers; import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.Player;
import de.steamwar.velocitycore.ServerVersion;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.commands.TypeMappers;
import de.steamwar.messages.Chatter;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
@UtilityClass @UtilityClass
public class TypeUtils { public class TypeUtils {
static void init() { static void init() {
SWCommandUtils.addMapper(ProxiedPlayer.class, SWCommandUtils.createMapper(BungeeCord.getInstance()::getPlayer, (s) -> BungeeCord.getInstance().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList()))); SWCommandUtils.addMapper(Player.class, SWCommandUtils.createMapper(s -> VelocityCore.getProxy().getPlayer(s).orElse(null), s -> VelocityCore.getProxy().getAllPlayers().stream().map(Player::getUsername).collect(Collectors.toList())));
SWCommandUtils.addMapper(SteamwarUser.class, SWCommandUtils.createMapper(SteamwarUser::get, s -> BungeeCord.getInstance().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList()))); SWCommandUtils.addMapper(SteamwarUser.class, SWCommandUtils.createMapper(SteamwarUser::get, s -> VelocityCore.getProxy().getAllPlayers().stream().map(Player::getUsername).collect(Collectors.toList())));
SWCommandUtils.addMapper(ServerVersion.class, new TypeMapper<>() {
@Override
public ServerVersion map(Chatter sender, PreviousArguments previousArguments, String s) {
Player player = sender.getPlayer();
if (player != null && s.isEmpty()) {
ProtocolVersion version = player.getProtocolVersion();
if (version.greaterThan(ProtocolVersion.MINECRAFT_1_19_4)) {
return ServerVersion.PAPER_20;
} else if (version.greaterThan(ProtocolVersion.MINECRAFT_1_15_2)) {
return ServerVersion.PAPER_19;
} else if (version.greaterThan(ProtocolVersion.MINECRAFT_1_12_2)) {
return ServerVersion.SPIGOT_15;
} else {
return ServerVersion.SPIGOT_12;
}
}
return ServerVersion.get(s);
}
@Override
public Collection<String> tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) {
return ServerVersion.chatVersions();
}
});
AbstractTypeMapper<Object, Team> teamMapper = SWCommandUtils.createMapper(Team::get, s -> Team.getAll().stream().flatMap(team -> Stream.of(team.getTeamKuerzel(), team.getTeamName())).collect(Collectors.toList()));
TabCompletionCache.add(teamMapper, true, 10, TimeUnit.SECONDS);
SWCommandUtils.addMapper(Team.class, teamMapper);
TypeMappers.init(); TypeMappers.init();
} }

Datei anzeigen

@ -19,7 +19,6 @@
package de.steamwar.command; package de.steamwar.command;
import net.md_5.bungee.api.CommandSender; import de.steamwar.messages.Chatter;
public interface TypeValidator<T> extends AbstractValidator<CommandSender, T> { public interface TypeValidator<T> extends AbstractValidator<Chatter, T> {}
}

Datei anzeigen

@ -9,6 +9,7 @@ PLAIN_STRING={0}
UNKNOWN_COMMAND=§cUnknown command. UNKNOWN_COMMAND=§cUnknown command.
UNKNOWN_PLAYER=§cUnknown player. UNKNOWN_PLAYER=§cUnknown player.
UNKNOWN_TEAM=§cUnknown team. UNKNOWN_TEAM=§cUnknown team.
UNKNOWN_EVENT=$cUnknown event.
INVALID_TIME=§cInvalid time. INVALID_TIME=§cInvalid time.
STEAMWAR_BRAND=§eSteam§8War.de §7({0}) §r<- §e{1} §7({2})§r STEAMWAR_BRAND=§eSteam§8War.de §7({0}) §r<- §e{1} §7({2})§r
@ -19,6 +20,7 @@ DEV_UNKNOWN_SERVER=§cPlease specify a dev server.
DISABLED=§cCurrently disabled. DISABLED=§cCurrently disabled.
SERVER_START_OVERLOAD=§cServer start cancelled due to overload. Please try again later. SERVER_START_OVERLOAD=§cServer start cancelled due to overload. Please try again later.
UPDATE_INTERRUPTION=§cPlease try again. A software update has interrupted this action.
#Help command #Help command
HELP_LOBBY=§7Return from anywhere to the lobby using §8/§el§7! HELP_LOBBY=§7Return from anywhere to the lobby using §8/§el§7!
@ -114,6 +116,7 @@ MOD_RED_SING=Attempted use of mod {0}
MOD_RED_PLUR=Attempted use of mods:\n{0} MOD_RED_PLUR=Attempted use of mods:\n{0}
MOD_YELLOW_SING=§7Deactivate the mod §e{0}§7 to continue playing on §eSteam§8War§7. MOD_YELLOW_SING=§7Deactivate the mod §e{0}§7 to continue playing on §eSteam§8War§7.
MOD_YELLOW_PLUR=§7Deactivate the mods\n§e{0}\n§7to continue playing on §eSteam§8War§7. MOD_YELLOW_PLUR=§7Deactivate the mods\n§e{0}\n§7to continue playing on §eSteam§8War§7.
MODS_CHECKED=§7Your Mods have been checked.\n§aYou can join §eSteam§8War §anow§8.
#Various commands #Various commands
ALERT=§f{0} ALERT=§f{0}
@ -253,7 +256,7 @@ EVENT_COMING=§eUpcoming events§8:
EVENT_COMING_EVENT=§7{0}§8-§7{1}§8: §e{2} EVENT_COMING_EVENT=§7{0}§8-§7{1}§8: §e{2}
EVENT_COMING_DEADLINE=§7 Registration deadline§8: §7{0} EVENT_COMING_DEADLINE=§7 Registration deadline§8: §7{0}
EVENT_COMING_SCHEM_DEADLINE=§7 Submission deadline§8: §7{0} EVENT_COMING_SCHEM_DEADLINE=§7 Submission deadline§8: §7{0}
EVENT_COMING_TEAMS=§7 With§8:{0} EVENT_COMING_TEAMS=§7 With§8: {0}
EVENT_COMING_TEAM= §{0}{1} EVENT_COMING_TEAM= §{0}{1}
EVENT_CURRENT_EVENT=§e§l{0} EVENT_CURRENT_EVENT=§e§l{0}
EVENT_CURRENT_FIGHT=§7{0} §{1}{2}§8 vs §{3}{4} EVENT_CURRENT_FIGHT=§7{0} §{1}{2}§8 vs §{3}{4}
@ -283,7 +286,7 @@ CHECK_HELP_DECLINE=§8/§7check decline §8[§ereason§8] - §7Decline schematic
CHECK_HELP_CANCEL=§8/§7check cancel §8- §7Cancels reviewing process CHECK_HELP_CANCEL=§8/§7check cancel §8- §7Cancels reviewing process
CHECK_LIST_HEADER=§e§l{0} schematics are left to review CHECK_LIST_HEADER=§e§l{0} schematics are left to review
CHECK_LIST_TO_CHECK={0} §8{1} §7{2} §e{3} CHECK_LIST_TO_CHECK={0} §8{1} §7{2} §e{3}
CHECK_LIST_WAIT={0}:{1} CHECK_LIST_WAIT=§{0}{1}:{2}
CHECK_LIST_TO_CHECK_HOVER=§eCheck schematic CHECK_LIST_TO_CHECK_HOVER=§eCheck schematic
CHECK_LIST_CHECKING={0} §8{1} §7{2} §e{3} §7is being reviewed by §e{4} CHECK_LIST_CHECKING={0} §8{1} §7{2} §e{3} §7is being reviewed by §e{4}
CHECK_LIST_CHECKING_HOVER=§eTo the reviewer CHECK_LIST_CHECKING_HOVER=§eTo the reviewer
@ -322,6 +325,7 @@ KICK_USAGE=§8/§7kick §8[§ePlayer§8] [§eMessage§8]
KICK_OFFLINE=§cThis player is currently not online! KICK_OFFLINE=§cThis player is currently not online!
KICK_CONFIRM=The player {0} was kicked. KICK_CONFIRM=The player {0} was kicked.
KICK_NORMAL=§cYou were kicked. KICK_NORMAL=§cYou were kicked.
KICK_CUSTOM=§c{0}
#MsgCommand #MsgCommand
MSG_USAGE=§8/§7msg §8[§euser§8] [§emessage§8] MSG_USAGE=§8/§7msg §8[§euser§8] [§emessage§8]
@ -481,7 +485,7 @@ TEAM_LIST_UNKNOWN_PAGE=§cInvalid page entered
TEAM_LIST_HEADER=§7§lTeam list §7{0}§8/§7{1} TEAM_LIST_HEADER=§7§lTeam list §7{0}§8/§7{1}
TEAM_LIST_TEAM=§{0}{1} §e{2} TEAM_LIST_TEAM=§{0}{1} §e{2}
TEAM_LIST_TEAM_HOVER=§7Team info TEAM_LIST_TEAM_HOVER=§7Team info
TEAM_LIST_PAGE=Page TEAM_LIST_PAGE=Page »»
TEAM_LIST_NEXT=§eNext page TEAM_LIST_NEXT=§eNext page
TEAM_LIST_PREV=§ePrevious page TEAM_LIST_PREV=§ePrevious page
@ -493,7 +497,7 @@ TEAM_EVENT_NO_EVENT=§cThis event does not exist
TEAM_EVENT_OVER=§cThe registration period for this event is already over TEAM_EVENT_OVER=§cThe registration period for this event is already over
TEAM_EVENT_LEFT=§7Your team no longer takes part in this event TEAM_EVENT_LEFT=§7Your team no longer takes part in this event
TEAM_EVENT_JOINED=§7Your team now takes part in the event §e{0}§7! TEAM_EVENT_JOINED=§7Your team now takes part in the event §e{0}§7!
TEAM_EVENT_HOW_TO_LEAVE=§7To cancel the participation, repeat the command TEAM_EVENT_HOW_TO_LEAVE=§7To cancel the participation repeat the command.
#Team Color #Team Color
TEAM_COLOR_TITLE=Choose color TEAM_COLOR_TITLE=Choose color
@ -568,8 +572,8 @@ EVENTMODE_KICK=§cYou are not an event participant.
POLL_HEADER=§e§lPoll POLL_HEADER=§e§lPoll
POLL_HEADER2=§7Click the answer you like! POLL_HEADER2=§7Click the answer you like!
POLL_QUESTION=§e{0} POLL_QUESTION=§e{0}
POLL_ANWSER=§7{0} POLL_ANSWER=§7{0}
POLL_ANWSER_HOVER=§eChoose {0} POLL_ANSWER_HOVER=§eChoose {0}
#TablistManager #TablistManager
TABLIST_PHASE_WEBSITE=§8Website: https://§eSteam§8War.de TABLIST_PHASE_WEBSITE=§8Website: https://§eSteam§8War.de
@ -620,6 +624,7 @@ VERIFY_INVALID=§cInvalid Code
VERIFY_SUCCESS=§7Successfully linked to the Discord account §e{0} VERIFY_SUCCESS=§7Successfully linked to the Discord account §e{0}
#Discord #Discord
DISCORD_TICKET_HOVER=§eTo the message
DISCORD_TICKET_MESSAGE=§7Ticket §e{0}§7» §f§l{1}: §7{2} DISCORD_TICKET_MESSAGE=§7Ticket §e{0}§7» §f§l{1}: §7{2}
DISCORD_TICKET_NEW=§7Ticket §e{0}§7» §aTicket was created! DISCORD_TICKET_NEW=§7Ticket §e{0}§7» §aTicket was created!
DISCORD_TICKET_CLOSED=§7Ticket §e{0}§7» §cTicket was closed! DISCORD_TICKET_CLOSED=§7Ticket §e{0}§7» §cTicket was closed!
@ -690,9 +695,38 @@ MOD_COMMAND_INFO=§7The mod {0} on platform {1} is of the type {2}.
MOD_COMMAND_GUI_TITLE=Unclassified Mods MOD_COMMAND_GUI_TITLE=Unclassified Mods
MOD_COMMAND_CLASSICIATION_GUI=Mod Type Changer MOD_COMMAND_CLASSICIATION_GUI=Mod Type Changer
MOD_OPEN_GUI=§7Open Gui MOD_OPEN_GUI=§7Open Gui
MOD_TITLE_FILTER=Filter
MOD_UNCLASSIFIED=§7Unclassified MOD_UNCLASSIFIED=§7Unclassified
MOD_ALLOWED=§aAllowed MOD_ALLOWED=§aAllowed
MOD_FORBIDDEN=§eForbidden MOD_FORBIDDEN=§eForbidden
MOD_AUTOBAN=§cAutoban MOD_AUTOBAN=§cAutoban
MOD_YT=§5YT Only MOD_YT=§5YT Only
MOD_ITEM_BACK=§7Back MOD_ITEM_BACK=§7Back
#StreamInv
INV_PAGE_BACK=§{0}Seite zurück
INV_PAGE_NEXT=§{0}Seite vor
#Discord
DC_UNLINKED=For this action your Discord account has to be linked to your Minecraft account. To link your accounts go onto the SteamWar Discord to the `regeln-infos` Channel and click on `Minecraft Verknüpfen`.
DC_TITLE_SCHEMINFO=Schematic Info
DC_SCHEM_ACCEPT=Your schematic **{0}** has been accepted.
DC_SCHEM_DECLINE=Your schematic **{0}** has been declined.\n**Reason:**{1}
DC_AUTH_SUCCESS=:white_check_mark: You're Discord account has been linked with **{0}**.
DC_ROLE_ADDED=:tada: You're getting {0} now.
DC_ROLE_REMOVED=You're not getting {0} anymore.
DC_TICKET_CREATED=You're Ticket {0} has been created.
DC_TICKET_TITLE=SteamWar Ticket
DC_TICKETINTRO_REPORT=Please answer for the punishment of the misconduct the following questions as accurately as possible and attach evidence whenever possible:\n - Which player(s)?\n - On which Server?\n - At what time?\n - Type and nature of the misconduct?
DC_TICKETINTRO_IDEA=Describe your idea as detailed as possible. Hereto belongs: What, Why, How, Where?
DC_TICKETINTRO_BUG=Please describe the observed unexpected or incorrect behaviour of our software. If necessary describe steps to reproduce the error.
DC_TICKETINTRO_QUESTION=Please ask your question. A staff member will address the question soon.
DC_TICKETINTRO_APPEAL=Asking creates wonders.
DC_TICKET_CLOSE=Close
DC_SCHEMUPLOAD_NOPERM=You're not allowed to upload schematics.
DC_SCHEMUPLOAD_IGNORED=Skipping `{0}`, not a schematic file.
DC_SCHEMUPLOAD_INVCHAR=`{0}` has invalid characters in its name.
DC_SCHEMUPLOAD_SUCCESS=`{0}` was uploaded successfully.
DC_SCHEMUPLOAD_ERROR=An error has occured during the upload of `{0}`. For more information ask a Developer.

Datei anzeigen

@ -7,6 +7,7 @@ TIMEFORMAT=dd.MM.yyyy HH:mm
UNKNOWN_COMMAND=§cUnbekannter Befehl. UNKNOWN_COMMAND=§cUnbekannter Befehl.
UNKNOWN_PLAYER=§cDiesen Spieler gibt es nicht. UNKNOWN_PLAYER=§cDiesen Spieler gibt es nicht.
UNKNOWN_TEAM=§cDieses Team gibt es nicht. UNKNOWN_TEAM=§cDieses Team gibt es nicht.
UNKNOWN_EVENT=$cDieses Event gibt es nicht.
INVALID_TIME=§cUngültige Zeitangabe. INVALID_TIME=§cUngültige Zeitangabe.
DEV_NO_SERVER=§cDer Server ist derzeit nicht erreichbar. DEV_NO_SERVER=§cDer Server ist derzeit nicht erreichbar.
@ -15,6 +16,7 @@ DEV_UNKNOWN_SERVER=§cBitte gib einen DevServer an.
DISABLED=§cDerzeit deaktiviert. DISABLED=§cDerzeit deaktiviert.
SERVER_START_OVERLOAD=§cDer Serverstart wurde aufgrund von Überlastung abgebrochen. Versuche es später erneut. SERVER_START_OVERLOAD=§cDer Serverstart wurde aufgrund von Überlastung abgebrochen. Versuche es später erneut.
UPDATE_INTERRUPTION=§cBitte erneut versuchen. Ein Softwareupdate hat die Aktion unterbrochen.
#Help command #Help command
HELP_LOBBY=§7Kehre von überall mit §8/§el §7zur Lobby zurück! HELP_LOBBY=§7Kehre von überall mit §8/§el §7zur Lobby zurück!
@ -99,6 +101,7 @@ MOD_RED_SING=Versuchte Benutzung des Mods {0}
MOD_RED_PLUR=Versuchte Benutzung der Mods:\n{0} MOD_RED_PLUR=Versuchte Benutzung der Mods:\n{0}
MOD_YELLOW_SING=§7Deaktiviere den Mod §e{0}§7, um weiter auf §eSteam§8War §7spielen zu können. MOD_YELLOW_SING=§7Deaktiviere den Mod §e{0}§7, um weiter auf §eSteam§8War §7spielen zu können.
MOD_YELLOW_PLUR=§7Deaktiviere die Mods\n§e{0}\n§7um weiter auf §eSteam§8War §7spielen zu können. MOD_YELLOW_PLUR=§7Deaktiviere die Mods\n§e{0}\n§7um weiter auf §eSteam§8War §7spielen zu können.
MODS_CHECKED=§7Deine installierten Mods wurden überprüft.\n§aDu kannst nun §eSteam§8War §abetreten§8.
#Various commands #Various commands
STAT_SERVER=§7Server §e{0}§8: §7Startfähig §e{1} §7Serveranzahl §e{2} STAT_SERVER=§7Server §e{0}§8: §7Startfähig §e{1} §7Serveranzahl §e{2}
@ -236,7 +239,7 @@ EVENT_COMING=§eKommende Events§8:
EVENT_COMING_EVENT=§7{0}§8-§7{1}§8: §e{2} EVENT_COMING_EVENT=§7{0}§8-§7{1}§8: §e{2}
EVENT_COMING_DEADLINE=§7 Anmeldeschluss§8: §7{0} EVENT_COMING_DEADLINE=§7 Anmeldeschluss§8: §7{0}
EVENT_COMING_SCHEM_DEADLINE=§7 Einsendeschluss§8: §7{0} EVENT_COMING_SCHEM_DEADLINE=§7 Einsendeschluss§8: §7{0}
EVENT_COMING_TEAMS=§7 Mit§8:{0} EVENT_COMING_TEAMS=§7 Mit§8: {0}
EVENT_COMING_TEAM= §{0}{1} EVENT_COMING_TEAM= §{0}{1}
EVENT_CURRENT_EVENT=§e§l{0} EVENT_CURRENT_EVENT=§e§l{0}
EVENT_CURRENT_FIGHT=§7{0} §{1}{2}§8 vs §{3}{4} EVENT_CURRENT_FIGHT=§7{0} §{1}{2}§8 vs §{3}{4}
@ -266,7 +269,6 @@ CHECK_HELP_DECLINE=§8/§7check decline §8[§eGrund§8] - §7Schematic ablehnen
CHECK_HELP_CANCEL=§8/§7check cancel §8- §7Bricht den Prüfvorgang ab CHECK_HELP_CANCEL=§8/§7check cancel §8- §7Bricht den Prüfvorgang ab
CHECK_LIST_HEADER=§e§lZu prüfen sind {0} Schematics CHECK_LIST_HEADER=§e§lZu prüfen sind {0} Schematics
CHECK_LIST_TO_CHECK={0} §8{1} §7{2} §e{3} CHECK_LIST_TO_CHECK={0} §8{1} §7{2} §e{3}
CHECK_LIST_WAIT={0}:{1}
CHECK_LIST_TO_CHECK_HOVER=§eSchematic prüfen CHECK_LIST_TO_CHECK_HOVER=§eSchematic prüfen
CHECK_LIST_CHECKING={0} §8{1} §7{2} §e{3} §7wird geprüft von §e{4} CHECK_LIST_CHECKING={0} §8{1} §7{2} §e{3} §7wird geprüft von §e{4}
CHECK_LIST_CHECKING_HOVER=§eZum Prüfer CHECK_LIST_CHECKING_HOVER=§eZum Prüfer
@ -458,7 +460,7 @@ TEAM_LIST_UNKNOWN_PAGE=§cUngültige Seitenzahl angegeben
TEAM_LIST_HEADER=§7§lTeamliste §7{0}§8/§7{1} TEAM_LIST_HEADER=§7§lTeamliste §7{0}§8/§7{1}
TEAM_LIST_TEAM=§{0}{1} §e{2} TEAM_LIST_TEAM=§{0}{1} §e{2}
TEAM_LIST_TEAM_HOVER=§7Teaminfo TEAM_LIST_TEAM_HOVER=§7Teaminfo
TEAM_LIST_PAGE=Seite TEAM_LIST_PAGE=Seite »»
TEAM_LIST_NEXT=§eNächste Seite TEAM_LIST_NEXT=§eNächste Seite
TEAM_LIST_PREV=§eVorherige Seite TEAM_LIST_PREV=§eVorherige Seite
@ -470,7 +472,7 @@ TEAM_EVENT_NO_EVENT=§cDieses Event gibt es nicht
TEAM_EVENT_OVER=§cDie Anmeldephase für dieses Event ist bereits vorbei TEAM_EVENT_OVER=§cDie Anmeldephase für dieses Event ist bereits vorbei
TEAM_EVENT_LEFT=§7Dein Team nimmt nicht mehr am Event teil TEAM_EVENT_LEFT=§7Dein Team nimmt nicht mehr am Event teil
TEAM_EVENT_JOINED=§7Dein Team nimmt nun am Event §e{0} §7 teil! TEAM_EVENT_JOINED=§7Dein Team nimmt nun am Event §e{0} §7 teil!
TEAM_EVENT_HOW_TO_LEAVE=§7Um die Teilnahme abzusagen, wiederhole den Befehl TEAM_EVENT_HOW_TO_LEAVE=§7Um die Teilnahme abzusagen, wiederhole den Befehl.
#Team Color #Team Color
TEAM_COLOR_TITLE=Farbe wählen TEAM_COLOR_TITLE=Farbe wählen
@ -546,8 +548,8 @@ EVENTMODE_KICK=§cDu bist kein Eventteilnehmer.
POLL_HEADER=§e§lUmfrage POLL_HEADER=§e§lUmfrage
POLL_HEADER2=§7Klicke die Antwort an, die dir gefällt! POLL_HEADER2=§7Klicke die Antwort an, die dir gefällt!
POLL_QUESTION=§e{0} POLL_QUESTION=§e{0}
POLL_ANWSER=§7{0} POLL_ANSWER=§7{0}
POLL_ANWSER_HOVER=§e{0} §ewählen POLL_ANSWER_HOVER=§e{0} §ewählen
#TablistManager #TablistManager
TABLIST_PHASE_WEBSITE=§8Website: https://§eSteam§8War.de TABLIST_PHASE_WEBSITE=§8Website: https://§eSteam§8War.de
@ -597,6 +599,7 @@ VERIFY_INVALID=§cInvalider Code
VERIFY_SUCCESS=§7Erfolgreich mit dem Discord Account §e{0} §7verknüpft VERIFY_SUCCESS=§7Erfolgreich mit dem Discord Account §e{0} §7verknüpft
#Discord #Discord
DISCORD_TICKET_HOVER=§eZur Nachricht
DISCORD_TICKET_MESSAGE=§7Ticket §e{0}§7» §f§l{1}: §7{2} DISCORD_TICKET_MESSAGE=§7Ticket §e{0}§7» §f§l{1}: §7{2}
DISCORD_TICKET_NEW=§7Ticket §e{0}§7» §aTicket wurde geöffnet! DISCORD_TICKET_NEW=§7Ticket §e{0}§7» §aTicket wurde geöffnet!
DISCORD_TICKET_CLOSED=§7Ticket §e{0}§7» §cTicket wurde geschlossen! DISCORD_TICKET_CLOSED=§7Ticket §e{0}§7» §cTicket wurde geschlossen!
@ -651,4 +654,31 @@ ADVENT_CALENDAR_TITLE=§eAdventskalender
ADVENT_CALENDAR_DAY=§7Tag§8: §e{0} ADVENT_CALENDAR_DAY=§7Tag§8: §e{0}
ADVENT_CALENDAR_MESSAGE=§eHast du heute schon dein Geschenk geholt? ADVENT_CALENDAR_MESSAGE=§eHast du heute schon dein Geschenk geholt?
ADVENT_CALENDAR_MESSAGE_HOVER=§eKlicken zum öffnen! ADVENT_CALENDAR_MESSAGE_HOVER=§eKlicken zum öffnen!
ADVENT_CALENDAR_OPEN=§7Du hast §e{0}§7 aus dem Adventskalender erhalten! ADVENT_CALENDAR_OPEN=§7Du hast §e{0}§7 aus dem Adventskalender erhalten!
#StreamInv
INV_PAGE_BACK=§{0}Page back
INV_PAGE_NEXT=§{0}Next page
#Discord
DC_UNLINKED=Für diese Aktion muss dein Minecraftaccount mit deinem Discordaccount verknüpft sein, gehe dazu auf dem SteamWar-Discord in den `regeln-infos` Channel und Klicke auf `Minecraft Verknüpfen`.
DC_TITLE_SCHEMINFO=Schematicinfo
DC_SCHEM_ACCEPT=Deine Schematic **{0}** wurde angenommen.
DC_SCHEM_DECLINE=Deine Schematic **{0}** wurde abgelehnt. **Grund:** \n{1}
DC_AUTH_SUCCESS=:white_check_mark: Dein Discordaccount wurde mit **{0}** verknüpft.
DC_ROLE_ADDED=:tada: Du bekommst nun {0}.
DC_ROLE_REMOVED=Du bekommst nun keine {0} mehr.
DC_TICKET_CREATED=Dein Ticket {0} wurde erstellt.
DC_TICKETINTRO_REPORT=Bitte beantworte für die Ahndung des Fehlverhaltens möglichst genau folgende Fragen und füge nach Möglichkeit Beweismaterial hinzu:\n - Welche(r) Spieler?\n - Auf welchem Server?\n - Zu welchem Zeitpunkt?\n - Art und Natur des Fehlverhaltens?
DC_TICKETINTRO_IDEA=Beschreibe deine Idee möglichst detailiert. Hierzu gehört: Was, Warum, Wie, Wo?
DC_TICKETINTRO_BUG=Bitte beschreibe das beobachtete unerwartete bzw. inkorrekte Verhalten der Serversoftware. Falls notwendig, beschreibe die Schritte, mit denen der Fehler reproduziert werden kann.
DC_TICKETINTRO_QUESTION=Bitte stelle deine Frage, ein Serverteammitglied wird sich dieser zeitnah annehmen.
DC_TICKETINTRO_APPEAL=Fragen wirkt Wunder!
DC_TICKET_CLOSE=Schließen
DC_SCHEMUPLOAD_NOPERM=Du darfst keine Schematics hochladen.
DC_SCHEMUPLOAD_IGNORED=`{0}` wird ignoriert, da die Datei keine Schematic ist.
DC_SCHEMUPLOAD_INVCHAR=`{0}` hat unzulässige Buchstaben im Namen.
DC_SCHEMUPLOAD_SUCCESS=`{0}` wurde erfolgreich hochgeladen.
DC_SCHEMUPLOAD_ERROR=Ein Fehler ist beim Hochladen von `{0}` aufgetreten. Für nähere Informationen wende dich an einen Developer.

Datei anzeigen

@ -1,300 +0,0 @@
/*
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.messages;
import de.steamwar.bungeecore.*;
import de.steamwar.bungeecore.bot.listeners.DiscordChatListener;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.command.ConsoleCommandSender;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.function.BiConsumer;
import java.util.logging.Level;
import java.util.stream.Stream;
public interface ChatSender {
static Stream<ProxiedPlayer> all() {
return ProxyServer.getInstance().getPlayers().stream();
}
static Stream<ChatSender> allReceivers() {
return all().map(ChatSender::of);
}
static Stream<ChatSender> globalReceivers() {
return all().filter(player -> {
Subserver subserver = Subserver.getSubserver(player);
return subserver == null || !(subserver.getType() == Servertype.ARENA && subserver.getServer() == player.getServer().getInfo());
}).map(ChatSender::of);
}
static Stream<ChatSender> serverteamReceivers() {
return allReceivers().filter(player -> player.user().hasPerm(UserPerm.TEAM));
}
SteamwarUser user();
Locale getLocale();
boolean chatShown();
void sendMessage(ChatMessageType type, BaseComponent... msg);
default void chat(Message message) {
send(false, ChatMessageType.CHAT, null, null, message);
}
default void system(String format, Object... params) {
system(new Message(format, params));
}
default void system(Message message) {
send(true, ChatMessageType.SYSTEM, null, null, message);
}
default void system(String format, Message onHover, ClickEvent onClick, Object... params) {
send(true, ChatMessageType.SYSTEM, onHover, onClick, new Message(format, params));
}
default void prefixless(String format, Object... params) {
prefixless(format, null, null, params);
}
default void prefixless(String format, Message onHover, ClickEvent onClick, Object... params) {
send(false, ChatMessageType.SYSTEM, onHover, onClick, new Message(format, params));
}
default void send(boolean prefixed, ChatMessageType type, Message onHover, ClickEvent onClick, Message message) {
TextComponent msg = parseToComponent(prefixed, message);
if(onHover != null)
msg.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(parse(false, onHover))));
if(onClick != null)
msg.setClickEvent(onClick);
sendMessage(type, msg);
}
default TextComponent parseToComponent(boolean prefixed, Message message) {
return new TextComponent(parse(prefixed, message));
}
default String parseToPlain(String format, Object... params) {
return parseToPlain(new Message(format, params));
}
default String parseToPlain(Message message) {
return parseToComponent(false, message).toPlainText();
}
default String parseToLegacy(String format, Object... params) {
return parseToLegacy(new Message(format, params));
}
default String parseToLegacy(Message message) {
return parseToComponent(false, message).toLegacyText();
}
default BaseComponent[] parse(boolean prefixed, String format, Object... params) {
return parse(prefixed, new Message(format, params));
}
default BaseComponent[] parse(boolean prefixed, Message message) {
Locale locale = getLocale();
ResourceBundle resourceBundle = SteamwarResourceBundle.getResourceBundle(locale);
String pattern = "";
if(prefixed)
pattern = resourceBundle.getObject("PREFIX") + " ";
pattern += (String)resourceBundle.getObject(message.getFormat());
MessageFormat format = new MessageFormat(pattern, locale);
Object[] params = message.getParams();
for (int i = 0; i < params.length; i++) {
if(params[i] instanceof Message) {
params[i] = parseToLegacy((Message) params[i]);
} else if(params[i] instanceof Date) {
params[i] = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale).format((Date) params[i]);
} else if(params[i] instanceof SteamwarUser) {
params[i] = ((SteamwarUser) params[i]).getUserName();
} else if(params[i] instanceof ProxiedPlayer) {
params[i] = ((ProxiedPlayer) params[i]).getName();
} else if(params[i] instanceof ChatSender) {
params[i] = ((ChatSender) params[i]).user().getUserName();
}
}
return TextComponent.fromLegacyText(format.format(params));
}
static ChatSender ofProxiedPlayer(ProxiedPlayer player, BiConsumer<ChatMessageType, BaseComponent[]> sendMessage) {
return new ChatSender() {
@Override
public SteamwarUser user() {
return SteamwarUser.get(player.getUniqueId());
}
@Override
public Locale getLocale() {
return user().getLocale();
}
@Override
public boolean chatShown() {
return player.getChatMode() == ProxiedPlayer.ChatMode.SHOWN;
}
@Override
public void sendMessage(ChatMessageType type, BaseComponent... msg) {
sendMessage.accept(type, msg);
}
};
}
static ChatSender of(ProxiedPlayer player) {
return ofProxiedPlayer(player, player::sendMessage);
}
static ChatSender disconnect(ProxiedPlayer player) {
return ofProxiedPlayer(player, (type, msg) -> player.disconnect(msg));
}
static ChatSender of(CommandSender sender) {
if(sender instanceof ProxiedPlayer)
return of((ProxiedPlayer) sender);
//Console
return new ChatSender() {
@Override
public SteamwarUser user() {
return SteamwarUser.get(-1);
}
@Override
public Locale getLocale() {
return Locale.getDefault();
}
@Override
public boolean chatShown() {
return true;
}
@Override
public void sendMessage(ChatMessageType type, BaseComponent... msg) {
sender.sendMessage(msg);
}
};
}
static ChatSender console() {
return of(ConsoleCommandSender.getInstance());
}
static ChatSender of(LoginEvent event) {
return new ChatSender() {
@Override
public SteamwarUser user() {
return SteamwarUser.get(event.getConnection().getUniqueId());
}
@Override
public Locale getLocale() {
return Locale.getDefault();
}
@Override
public boolean chatShown() {
return false;
}
@Override
public void sendMessage(ChatMessageType type, BaseComponent... msg) {
event.setCancelReason(msg);
}
};
}
static ChatSender discordChannel(DiscordChatListener channel) {
return new ChatSender() {
@Override
public SteamwarUser user() {
return SteamwarUser.get(-1);
}
@Override
public Locale getLocale() {
return Locale.getDefault();
}
@Override
public boolean chatShown() {
return true;
}
@Override
public void sendMessage(ChatMessageType type, BaseComponent... msg) {
try {
channel.send("<t:" + (System.currentTimeMillis() / 1000) + "> " + new TextComponent(msg).toPlainText());
} catch (Exception e) {
BungeeCore.get().getLogger().log(Level.SEVERE, "Could not send chat message to discord", e);
}
}
};
}
static ChatSender of(net.dv8tion.jda.api.entities.Message message, SteamwarUser user) {
return new ChatSender() {
@Override
public SteamwarUser user() {
return user;
}
@Override
public Locale getLocale() {
return Locale.getDefault();
}
@Override
public boolean chatShown() {
return true;
}
@Override
public void sendMessage(ChatMessageType type, BaseComponent... msg) {
try {
message.delete().queue();
} catch (Exception e) {
BungeeCore.get().getLogger().log(Level.SEVERE, "Could not send chat reply to discord user", e);
}
}
};
}
}

Datei anzeigen

@ -0,0 +1,275 @@
/*
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.messages;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.proxy.Player;
import de.steamwar.persistent.Servertype;
import de.steamwar.persistent.Subserver;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
public interface Chatter {
static Stream<Player> allPlayers() {
return VelocityCore.getProxy().getAllPlayers().stream();
}
static Stream<Chatter> allStream() {
return Stream.concat(Stream.of(Chatter.console()), allPlayers().map(Chatter::of));
}
static ChatterGroup broadcast() {
return new ChatterGroup(allStream());
}
static ChatterGroup globalChat() {
return new ChatterGroup(Stream.concat(Stream.of(Chatter.console()), allPlayers().filter(player -> {
Subserver subserver = Subserver.getSubserver(player);
return subserver == null || !(subserver.getType() == Servertype.ARENA && subserver.getServer() == player.getCurrentServer().get().getServerInfo());
}).map(Chatter::of)));
}
static ChatterGroup serverteam() {
return new ChatterGroup(allStream().filter(player -> player.user().hasPerm(UserPerm.TEAM)));
}
SteamwarUser user();
Locale getLocale();
boolean chatShown();
void sendMessage(Component msg);
Player getPlayer();
default <T> T withPlayerOrOffline(Function<Player, T> withPlayer, Supplier<T> withOffline) {
Player player = getPlayer();
if(player == null)
return withOffline.get();
else
return withPlayer.apply(player);
}
default void withPlayerOrOffline(Consumer<Player> withPlayer, Runnable withOffline) {
Player player = getPlayer();
if(player == null)
withOffline.run();
else
withPlayer.accept(player);
}
default void withPlayer(Consumer<Player> function) {
withPlayerOrOffline(function, () -> {});
}
default void system(String format, Object... params) {
system(new Message(format, params));
}
default void system(Message message) {
send(true, null, null, message);
}
default void system(String format, Message onHover, ClickEvent onClick, Object... params) {
send(true, onHover, onClick, new Message(format, params));
}
default void prefixless(String format, Object... params) {
prefixless(format, null, null, params);
}
default void prefixless(String format, Message onHover, ClickEvent onClick, Object... params) {
send(false, onHover, onClick, new Message(format, params));
}
default void send(boolean prefixed, Message onHover, ClickEvent onClick, Message message) {
Component msg = parse(prefixed, message);
if(onHover != null)
msg = msg.hoverEvent(HoverEvent.showText(parse(false, onHover)));
if(onClick != null)
msg = msg.clickEvent(onClick);
sendMessage(msg);
}
default String parseToPlain(String format, Object... params) {
return parseToPlain(new Message(format, params));
}
default String parseToPlain(Message message) {
return PlainTextComponentSerializer.plainText().serialize(parse(message));
}
default String parseToLegacy(String format, Object... params) {
return parseToLegacy(new Message(format, params));
}
default String parseToLegacy(Message message) {
return LegacyComponentSerializer.legacySection().serialize(parse(message));
}
default Component parse(String format, Object... params) {
return parse(false, new Message(format, params));
}
default Component parse(Message message) {
return parse(false, message);
}
default Component parse(boolean prefixed, String format, Object... params) {
return parse(prefixed, new Message(format, params));
}
default Component parse(boolean prefixed, Message message) {
Locale locale = getLocale();
ResourceBundle resourceBundle = SteamwarResourceBundle.getResourceBundle(locale);
String pattern = "";
if(prefixed)
pattern = resourceBundle.getObject("PREFIX") + " ";
pattern += (String)resourceBundle.getObject(message.format());
MessageFormat format = new MessageFormat(pattern, locale);
Object[] params = message.params();
for (int i = 0; i < params.length; i++) {
if(params[i] instanceof Message msg) {
params[i] = parseToLegacy(msg);
} else if(params[i] instanceof Date date) {
params[i] = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale).format(date);
} else if(params[i] instanceof SteamwarUser user) {
params[i] = user.getUserName();
} else if(params[i] instanceof Player player) {
params[i] = player.getUsername();
} else if(params[i] instanceof Chatter chatter) {
params[i] = chatter.user().getUserName();
} else if(params[i] instanceof Function func) {
params[i] = func.apply(this);
}
}
return LegacyComponentSerializer.legacySection().deserialize(format.format(params));
}
static PlayerChatter of(Player player) {
return new PlayerChatter(player, player::sendMessage);
}
static PlayerChatter disconnect(Player player) {
return new PlayerChatter(player, player::disconnect);
}
static Chatter of(CommandSource sender) {
if(sender instanceof Player player)
return of(player);
//Console
return new PlayerlessChatter() {
@Override
public SteamwarUser user() {
return SteamwarUser.get(-1);
}
@Override
public boolean chatShown() {
return true;
}
@Override
public void sendMessage(Component msg) {
sender.sendMessage(msg);
}
};
}
static Chatter of(SteamwarUser user) {
return of(user.getUUID());
}
static Chatter of(UUID uuid) {
Player player = VelocityCore.getProxy().getPlayer(uuid).orElse(null);
if(player != null)
return Chatter.of(player);
return new PlayerlessChatter() {
@Override
public SteamwarUser user() {
return SteamwarUser.get(uuid);
}
@Override
public boolean chatShown() {
return false;
}
@Override
public void sendMessage(Component msg) {
// Nowhere to send
}
};
}
static Chatter console() {
return of(VelocityCore.getProxy().getConsoleCommandSource());
}
static Chatter of(LoginEvent event) {
return new PlayerlessChatter() {
@Override
public SteamwarUser user() {
return SteamwarUser.get(event.getPlayer().getUniqueId());
}
@Override
public boolean chatShown() {
return false;
}
@Override
public void sendMessage(Component msg) {
event.setResult(ResultedEvent.ComponentResult.denied(msg));
}
};
}
abstract class PlayerlessChatter implements Chatter {
@Override
public Locale getLocale() {
return user().getLocale();
}
@Override
public Player getPlayer() {
return VelocityCore.getProxy().getPlayer(user().getUUID()).orElse(null);
}
}
}

Datei anzeigen

@ -0,0 +1,63 @@
/*
* 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.messages;
import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import java.util.Arrays;
import java.util.stream.Stream;
@Getter
public class ChatterGroup extends Chatter.PlayerlessChatter {
final Chatter[] chatters;
public ChatterGroup(Stream<Chatter> stream) {
chatters = stream.toArray(Chatter[]::new);
}
public ChatterGroup(Chatter... chatters) {
this.chatters = chatters;
}
@Override
public boolean chatShown() {
return Arrays.stream(chatters).allMatch(Chatter::chatShown);
}
@Override
public void send(boolean prefixed, Message onHover, ClickEvent onClick, Message message) {
for(Chatter sender : chatters)
sender.send(prefixed, onHover, onClick, message);
}
@Override
public SteamwarUser user() {
throw new UnsupportedOperationException();
}
@Override
public void sendMessage(Component msg) {
throw new UnsupportedOperationException();
}
}

Datei anzeigen

@ -0,0 +1,22 @@
/*
* 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.messages;
public record Message(String format, Object... params) { }

Datei anzeigen

@ -0,0 +1,64 @@
/*
* 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.messages;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.player.PlayerSettings;
import de.steamwar.sql.SteamwarUser;
import lombok.AllArgsConstructor;
import net.kyori.adventure.text.Component;
import java.util.Locale;
import java.util.function.Consumer;
@AllArgsConstructor
public class PlayerChatter implements Chatter {
private final Player player;
private final Consumer<Component> sendMessage;
@Override
public SteamwarUser user() {
return SteamwarUser.get(player.getUniqueId());
}
@Override
public Locale getLocale() {
return user().getLocale();
}
@Override
public boolean chatShown() {
if(!player.hasSentPlayerSettings())
return false;
return player.getPlayerSettings().getChatMode() == PlayerSettings.ChatMode.SHOWN;
}
@Override
public void sendMessage(Component msg) {
sendMessage.accept(msg);
}
@Override
public Player getPlayer() {
return player;
}
}

Datei anzeigen

@ -19,8 +19,6 @@
package de.steamwar.messages; package de.steamwar.messages;
import de.steamwar.bungeecore.Message;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.*;

Datei anzeigen

@ -19,7 +19,7 @@
package de.steamwar.sql; package de.steamwar.sql;
import de.steamwar.bungeecore.BungeeCore; import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.sql.internal.SQLConfig; import de.steamwar.sql.internal.SQLConfig;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -27,7 +27,7 @@ import java.util.logging.Logger;
public class SQLConfigImpl implements SQLConfig { public class SQLConfigImpl implements SQLConfig {
@Override @Override
public Logger getLogger() { public Logger getLogger() {
return BungeeCore.get().getLogger(); return VelocityCore.getLogger();
} }
@Override @Override

Datei anzeigen

@ -19,27 +19,19 @@
package de.steamwar.sql; package de.steamwar.sql;
import de.steamwar.bungeecore.BungeeCore; import com.velocitypowered.api.proxy.Player;
import de.steamwar.bungeecore.commands.CheckCommand; import com.velocitypowered.api.proxy.server.RegisteredServer;
import net.md_5.bungee.api.ProxyServer; import de.steamwar.velocitycore.GameModeConfig;
import net.md_5.bungee.api.config.ServerInfo; import de.steamwar.velocitycore.VelocityCore;
import net.md_5.bungee.api.connection.ProxiedPlayer; import de.steamwar.velocitycore.commands.CheckCommand;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
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");
private static Date parseDeadline(String deadline) { private static Date parseDeadline(String deadline) {
if(deadline == null) if(deadline == null)
@ -54,52 +46,36 @@ 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(BungeeCore.get().getDataFolder().getParentFile(), "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;
Configuration config;
try {
config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
} catch (IOException e) {
throw new SecurityException("Could not load SchematicTypes", e);
}
if(!config.contains("Schematic")) String shortcut = config.getSchematic().getShortcut();
continue; String material = config.getSchematic().getMaterial();
String type = config.getString("Schematic.Type"); SchematicType checktype = null;
assert type != null; if(!config.getCheckQuestions().isEmpty()) {
String shortcut = config.getString("Schematic.Shortcut"); checktype = new SchematicType("C" + config.getSchemType(), "C" + shortcut, SchematicType.Type.CHECK_TYPE, null, material, true);
if(tmpFromDB.containsKey(type.toLowerCase())) tmpTypes.add(checktype);
continue; tmpFromDB.put(checktype.toDB(), checktype);
CheckCommand.setCheckQuestions(checktype, config.getCheckQuestions());
SchematicType checktype = null;
String material = config.getString("Schematic.Material");
if(!config.getStringList("CheckQuestions").isEmpty()) {
checktype = new SchematicType("C" + type, "C" + shortcut, SchematicType.Type.CHECK_TYPE, null, material, true);
tmpTypes.add(checktype);
tmpFromDB.put(checktype.toDB(), checktype);
CheckCommand.setCheckQuestions(checktype, config);
}
boolean manualCheck = config.getBoolean("Schematic.ManualCheck", true);
SchematicType current = new SchematicType(type, shortcut, !config.contains("Server") ? SchematicType.Type.FIGHT_TYPE : SchematicType.Type.NORMAL, checktype, material, parseDeadline(config.getString("deadline", null)), manualCheck);
tmpTypes.add(current);
tmpFromDB.put(type.toLowerCase(), current);
if(checktype != null)
CheckCommand.addFightType(checktype, current);
} }
}
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);
tmpFromDB.put(config.getSchemType().toLowerCase(), current);
if(checktype != null)
CheckCommand.addFightType(checktype, current);
});
} }
@Override @Override
public void additionalExceptionMetadata(StringBuilder builder) { public void additionalExceptionMetadata(StringBuilder builder) {
builder.append("\nServers: "); builder.append("\nServers: ");
for(Map.Entry<String, ServerInfo> server : ProxyServer.getInstance().getServers().entrySet()) { for(RegisteredServer server : VelocityCore.getProxy().getAllServers()) {
builder.append(server.getKey()).append("("); builder.append(server.getServerInfo().getName()).append("(");
for(ProxiedPlayer player : server.getValue().getPlayers()) { for(Player player : server.getPlayersConnected()) {
builder.append(player.getName()).append(" "); builder.append(player.getUsername()).append(" ");
} }
builder.append(") "); builder.append(") ");
} }

Datei anzeigen

@ -0,0 +1,121 @@
/*
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.velocitycore;
import de.steamwar.sql.SchematicType;
import lombok.Getter;
import java.util.*;
public class ArenaMode extends GameModeConfig {
private static final Random random = new Random();
private static final Map<String, ArenaMode> byChat = new HashMap<>();
private static final Map<String, ArenaMode> byInternal = new HashMap<>();
private static final Map<SchematicType, ArenaMode> bySchemType = new HashMap<>();
@Getter
private static final List<ArenaMode> allModes = new LinkedList<>();
static {
init();
}
public static void init() {
byChat.clear();
byInternal.clear();
bySchemType.clear();
allModes.clear();
GameModeConfig.loadAll(ArenaMode.class, (file, mode) -> {
if(mode.getServer() == null)
return;
mode.config = file.getName();
mode.internalName = file.getName().replace(".yml", "");
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(mode.getSchematic() != null && mode.getSchemType() != null)
bySchemType.put(SchematicType.fromDB(mode.getSchemType()), mode);
});
}
public static ArenaMode getByChat(String name){
return byChat.get(name.toLowerCase());
}
public static ArenaMode getByInternal(String name){
return byInternal.get(name);
}
public static List<String> getAllChatNames(boolean historic) {
List<String> chatNames = new LinkedList<>();
for(ArenaMode mode : byInternal.values()){
if(historic == mode.isHistoric())
chatNames.addAll(mode.getServer().getChatNames());
}
return chatNames;
}
public static ArenaMode getBySchemType(SchematicType schemType){
return bySchemType.get(schemType);
}
private final Map<String, String> lowerToRealMapNames = new HashMap<>();
@Getter
private String internalName;
@Getter
private String config;
public String hasMap(String map){
for(String m : getMaps()) {
if(m.equalsIgnoreCase(map))
return m;
}
return null;
}
public String getRandomMap(){
return getMaps().get(random.nextInt(getMaps().size()));
}
public String convertToRealMapName(String map){
return lowerToRealMapNames.get(map.toLowerCase());
}
public String getChatName(){
return getServer().getChatNames().get(0);
}
public boolean withoutChatName(){
return getServer().getChatNames().isEmpty();
}
}

Datei anzeigen

@ -17,29 +17,28 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bungeecore; package de.steamwar.velocitycore;
import net.md_5.bungee.api.ProxyServer; import de.steamwar.messages.Chatter;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
class Broadcaster { class Broadcaster {
private static String [] broadCastMsgs; private final List<String> broadcasts = VelocityCore.get().getConfig().getBroadcasts();
private int lastBroadCast = 0; private int lastBroadCast = 0;
Broadcaster(){ Broadcaster() {
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> { if(!broadcasts.isEmpty())
if(!ProxyServer.getInstance().getPlayers().isEmpty() && broadCastMsgs.length > 0) VelocityCore.schedule(this::broadcast).repeat(10, TimeUnit.MINUTES).schedule();
BungeeCore.broadcast(BungeeCore.CHAT_PREFIX + broadCastMsgs[lastBroadCast]);
lastBroadCast++;
if(lastBroadCast == broadCastMsgs.length){
lastBroadCast = 0;
}
}, 10, 10, TimeUnit.MINUTES);
} }
static void setBroadCastMsgs(String[] broadCastMsgs) { private void broadcast() {
Broadcaster.broadCastMsgs = broadCastMsgs; if(!VelocityCore.getProxy().getAllPlayers().isEmpty())
Chatter.broadcast().system("PLAIN_STRING", broadcasts.get(lastBroadCast++));
if(lastBroadCast == broadcasts.size())
lastBroadCast = 0;
} }
} }

Datei anzeigen

@ -0,0 +1,88 @@
/*
* 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.velocitycore;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import lombok.Getter;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.BeanAccess;
import org.yaml.snakeyaml.representer.Representer;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@Getter
public class Config {
public static <T> T load(Class<T> clazz, File file, Consumer<TypeDescription> description) {
TypeDescription typeDescription = new TypeDescription(Config.class);
description.accept(typeDescription);
Constructor constructor = new Constructor(clazz, new LoaderOptions());
constructor.addTypeDescription(typeDescription);
Representer representer = new Representer();
representer.getPropertyUtils().setSkipMissingProperties(true);
Yaml yaml = new Yaml(constructor, representer);
yaml.setBeanAccess(BeanAccess.FIELD);
try{
return yaml.load(new FileInputStream(file));
}catch(IOException e){
VelocityCore.getProxy().shutdown();
throw new SecurityException("Could not load config", e);
}
}
public static Config load() {
return load(Config.class, new File(VelocityCore.get().getDataDirectory().toFile(), "config.yml"), description -> description.addPropertyParameters("servers", String.class, Config.Server.class));
}
private String lobbyserver;
private boolean eventmode = false;
private Map<String, Server> servers = Collections.emptyMap();
private List<String> broadcasts = Collections.emptyList();
private Poll poll = null;
public RegisteredServer lobbyserver() {
return VelocityCore.getProxy().getServer(lobbyserver).orElseThrow();
}
@Getter
public static class Poll {
private String question;
private List<String> answers;
}
@Getter
public static class Server {
private int spectatePort = 0;
private List<String> commands;
}
}

Datei anzeigen

@ -17,77 +17,66 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bungeecore; package de.steamwar.velocitycore;
import de.steamwar.sql.SWException; import de.steamwar.sql.SWException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
import org.apache.logging.log4j.core.config.Property;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
public class ErrorLogger extends Handler { public class ErrorLogger extends AbstractAppender {
ErrorLogger(){ ErrorLogger() {
Logger.getLogger("").addHandler(this); super("SW ErrorLogger", null, null, false, Property.EMPTY_ARRAY);
start();
LoggerContext context = (LoggerContext) LogManager.getContext(false);
context.getConfiguration().addAppender(this);
context.getRootLogger().addAppender(this);
context.updateLoggers();
} }
void unregister(){ void unregister() {
Logger.getLogger("").removeHandler(this); LoggerContext context = (LoggerContext) LogManager.getContext(false);
((AbstractConfiguration) context.getConfiguration()).removeAppender(getName());
context.getRootLogger().removeAppender(this);
context.updateLoggers();
} }
@Override @Override
public void publish(LogRecord logRecord) { public void append(LogEvent event) {
if(logRecord.getLevel().intValue() < Level.WARNING.intValue()) if(event.getLevel().isLessSpecificThan(Level.WARN))
return; return;
String message = logRecord.getParameters() != null ? MessageFormat.format(logRecord.getMessage(), logRecord.getParameters()) : logRecord.getMessage(); String message = event.getMessage().getFormattedMessage();
for(String reason : ignoreContains) for(String reason : ignoreContains)
if(message.contains(reason)) if(message.contains(reason))
return; return;
ByteArrayOutputStream stacktraceOutput = new ByteArrayOutputStream(); ByteArrayOutputStream stacktraceOutput = new ByteArrayOutputStream();
if(logRecord.getThrown() != null) if(event.getThrown() != null)
logRecord.getThrown().printStackTrace(new PrintStream(stacktraceOutput)); event.getThrown().printStackTrace(new PrintStream(stacktraceOutput));
String stacktrace = stacktraceOutput.toString(); String stacktrace = stacktraceOutput.toString();
if (stacktrace.contains("ErrorLogger")) { if (stacktrace.contains("ErrorLogger"))
return; return;
}
SWException.log(message, stacktrace); SWException.log(message, stacktrace);
} }
@Override
public void flush() {
//ignored
}
@Override
public void close() {
//ignored
}
private static final List<String> ignoreContains; private static final List<String> ignoreContains;
static { static {
List<String> contains = new ArrayList<>(); List<String> contains = new ArrayList<>();
contains.add("Error authenticating ");
contains.add("read timed out");
contains.add("could not decode packet");
contains.add("Connection reset by peer");
contains.add("No client connected for pending server");
contains.add("Error occurred processing connection for");
contains.add("Server is online mode!");
contains.add(" took ");
contains.add("Could not translate packet ");
contains.add("455420");
ignoreContains = Collections.unmodifiableList(contains); ignoreContains = Collections.unmodifiableList(contains);
} }
} }

Datei anzeigen

@ -17,12 +17,13 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bungeecore; package de.steamwar.velocitycore;
import de.steamwar.messages.Chatter;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.EventFight; import de.steamwar.sql.EventFight;
import de.steamwar.sql.Team; import de.steamwar.sql.Team;
import net.md_5.bungee.api.ProxyServer; import net.kyori.adventure.text.event.ClickEvent;
import net.md_5.bungee.api.chat.ClickEvent;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.HashMap; import java.util.HashMap;
@ -30,7 +31,7 @@ import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static de.steamwar.bungeecore.Storage.eventServer; import static de.steamwar.persistent.Storage.eventServer;
public class EventStarter { public class EventStarter {
@ -42,7 +43,7 @@ public class EventStarter {
public EventStarter() { public EventStarter() {
EventFight.loadAllComingFights(); EventFight.loadAllComingFights();
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), this::run, 1, 10, TimeUnit.SECONDS); VelocityCore.schedule(this::run).delay(10, TimeUnit.SECONDS).schedule();
} }
public static Map<Integer, Subserver> getEventServer() { public static Map<Integer, Subserver> getEventServer() {
@ -59,7 +60,8 @@ public class EventStarter {
Team red = Team.get(next.getTeamRed()); Team red = Team.get(next.getTeamRed());
//Don't start EventServer if not the event bungee //Don't start EventServer if not the event bungee
if(BungeeCore.EVENT_MODE || next.getSpectatePort() == 0) { String command;
if(VelocityCore.get().getConfig().isEventmode() || next.getSpectatePort() == 0) {
ServerStarter starter = new ServerStarter().event(next); ServerStarter starter = new ServerStarter().event(next);
starter.callback(subserver -> { starter.callback(subserver -> {
@ -67,12 +69,11 @@ public class EventStarter {
eventServer.put(red.getTeamId(), subserver); eventServer.put(red.getTeamId(), subserver);
}).start(); }).start();
Message.broadcast("EVENT_FIGHT_BROADCAST", "EVENT_FIGHT_BROADCAST_HOVER", command = "/event " + blue.getTeamKuerzel();
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/event " + blue.getTeamKuerzel()), blue.getTeamColor(), blue.getTeamName(), red.getTeamColor(), red.getTeamName());
} else { } else {
Message.broadcast("EVENT_FIGHT_BROADCAST", "EVENT_FIGHT_BROADCAST_HOVER", command = "/" + spectatePorts.get(next.getSpectatePort());
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + spectatePorts.get(next.getSpectatePort())), blue.getTeamColor(), blue.getTeamName(), red.getTeamColor(), red.getTeamName());
} }
Chatter.broadcast().system("EVENT_FIGHT_BROADCAST", "EVENT_FIGHT_BROADCAST_HOVER", ClickEvent.runCommand(command), blue.getTeamColor(), blue.getTeamName(), red.getTeamColor(), red.getTeamName());
} }
} }

Datei anzeigen

@ -0,0 +1,97 @@
/*
* 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.velocitycore;
import lombok.Getter;
import lombok.Setter;
import java.io.File;
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;
for(File file : Arrays.stream(folder.listFiles((file, name) -> name.endsWith(".yml") && !name.endsWith(".kits.yml"))).sorted().toList()) {
consumer.accept(file, Config.load(config, file, description -> {}));
/*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();
}
}

Datei anzeigen

@ -17,12 +17,12 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bungeecore; package de.steamwar.velocitycore;
import net.md_5.bungee.BungeeCord; import java.io.BufferedReader;
import net.md_5.bungee.api.ProxyServer; import java.io.File;
import java.io.IOException;
import java.io.*; import java.io.InputStreamReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -36,7 +36,7 @@ public abstract class Node {
"-XX:+EnableCRIUSupport", "-XX:-CRIURestoreNonPortableMode", "-XX:+EnableCRIUSupport", "-XX:-CRIURestoreNonPortableMode",
"-Xgc:excessiveGCratio=80", "-Xdisableexplicitgc", "-Xnoclassgc", "-Xmos128M", "-Xmns48M", "-XX:+ExitOnOutOfMemoryError", // initial heap half values of memory observed by 1.19 spectate server "-Xgc:excessiveGCratio=80", "-Xdisableexplicitgc", "-Xnoclassgc", "-Xmos128M", "-Xmns48M", "-XX:+ExitOnOutOfMemoryError", // initial heap half values of memory observed by 1.19 spectate server
"-Xsyslog:none", "-Xtrace:none", "-Xverify:none", "-Xdump:system:none", "-Xdump:jit:none", "-Xdump:snap:none", "-Xsyslog:none", "-Xtrace:none", "-Xverify:none", "-Xdump:system:none", "-Xdump:jit:none", "-Xdump:snap:none",
"-Dlog4j.configurationFile=log4j2.xml" "-XX:+EnableDynamicAgentLoading", "-Dlog4j.configurationFile=log4j2.xml"
); );
private static final Set<String> JAVA_8 = new HashSet<>(); private static final Set<String> JAVA_8 = new HashSet<>();
static { static {
@ -74,7 +74,7 @@ public abstract class Node {
protected Node(String hostname) { protected Node(String hostname) {
this.hostname = hostname; this.hostname = hostname;
nodes.add(this); nodes.add(this);
BungeeCord.getInstance().getScheduler().schedule(BungeeCore.get(), this::calcLoadLimit, 1, 2, TimeUnit.SECONDS); VelocityCore.schedule(this::calcLoadLimit).repeat(2, TimeUnit.SECONDS).schedule();
} }
public void execute(String... command) { public void execute(String... command) {
@ -83,7 +83,7 @@ public abstract class Node {
} catch (IOException e) { } catch (IOException e) {
throw new SecurityException("Could not execute command", e); throw new SecurityException("Could not execute command", e);
} catch (InterruptedException e) { } catch (InterruptedException e) {
ProxyServer.getInstance().getLogger().log(Level.SEVERE, "Interrupted during execution", e); VelocityCore.getLogger().log(Level.SEVERE, "Interrupted during execution", e);
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }
@ -155,7 +155,7 @@ public abstract class Node {
try (BufferedReader meminfo = new BufferedReader(new InputStreamReader(Files.newInputStream(MEMINFO.toPath())))) { try (BufferedReader meminfo = new BufferedReader(new InputStreamReader(Files.newInputStream(MEMINFO.toPath())))) {
calcLoadLimit(meminfo); calcLoadLimit(meminfo);
} catch (IOException e) { } catch (IOException e) {
BungeeCore.get().getLogger().log(Level.SEVERE, "Could not read local load", e); VelocityCore.getLogger().log(Level.SEVERE, "Could not read local load", e);
belowLoadLimit = false; belowLoadLimit = false;
} }
} }
@ -170,7 +170,7 @@ public abstract class Node {
public RemoteNode(String hostname) { public RemoteNode(String hostname) {
super(hostname); super(hostname);
BungeeCore.get().getLogger().log(Level.INFO, "Added node " + hostname); VelocityCore.getLogger().log(Level.INFO, "Added node {0}", hostname);
} }
@Override @Override
@ -207,7 +207,7 @@ public abstract class Node {
} }
} catch (IOException e) { } catch (IOException e) {
if(belowLoadLimit) if(belowLoadLimit)
BungeeCore.get().getLogger().log(Level.SEVERE, "Could read remote load", e); VelocityCore.getLogger().log(Level.SEVERE, "Could read remote load", e);
belowLoadLimit = false; belowLoadLimit = false;
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();

Datei anzeigen

@ -1,14 +1,35 @@
package de.steamwar.bungeecore; /*
* 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/>.
*/
import de.steamwar.messages.ChatSender; package de.steamwar.velocitycore;
import com.velocitypowered.api.proxy.Player;
import de.steamwar.messages.Chatter;
import de.steamwar.persistent.Arenaserver;
import de.steamwar.persistent.Bauserver;
import de.steamwar.persistent.Builderserver;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.*; import de.steamwar.sql.*;
import lombok.Getter;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.file.Files; import java.nio.file.Files;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
@ -19,10 +40,10 @@ import java.util.stream.Collectors;
public class ServerStarter { public class ServerStarter {
private static final Portrange BAU_PORTS = BungeeCore.MAIN_SERVER ? new Portrange(10100, 20000) : new Portrange(2100, 2200); private static final Portrange BAU_PORTS = VelocityCore.MAIN_SERVER ? new Portrange(10100, 20000) : new Portrange(2100, 2200);
private static final Portrange ARENA_PORTS = BungeeCore.MAIN_SERVER ? new Portrange(3000, 3100) : (BungeeCore.EVENT_MODE ? new Portrange(4000, 5000) : BAU_PORTS); private static final Portrange ARENA_PORTS = VelocityCore.MAIN_SERVER ? new Portrange(3000, 3100) : (VelocityCore.get().getConfig().isEventmode() ? new Portrange(4000, 5000) : BAU_PORTS);
private static final String SERVER_PATH = "/servers/"; public static final String SERVER_PATH = "/servers/";
private static final String USER_HOME = System.getProperty("user.home") + "/"; private static final String USER_HOME = System.getProperty("user.home") + "/";
private static final String EVENT_PATH = USER_HOME + "event/"; private static final String EVENT_PATH = USER_HOME + "event/";
public static final String TEMP_WORLD_PATH = USER_HOME + "arenaserver/"; public static final String TEMP_WORLD_PATH = USER_HOME + "arenaserver/";
@ -50,13 +71,13 @@ public class ServerStarter {
private ServerConstructor constructor = (serverName, port, builder, shutdownCallback, failureCallback) -> new Arenaserver(serverName, gameMode, fightMap, allowMerge, port, builder, shutdownCallback); private ServerConstructor constructor = (serverName, port, builder, shutdownCallback, failureCallback) -> new Arenaserver(serverName, gameMode, fightMap, allowMerge, port, builder, shutdownCallback);
private Consumer<Subserver> callback = subserver -> {}; private Consumer<Subserver> callback = subserver -> {};
private final Set<ProxiedPlayer> playersToSend = new HashSet<>(); private final Set<Player> playersToSend = new HashSet<>();
private final Map<String, String> arguments = new HashMap<>(); private final Map<String, String> arguments = new HashMap<>();
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.serverJar(); serverJar = mode.getServerJar();
allowMerge = true; allowMerge = true;
fightMap = map; fightMap = map;
gameMode = mode.getInternalName(); gameMode = mode.getInternalName();
@ -68,7 +89,7 @@ public class ServerStarter {
public ServerStarter event(EventFight eventFight) { public ServerStarter event(EventFight eventFight) {
arena(ArenaMode.getByInternal(eventFight.getSpielmodus()), eventFight.getMap()); arena(ArenaMode.getByInternal(eventFight.getSpielmodus()), eventFight.getMap());
node = BungeeCore.local; node = VelocityCore.local;
worldDir = EVENT_PATH; worldDir = EVENT_PATH;
worldCleanup = () -> {}; worldCleanup = () -> {};
arguments.put("fightID", String.valueOf(eventFight.getFightID())); arguments.put("fightID", String.valueOf(eventFight.getFightID()));
@ -81,7 +102,7 @@ public class ServerStarter {
return this; return this;
} }
public ServerStarter test(ArenaMode mode, String map, ProxiedPlayer owner) { public ServerStarter test(ArenaMode mode, String map, Player owner) {
arena(mode, map); arena(mode, map);
buildWithTemp(owner); buildWithTemp(owner);
portrange = BAU_PORTS; portrange = BAU_PORTS;
@ -89,12 +110,12 @@ public class ServerStarter {
return send(owner); return send(owner);
} }
public ServerStarter blueLeader(ProxiedPlayer player) { public ServerStarter blueLeader(Player player) {
arguments.put("blueLeader", player.getUniqueId().toString()); arguments.put("blueLeader", player.getUniqueId().toString());
return send(player); return send(player);
} }
public ServerStarter redLeader(ProxiedPlayer player) { public ServerStarter redLeader(Player player) {
arguments.put("redLeader", player.getUniqueId().toString()); arguments.put("redLeader", player.getUniqueId().toString());
return send(player); return send(player);
} }
@ -114,11 +135,11 @@ public class ServerStarter {
return this; return this;
} }
public ServerStarter build(Version version, UUID owner) { public ServerStarter build(ServerVersion version, UUID owner) {
directory = version.getServerDirectory("Bau"); directory = version.getServerDirectory("Bau");
serverJar = version.getServerJar(); serverJar = version.getServerJar();
worldDir = version.getWorldFolder(WORLDS_BASE_PATH); worldDir = version.getWorldFolder(WORLDS_BASE_PATH);
worldName = version != Version.SPIGOT_12 ? String.valueOf(SteamwarUser.get(owner).getId()) : owner.toString(); worldName = version != ServerVersion.SPIGOT_12 ? String.valueOf(SteamwarUser.get(owner).getId()) : owner.toString();
checkpoint = true; checkpoint = true;
build(owner); build(owner);
@ -133,7 +154,7 @@ public class ServerStarter {
startCondition = () -> { startCondition = () -> {
Bauserver subserver = Bauserver.get(owner); Bauserver subserver = Bauserver.get(owner);
if(subserver != null) { if(subserver != null) {
for(ProxiedPlayer p : playersToSend) for(Player p : playersToSend)
SubserverSystem.sendPlayer(subserver, p); SubserverSystem.sendPlayer(subserver, p);
return false; return false;
} }
@ -143,8 +164,8 @@ public class ServerStarter {
return bauweltMember.isSupervisor(); return bauweltMember.isSupervisor();
}); });
if (!atLeastOneSupervisor) { if (!atLeastOneSupervisor) {
for (ProxiedPlayer p : playersToSend) { for (Player p : playersToSend) {
ChatSender.of(p).system("BAU_START_NOT_ALLOWED"); Chatter.of(p).system("BAU_START_NOT_ALLOWED");
} }
} }
return atLeastOneSupervisor; return atLeastOneSupervisor;
@ -153,7 +174,7 @@ public class ServerStarter {
return this; return this;
} }
public ServerStarter tutorial(ProxiedPlayer owner, Tutorial tutorial) { public ServerStarter tutorial(Player owner, Tutorial tutorial) {
directory = new File(SERVER_PATH, "Tutorial"); directory = new File(SERVER_PATH, "Tutorial");
buildWithTemp(owner); buildWithTemp(owner);
tempWorld(TUTORIAL_PATH + tutorial.getTutorialId()); tempWorld(TUTORIAL_PATH + tutorial.getTutorialId());
@ -167,7 +188,7 @@ public class ServerStarter {
worldCleanup = () -> SubserverSystem.deleteFolder(node, worldDir + worldName); worldCleanup = () -> SubserverSystem.deleteFolder(node, worldDir + worldName);
} }
private void buildWithTemp(ProxiedPlayer owner) { private void buildWithTemp(Player owner) {
build(owner.getUniqueId()); build(owner.getUniqueId());
// Stop existing build server // Stop existing build server
@ -188,7 +209,7 @@ public class ServerStarter {
serverNameProvider = port -> bauServerName(SteamwarUser.get(owner)); serverNameProvider = port -> bauServerName(SteamwarUser.get(owner));
} }
public ServerStarter builder(Version version, String map, File generator) { public ServerStarter builder(ServerVersion version, String map, File generator) {
serverJar = version.getServerJar(); serverJar = version.getServerJar();
directory = version.getServerDirectory("Builder"); directory = version.getServerDirectory("Builder");
worldDir = version.getWorldFolder(BUILDER_BASE_PATH); worldDir = version.getWorldFolder(BUILDER_BASE_PATH);
@ -201,7 +222,7 @@ public class ServerStarter {
startCondition = () -> { startCondition = () -> {
Builderserver subserver = Builderserver.get(worldName); Builderserver subserver = Builderserver.get(worldName);
if (subserver != null) { if (subserver != null) {
for(ProxiedPlayer p : playersToSend) for(Player p : playersToSend)
SubserverSystem.sendPlayer(subserver, p); SubserverSystem.sendPlayer(subserver, p);
return false; return false;
} }
@ -222,7 +243,7 @@ public class ServerStarter {
return this; return this;
} }
public ServerStarter send(ProxiedPlayer player) { public ServerStarter send(Player player) {
playersToSend.add(player); playersToSend.add(player);
return this; return this;
} }
@ -242,8 +263,8 @@ public class ServerStarter {
if(node == null) { if(node == null) {
node = Node.getNode(); node = Node.getNode();
if(node == null) { if(node == null) {
for (ProxiedPlayer p : playersToSend) for (Player p : playersToSend)
ChatSender.of(p).system("SERVER_START_OVERLOAD"); Chatter.of(p).system("SERVER_START_OVERLOAD");
return false; return false;
} }
@ -259,8 +280,8 @@ public class ServerStarter {
arguments.put("checkpoint", checkpointDir.getPath()); arguments.put("checkpoint", checkpointDir.getPath());
if(checkpoint && checkpointDir.exists()) { if(checkpoint && checkpointDir.exists()) {
try { try(DataOutputStream out = new DataOutputStream(Files.newOutputStream(new File(checkpointDir, "port").toPath()))) {
new DataOutputStream(Files.newOutputStream(new File(checkpointDir, "port").toPath())).writeInt(port); out.writeInt(port);
} catch (IOException e) { } catch (IOException e) {
throw new SecurityException(e); throw new SecurityException(e);
} }
@ -282,16 +303,16 @@ public class ServerStarter {
} }
private void postStart(Subserver subserver) { private void postStart(Subserver subserver) {
for(ProxiedPlayer p : playersToSend) for(Player p : playersToSend)
SubserverSystem.sendPlayer(subserver, p); SubserverSystem.sendPlayer(subserver, p);
callback.accept(subserver); callback.accept(subserver);
} }
private static boolean startingBau(ProxiedPlayer p) { private static boolean startingBau(Player p) {
Bauserver subserver = Bauserver.get(p.getUniqueId()); Bauserver subserver = Bauserver.get(p.getUniqueId());
if(subserver != null && !subserver.isStarted()) { if(subserver != null && !subserver.isStarted()) {
ChatSender.of(p).system("BAU_START_ALREADY"); Chatter.of(p).system("BAU_START_ALREADY");
return true; return true;
} }
return false; return false;
@ -336,7 +357,7 @@ public class ServerStarter {
Set<Integer> usedPorts; Set<Integer> usedPorts;
synchronized (Subserver.getServerList()) { synchronized (Subserver.getServerList()) {
usedPorts = Subserver.getServerList().stream().map(server -> ((InetSocketAddress) server.getServer().getSocketAddress()).getPort()).collect(Collectors.toSet()); usedPorts = Subserver.getServerList().stream().map(server -> server.getServer().getAddress().getPort()).collect(Collectors.toSet());
} }
while(usedPorts.contains(current)) { while(usedPorts.contains(current)) {
@ -349,27 +370,4 @@ public class ServerStarter {
} }
} }
@Getter
public enum Version {
SPIGOT_12("spigot-1.12.2.jar", 12),
SPIGOT_15("spigot-1.15.2.jar", 15),
PAPER_19("paper-1.19.3.jar", 19),
PAPER_20("paper-1.20.1.jar", 20);
private final String serverJar;
private final int versionSuffix;
Version(String serverJar, int versionSuffix) {
this.serverJar = serverJar;
this.versionSuffix = versionSuffix;
}
public String getWorldFolder(String base) {
return base + versionSuffix + "/";
}
public File getServerDirectory(String base) {
return new File(SERVER_PATH, base + versionSuffix);
}
}
} }

Datei anzeigen

@ -0,0 +1,87 @@
/*
* 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.velocitycore;
import lombok.Getter;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@Getter
public enum ServerVersion {
SPIGOT_12("spigot-1.12.2.jar", 12),
SPIGOT_15("spigot-1.15.2.jar", 15),
PAPER_19("paper-1.19.3.jar", 19),
PAPER_20("paper-1.20.1.jar", 20);
private static final Map<String, ServerVersion> chatMap = new HashMap<>();
static {
chatMap.put("20", ServerVersion.PAPER_20);
chatMap.put("1.20", ServerVersion.PAPER_20);
chatMap.put("1.20.1", ServerVersion.PAPER_20);
chatMap.put("as", ServerVersion.PAPER_20);
chatMap.put("airship", ServerVersion.PAPER_20);
chatMap.put("wg", ServerVersion.PAPER_20);
chatMap.put("wargear", ServerVersion.PAPER_20);
chatMap.put("ws", ServerVersion.PAPER_20);
chatMap.put("warship", ServerVersion.PAPER_20);
chatMap.put("mwg", ServerVersion.PAPER_20);
chatMap.put("miniwargear", ServerVersion.PAPER_20);
chatMap.put("19", ServerVersion.PAPER_19);
chatMap.put("1.19", ServerVersion.PAPER_19);
chatMap.put("1.19.2", ServerVersion.PAPER_19);
chatMap.put("15", ServerVersion.SPIGOT_15);
chatMap.put("1.15", ServerVersion.SPIGOT_15);
chatMap.put("1.15.2", ServerVersion.SPIGOT_15);
chatMap.put("12", ServerVersion.SPIGOT_12);
chatMap.put("1.12", ServerVersion.SPIGOT_12);
chatMap.put("1.12.2", ServerVersion.SPIGOT_12);
}
public static ServerVersion get(String chat) {
return chatMap.get(chat.toLowerCase());
}
public static Set<String> chatVersions() {
return chatMap.keySet();
}
private final String serverJar;
private final int versionSuffix;
ServerVersion(String serverJar, int versionSuffix) {
this.serverJar = serverJar;
this.versionSuffix = versionSuffix;
}
public String getWorldFolder(String base) {
return base + versionSuffix + "/";
}
public File getServerDirectory(String base) {
return new File(ServerStarter.SERVER_PATH, base + versionSuffix);
}
}

Datei anzeigen

@ -17,16 +17,18 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bungeecore; package de.steamwar.velocitycore;
import de.steamwar.bungeecore.network.NetworkSender; import com.velocitypowered.api.proxy.Player;
import de.steamwar.bungeecore.network.handlers.FightInfoHandler; import de.steamwar.velocitycore.network.NetworkSender;
import de.steamwar.velocitycore.network.handlers.FightInfoHandler;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
import de.steamwar.network.packets.server.StartingServerPacket;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.IgnoreSystem; import de.steamwar.sql.IgnoreSystem;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.network.packets.server.StartingServerPacket; import net.kyori.adventure.text.event.ClickEvent;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID; import java.util.UUID;
@ -37,23 +39,20 @@ public class SubserverSystem {
node.execute("rm", "-r", worldName); node.execute("rm", "-r", worldName);
} }
public static void sendDeniedMessage(ProxiedPlayer p, UUID owner){ public static void sendDeniedMessage(Chatter p, UUID owner) {
ProxiedPlayer o = ProxyServer.getInstance().getPlayer(owner); if(IgnoreSystem.isIgnored(owner, p.user().getUUID())){
if(o == null) p.system("SERVER_IGNORED");
return;
if(IgnoreSystem.isIgnored(owner, p.getUniqueId())){
Message.send("SERVER_IGNORED", p);
return; return;
} }
Message.send("SERVER_ADD_MEMBER", o, p.getName()); Chatter o = Chatter.of(owner);
Message.sendPrefixless("SERVER_ADD_MESSAGE", o, Message.parse("SERVER_ADD_MESSAGE_HOVER", o, p.getName()), o.system("SERVER_ADD_MEMBER", p);
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/bau addmember " + p.getName())); o.prefixless("SERVER_ADD_MESSAGE", new Message("SERVER_ADD_MESSAGE_HOVER"), ClickEvent.runCommand("/bau addmember " + p.user().getUserName()));
} }
public static void sendPlayer(Subserver subserver, ProxiedPlayer player) { public static void sendPlayer(Subserver subserver, Player player) {
subserver.sendPlayer(player); subserver.sendPlayer(player);
if(!subserver.hasStarted() && FightInfoHandler.onLobby(player)) if(!subserver.isStarted() && FightInfoHandler.onLobby(player))
NetworkSender.send(player, new StartingServerPacket(SteamwarUser.get(player.getUniqueId()).getId())); NetworkSender.send(player, new StartingServerPacket(SteamwarUser.get(player.getUniqueId()).getId()));
} }
} }

Datei anzeigen

@ -0,0 +1,282 @@
/*
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.velocitycore;
import com.google.inject.Inject;
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 com.velocitypowered.api.scheduler.Scheduler;
import de.steamwar.command.*;
import de.steamwar.messages.Chatter;
import de.steamwar.network.packets.PacketHandler;
import de.steamwar.persistent.ReloadablePlugin;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
import de.steamwar.sql.UserElo;
import de.steamwar.sql.internal.Statement;
import de.steamwar.velocitycore.commands.*;
import de.steamwar.velocitycore.discord.DiscordBot;
import de.steamwar.velocitycore.discord.DiscordConfig;
import de.steamwar.velocitycore.listeners.*;
import de.steamwar.velocitycore.mods.*;
import de.steamwar.velocitycore.network.handlers.*;
import de.steamwar.velocitycore.tablist.TablistManager;
import lombok.Getter;
import java.nio.file.Path;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
@Plugin(
id = "velocitycore",
name = "VelocityCore",
dependencies = { @Dependency(id = "persistentvelocitycore") }
)
public class VelocityCore implements ReloadablePlugin {
public static boolean MAIN_SERVER;
private static VelocityCore instance;
public static VelocityCore get() {
return instance;
}
public static Node local;
public static Scheduler.TaskBuilder schedule(Runnable runnable) {
return instance.proxyServer.getScheduler().buildTask(instance, runnable);
}
public static ProxyServer getProxy() {
return instance.proxyServer;
}
public static Logger getLogger() {
return instance.logger;
}
private final ProxyServer proxyServer;
private final Logger logger;
@Getter
private final Path dataDirectory;
private Driver sqlDriver;
@Getter
private Config config;
private ErrorLogger errorLogger;
private TablistManager tablistManager;
@Getter
private TeamCommand teamCommand;
@Inject
public VelocityCore(ProxyServer proxyServer, Logger logger, @DataDirectory Path dataDirectory) {
this.proxyServer = proxyServer;
this.logger = logger;
this.dataDirectory = dataDirectory;
}
@Subscribe
@Override
public void onProxyInitialization(ProxyInitializeEvent event) {
instance = this;
config = Config.load();
MAIN_SERVER = proxyServer.getBoundAddress().getPort() == 25565;
try {
sqlDriver = Statement.mysqlMode() ? new com.mysql.cj.jdbc.Driver() : new org.sqlite.JDBC();
DriverManager.registerDriver(sqlDriver);
} catch (SQLException e) {
throw new SecurityException(e);
}
errorLogger = new ErrorLogger();
SWCommandUtils.init((SWTypeMapperCreator<TypeMapper<Object>, Chatter, Object>) (mapper, tabCompleter) -> new TypeMapper<>() {
@Override
public Object map(Chatter sender, PreviousArguments previousArguments, String s) {
return mapper.apply(s);
}
@Override
public Collection<String> tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) {
return tabCompleter.apply(sender, s);
}
});
schedule(TabCompletionCache::invalidateOldEntries).repeat(1, TimeUnit.SECONDS).schedule();
initStaticServers();
PollSystem.init();
new Hostname();
new PluginMessage();
new Schematica();
new Badlion();
new FabricModSender();
new ReplayMod();
new FML2();
new ConnectionListener();
new ChatListener();
new BanListener();
new CheckListener();
new IPSanitizer();
local = new Node.LocalNode();
if(MAIN_SERVER) {
//new Node.RemoteNode("lx");
}
new TeamchatCommand();
new MsgCommand();
new RCommand();
new PingCommand();
new AlertCommand();
new KickCommand();
new JoinmeCommand();
new TpCommand();
HelpCommand helpCommand = new HelpCommand();
teamCommand = new TeamCommand();
new ServerTeamchatCommand();
new DevCommand();
new EventCommand();
new EventreloadCommand();
new EventRescheduleCommand();
new PollCommand();
new BugCommand();
new WhoisCommand();
new RulesCommand();
new IgnoreCommand();
new UnIgnoreCommand();
new PollresultCommand();
new ListCommand();
new StatCommand();
new VerifyCommand();
new GDPRQuery();
new PlaytimeCommand();
new ArenaCommand();
new RankCommand();
new LocalCommand();
new SetLocaleCommand();
new BuilderCloudCommand();
new CheckCommand();
new ModCommand();
// Punishment Commands:
new PunishmentCommand("ban", Punishment.PunishmentType.Ban);
new PunishmentCommand("mute", Punishment.PunishmentType.Mute);
new PunishmentCommand("noschemreceiving", Punishment.PunishmentType.NoSchemReceiving);
new PunishmentCommand("noschemsharing", Punishment.PunishmentType.NoSchemSharing);
new PunishmentCommand("noschemsubmitting", Punishment.PunishmentType.NoSchemSubmitting);
new PunishmentCommand("nodev", Punishment.PunishmentType.NoDevServer);
new PunishmentCommand("nofight", Punishment.PunishmentType.NoFightServer);
new PunishmentCommand("noteamserver", Punishment.PunishmentType.NoTeamServer);
new PunishmentCommand("note", Punishment.PunishmentType.Note);
if(!config.isEventmode()){
new BauCommand(helpCommand);
new WebpasswordCommand();
new FightCommand();
new ChallengeCommand();
new HistoricCommand();
new ReplayCommand();
new TutorialCommand();
new Broadcaster();
}else{
new EventModeListener();
}
for(PacketHandler handler : new PacketHandler[] {
new EloPlayerHandler(), new EloSchemHandler(), new ExecuteCommandHandler(), new FightInfoHandler(),
new ImALobbyHandler(), new InventoryCallbackHandler(), new PrepareSchemHandler()
})
handler.register();
new EventStarter();
new SessionManager();
tablistManager = new TablistManager();
new SettingsChangedListener();
schedule(() -> {
SteamwarUser.clear();
UserElo.clear();
Team.clear();
}).repeat(1, TimeUnit.HOURS).schedule();
DiscordConfig discordConfig = DiscordConfig.load();
if (discordConfig != null) {
try {
new DiscordBot(discordConfig);
} catch (Throwable e) {
logger.log(Level.SEVERE, "Could not initialize discord bot", e);
}
}
}
@Subscribe
@Override
public void onProxyShutdown(ProxyShutdownEvent event) {
try {
DiscordBot.withBot(bot -> bot.getJda().shutdown());
} catch (Throwable e) {
logger.log(Level.SEVERE, "Could not shutdown discord bot", e);
}
if(tablistManager != null)
tablistManager.disable();
errorLogger.unregister();
Statement.closeAll();
try {
DriverManager.deregisterDriver(sqlDriver);
} catch (SQLException e) {
throw new SecurityException(e);
}
}
private void initStaticServers() {
for (Map.Entry<String, Config.Server> entry : config.getServers().entrySet()) {
Config.Server server = entry.getValue();
List<String> cmds = server.getCommands();
String cmd = cmds.remove(0);
if(server.getSpectatePort() != 0)
EventStarter.addSpectateServer(server.getSpectatePort(), cmd);
new ServerSwitchCommand(cmd, entry.getKey(), cmds.toArray(new String[0]));
}
}
}

Datei anzeigen

@ -17,33 +17,30 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.bungeecore.commands; package de.steamwar.velocitycore.commands;
import de.steamwar.bungeecore.Message; import de.steamwar.velocitycore.discord.DiscordBot;
import de.steamwar.bungeecore.bot.SteamwarDiscordBot;
import de.steamwar.bungeecore.listeners.ConnectionListener;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.messages.ChatSender; import de.steamwar.messages.Chatter;
import net.md_5.bungee.api.ChatColor; import de.steamwar.sql.UserPerm;
import net.md_5.bungee.api.CommandSender;
public class AlertCommand extends SWCommand { public class AlertCommand extends SWCommand {
public AlertCommand() { public AlertCommand() {
super("alert", ConnectionListener.ALERT_PERMISSION, "broadcast", "bbc"); super("alert", UserPerm.MODERATION, "broadcast", "bbc");
} }
@Register(description = "USAGE_ALERT") @Register(description = "USAGE_ALERT")
public void broadcast(CommandSender sender, @OptionalValue("") @StaticValue("-discord") String sendToDiscord, String... message) { public void broadcast(Chatter sender, @OptionalValue("") @StaticValue("-discord") String sendToDiscord, String... message) {
if (message.length == 0) { if (message.length == 0) {
ChatSender.of(sender).system(new Message("USAGE_ALERT")); sender.system("USAGE_ALERT");
return; return;
} }
String s = String.join(" ", message); String s = String.join(" ", message);
Message.broadcast("ALERT", ChatColor.translateAlternateColorCodes('&', s)); Chatter.broadcast().system("ALERT", s.replace('&', '§'));
if ("-discord".equals(sendToDiscord) && SteamwarDiscordBot.instance() != null) {
SteamwarDiscordBot.instance().getAnnouncementListener().announce(s); if ("-discord".equals(sendToDiscord))
} DiscordBot.withBot(bot -> bot.getAnnouncementChannel().send(s));
} }
} }

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen