Merge pull request 'Velocity' (#516) from velocity into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #516
Dieser Commit ist enthalten in:
Commit
213bc3d319
55
Persistent/build.gradle
Normale Datei
55
Persistent/build.gradle
Normale Datei
@ -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'
|
||||||
|
}
|
37
Persistent/src/de/steamwar/persistent/Arenaserver.java
Normale Datei
37
Persistent/src/de/steamwar/persistent/Arenaserver.java
Normale Datei
@ -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;
|
||||||
|
}
|
||||||
|
}
|
60
Persistent/src/de/steamwar/persistent/Bauserver.java
Normale Datei
60
Persistent/src/de/steamwar/persistent/Bauserver.java
Normale Datei
@ -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();
|
||||||
|
}
|
||||||
|
}
|
59
Persistent/src/de/steamwar/persistent/Builderserver.java
Normale Datei
59
Persistent/src/de/steamwar/persistent/Builderserver.java
Normale Datei
@ -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();
|
||||||
|
}
|
||||||
|
}
|
203
Persistent/src/de/steamwar/persistent/Persistent.java
Normale Datei
203
Persistent/src/de/steamwar/persistent/Persistent.java
Normale Datei
@ -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();
|
||||||
|
}
|
||||||
|
}
|
75
Persistent/src/de/steamwar/persistent/Reflection.java
Normale Datei
75
Persistent/src/de/steamwar/persistent/Reflection.java
Normale Datei
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
Persistent/src/de/steamwar/persistent/ReloadablePlugin.java
Normale Datei
28
Persistent/src/de/steamwar/persistent/ReloadablePlugin.java
Normale Datei
@ -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) {}
|
||||||
|
}
|
26
Persistent/src/de/steamwar/persistent/Servertype.java
Normale Datei
26
Persistent/src/de/steamwar/persistent/Servertype.java
Normale Datei
@ -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
|
||||||
|
}
|
52
Persistent/src/de/steamwar/persistent/Storage.java
Normale Datei
52
Persistent/src/de/steamwar/persistent/Storage.java
Normale Datei
@ -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<>();
|
||||||
|
}
|
263
Persistent/src/de/steamwar/persistent/Subserver.java
Normale Datei
263
Persistent/src/de/steamwar/persistent/Subserver.java
Normale Datei
@ -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);
|
||||||
|
}
|
||||||
|
}
|
50
build.gradle
50
build.gradle
@ -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,8 +50,15 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
allprojects {
|
||||||
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
url 'https://repo.papermc.io/repository/maven-public/'
|
||||||
|
content {
|
||||||
|
includeGroup 'com.velocitypowered'
|
||||||
|
}
|
||||||
|
}
|
||||||
maven {
|
maven {
|
||||||
url 'https://m2.dv8tion.net/releases'
|
url 'https://m2.dv8tion.net/releases'
|
||||||
content {
|
content {
|
||||||
@ -69,30 +71,42 @@ repositories {
|
|||||||
includeGroup 'com.lunarclient'
|
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'
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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
|
||||||
|
@ -26,6 +26,7 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.name = 'BungeeCore'
|
rootProject.name = 'VelocityCore'
|
||||||
|
|
||||||
include 'CommonCore'
|
include 'CommonCore'
|
||||||
|
include 'Persistent'
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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()));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -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(", ")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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()));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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())));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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> {}
|
||||||
}
|
|
||||||
|
@ -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.
|
||||||
|
@ -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!
|
||||||
@ -652,3 +655,30 @@ 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.
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
275
src/de/steamwar/messages/Chatter.java
Normale Datei
275
src/de/steamwar/messages/Chatter.java
Normale Datei
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
src/de/steamwar/messages/ChatterGroup.java
Normale Datei
63
src/de/steamwar/messages/ChatterGroup.java
Normale Datei
@ -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();
|
||||||
|
}
|
||||||
|
}
|
22
src/de/steamwar/messages/Message.java
Normale Datei
22
src/de/steamwar/messages/Message.java
Normale Datei
@ -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) { }
|
64
src/de/steamwar/messages/PlayerChatter.java
Normale Datei
64
src/de/steamwar/messages/PlayerChatter.java
Normale Datei
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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.*;
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
|
||||||
assert type != null;
|
|
||||||
String shortcut = config.getString("Schematic.Shortcut");
|
|
||||||
if(tmpFromDB.containsKey(type.toLowerCase()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SchematicType checktype = null;
|
SchematicType checktype = null;
|
||||||
String material = config.getString("Schematic.Material");
|
if(!config.getCheckQuestions().isEmpty()) {
|
||||||
|
checktype = new SchematicType("C" + config.getSchemType(), "C" + shortcut, SchematicType.Type.CHECK_TYPE, null, material, true);
|
||||||
if(!config.getStringList("CheckQuestions").isEmpty()) {
|
|
||||||
checktype = new SchematicType("C" + type, "C" + shortcut, SchematicType.Type.CHECK_TYPE, null, material, true);
|
|
||||||
tmpTypes.add(checktype);
|
tmpTypes.add(checktype);
|
||||||
tmpFromDB.put(checktype.toDB(), checktype);
|
tmpFromDB.put(checktype.toDB(), checktype);
|
||||||
CheckCommand.setCheckQuestions(checktype, config);
|
CheckCommand.setCheckQuestions(checktype, config.getCheckQuestions());
|
||||||
}
|
}
|
||||||
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);
|
SchematicType current = new SchematicType(config.getSchemType(), shortcut, config.getServer() != null ? SchematicType.Type.FIGHT_TYPE : SchematicType.Type.NORMAL, checktype, material, parseDeadline(config.getDeadline()), config.getSchematic().isManualCheck());
|
||||||
tmpTypes.add(current);
|
tmpTypes.add(current);
|
||||||
tmpFromDB.put(type.toLowerCase(), current);
|
tmpFromDB.put(config.getSchemType().toLowerCase(), current);
|
||||||
if(checktype != null)
|
if(checktype != null)
|
||||||
CheckCommand.addFightType(checktype, current);
|
CheckCommand.addFightType(checktype, current);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
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(") ");
|
||||||
}
|
}
|
||||||
|
121
src/de/steamwar/velocitycore/ArenaMode.java
Normale Datei
121
src/de/steamwar/velocitycore/ArenaMode.java
Normale Datei
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
88
src/de/steamwar/velocitycore/Config.java
Normale Datei
88
src/de/steamwar/velocitycore/Config.java
Normale Datei
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
97
src/de/steamwar/velocitycore/GameModeConfig.java
Normale Datei
97
src/de/steamwar/velocitycore/GameModeConfig.java
Normale Datei
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
87
src/de/steamwar/velocitycore/ServerVersion.java
Normale Datei
87
src/de/steamwar/velocitycore/ServerVersion.java
Normale Datei
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
282
src/de/steamwar/velocitycore/VelocityCore.java
Normale Datei
282
src/de/steamwar/velocitycore/VelocityCore.java
Normale Datei
@ -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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
In neuem Issue referenzieren
Einen Benutzer sperren