Archiviert
1
0

Merge branch 'master' into april

Dieser Commit ist enthalten in:
YoyoNow 2022-04-01 09:08:57 +02:00
Commit 5874cfc30f
11 geänderte Dateien mit 249 neuen und 158 gelöschten Zeilen

Datei anzeigen

@ -67,6 +67,7 @@ public class BungeeCore extends Plugin {
@Override @Override
public void onEnable(){ public void onEnable(){
getProxy().registerChannel("sw:bridge"); getProxy().registerChannel("sw:bridge");
getProxy().registerChannel("fabricmodsender:mods");
setInstance(this); setInstance(this);
loadConfig(); loadConfig();
@ -83,6 +84,7 @@ public class BungeeCore extends Plugin {
new ModLoaderBlocker(); new ModLoaderBlocker();
new WorldDownloader(); new WorldDownloader();
new BrandListener(); new BrandListener();
new Fabric();
new Node.LocalNode(); new Node.LocalNode();
//new Node.RemoteNode("lx"); //new Node.RemoteNode("lx");
@ -102,7 +104,6 @@ public class BungeeCore extends Plugin {
new JoinmeCommand(); new JoinmeCommand();
new TpCommand(); new TpCommand();
new HelpCommand(); new HelpCommand();
new DenyCommand("watchcat", "wc");
new TeamCommand(); new TeamCommand();
new ServerTeamchatCommand(); new ServerTeamchatCommand();
new DevCommand(); new DevCommand();
@ -116,7 +117,6 @@ public class BungeeCore extends Plugin {
new IgnoreCommand(); new IgnoreCommand();
new UnIgnoreCommand(); new UnIgnoreCommand();
new PollresultCommand(); new PollresultCommand();
new ResourcereloadCommand();
new ListCommand(); new ListCommand();
new StatCommand(); new StatCommand();
new VerifyCommand(); new VerifyCommand();

Datei anzeigen

@ -26,6 +26,7 @@ public class ServerStarter {
private static final String EVENT_PATH = BACKBONE + "event/"; private static final String EVENT_PATH = BACKBONE + "event/";
public static final String TEMP_WORLD_PATH = BACKBONE + "arenaserver/"; public static final String TEMP_WORLD_PATH = BACKBONE + "arenaserver/";
public static final String TUTORIAL_PATH = BACKBONE + "tutorials/"; public static final String TUTORIAL_PATH = BACKBONE + "tutorials/";
public static final String WORLDS18_PATH = BACKBONE + "userworlds18/";
private File directory = null; private File directory = null;
private String worldDir = null; private String worldDir = null;
@ -46,7 +47,7 @@ public class ServerStarter {
public ServerStarter arena(ArenaMode mode, String map) { public ServerStarter arena(ArenaMode mode, String map) {
portrange = ARENA_PORTS; portrange = ARENA_PORTS;
serverNameProvider = port -> mode.getChatName() + (port - portrange.start); serverNameProvider = port -> mode.getDisplayName() + (port - portrange.start);
serverJar = mode.serverJar(); serverJar = mode.serverJar();
directory = new File(SERVER_PATH, mode.getFolder()); directory = new File(SERVER_PATH, mode.getFolder());
arguments.put("config", mode.getConfig()); arguments.put("config", mode.getConfig());
@ -100,6 +101,15 @@ public class ServerStarter {
return this; return this;
} }
public ServerStarter build18(UUID owner) {
directory = new File(SERVER_PATH, "Bau18");
serverJar = "paper-1.18.2.jar";
worldDir = WORLDS18_PATH;
worldName = String.valueOf(SteamwarUser.get(owner).getId());
buildWithWorld(owner, new File(directory, "Bauwelt").getPath());
return this;
}
public ServerStarter build15(UUID owner) { public ServerStarter build15(UUID owner) {
directory = new File(SERVER_PATH, "Bau15"); directory = new File(SERVER_PATH, "Bau15");
worldDir = BungeeCore.USERWORLDS15; worldDir = BungeeCore.USERWORLDS15;

Datei anzeigen

@ -33,7 +33,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
public class BauCommand extends BasicCommand { public class BauCommand extends BasicCommand {
public BauCommand(){ public BauCommand(){
super("bau", null, "b", "gs"); super("bau", null, "b", "build", "gs");
} }
@Override @Override
@ -44,28 +44,12 @@ public class BauCommand extends BasicCommand {
ProxiedPlayer p = (ProxiedPlayer) sender; ProxiedPlayer p = (ProxiedPlayer) sender;
if(args.length == 0){ versionSelector(p, args, 0,
(bau15(p, args, 0) ? new ServerStarter().build15(p.getUniqueId()) : new ServerStarter().build12(p.getUniqueId())).send(p).start(); () -> new ServerStarter().build18(p.getUniqueId()).send(p).start(),
return; () -> new ServerStarter().build15(p.getUniqueId()).send(p).start(),
} () -> new ServerStarter().build12(p.getUniqueId()).send(p).start(),
() -> {
switch(args[0].toLowerCase()){ switch (args[0].toLowerCase()) {
case "12":
case "1.12":
new ServerStarter().build12(p.getUniqueId()).send(p).start();
break;
case "ws":
case "warship":
case "as":
case "airship":
case "mwg":
case "miniwargear":
case "wg":
case "wargear":
case "15":
case "1.15":
new ServerStarter().build15(p.getUniqueId()).send(p).start();
break;
case "addmember": case "addmember":
addmember(p, args); addmember(p, args);
break; break;
@ -97,6 +81,8 @@ public class BauCommand extends BasicCommand {
HelpCommand.sendBauHelp(p); HelpCommand.sendBauHelp(p);
} }
} }
);
}
private static void addmember(ProxiedPlayer p, String[] args){ private static void addmember(ProxiedPlayer p, String[] args){
if (args.length == 1) { if (args.length == 1) {
@ -140,19 +126,31 @@ public class BauCommand extends BasicCommand {
return; return;
} }
(bau15(p, args, 2) ? new ServerStarter().build15(worldOwner.getUuid()) : new ServerStarter().build12(worldOwner.getUuid())).send(p).start(); versionSelector(p, args, 2,
() -> new ServerStarter().build18(worldOwner.getUuid()).send(p).start(),
() -> new ServerStarter().build15(worldOwner.getUuid()).send(p).start(),
() -> new ServerStarter().build12(worldOwner.getUuid()).send(p).start(),
() -> HelpCommand.sendBauHelp(p));
} }
private static boolean bau15(ProxiedPlayer p, String[] args, int pos){ private static void versionSelector(ProxiedPlayer p, String[] args, int pos, Runnable run18, Runnable run15, Runnable run12, Runnable runElse) {
if(args.length <= pos) if(args.length <= pos) {
return p.getPendingConnection().getVersion() > 340; // Version > 1.12.2 int version = p.getPendingConnection().getVersion();
if(version > 340) { // Version > 1.12.2
run15.run();
} else {
run12.run();
}
return;
}
switch(args[pos].toLowerCase()){ switch (args[pos].toLowerCase()) {
case "18":
case "1.18":
run18.run();
break;
case "ws": case "ws":
case "warship": case "warship":
case "12":
case "1.12":
return false;
case "as": case "as":
case "airship": case "airship":
case "mwg": case "mwg":
@ -161,9 +159,14 @@ public class BauCommand extends BasicCommand {
case "wargear": case "wargear":
case "15": case "15":
case "1.15": case "1.15":
return true; run15.run();
break;
case "12":
case "1.12":
run12.run();
break;
default: default:
return p.getPendingConnection().getVersion() > 340; // Version > 1.12.2 runElse.run();
} }
} }
@ -225,18 +228,22 @@ public class BauCommand extends BasicCommand {
} }
private static void delete(ProxiedPlayer p, String[] args){ private static void delete(ProxiedPlayer p, String[] args){
SteamwarUser user = SteamwarUser.get(p.getUniqueId());
versionSelector(p, args, 1,
() -> deleteConfirmation(p, () -> deleteWorld(p, ServerStarter.WORLDS18_PATH + user.getId())),
() -> deleteConfirmation(p, () -> deleteWorld(p, BungeeCore.USERWORLDS15 + user.getId())),
() -> deleteConfirmation(p, () -> deleteWorld(p, BungeeCore.WORLD_FOLDER + p.getUniqueId().toString())),
() -> HelpCommand.sendBauHelp(p));
}
private static void deleteConfirmation(ProxiedPlayer p, Runnable worldDeletion) {
SWInventory inventory = new SWInventory(p, 9, Message.parse("BAU_DELETE_GUI_NAME", p)); 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.addItem(8, new SWItem(Message.parse("BAU_DELETE_GUI_CANCEL", p), 1), click ->
inventory.close() inventory.close()
); );
inventory.addItem(0, new SWItem(Message.parse("BAU_DELETE_GUI_DELETE", p), 10), click -> { inventory.addItem(0, new SWItem(Message.parse("BAU_DELETE_GUI_DELETE", p), 10), click ->
if(bau15(p, args, 1)){ worldDeletion.run()
SteamwarUser user = SteamwarUser.get(p.getUniqueId()); );
deleteWorld(p, BungeeCore.USERWORLDS15 + user.getId());
}else{
deleteWorld(p, BungeeCore.WORLD_FOLDER + p.getUniqueId().toString());
}
});
inventory.open(); inventory.open();
} }

Datei anzeigen

@ -1,39 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.Message;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class DenyCommand extends BasicCommand {
public DenyCommand(String cmd, String ...aliases) {
super(cmd, "", aliases);
}
@Override
public void execute(CommandSender sender, String[] args) {
if(sender instanceof ProxiedPlayer){
ProxiedPlayer player = (ProxiedPlayer) sender;
Message.send("UNKNOWN_COMMAND", player);
}
}
}

Datei anzeigen

@ -60,7 +60,7 @@ public class GDPRQuery extends BasicCommand {
sqlCSV(user, out, bauweltMember, "BuildMember.csv"); sqlCSV(user, out, bauweltMember, "BuildMember.csv");
sqlCSV(user, out, bauweltMembers, "BuildMembers.csv"); sqlCSV(user, out, bauweltMembers, "BuildMembers.csv");
sqlCSV(user, out, checkedSchems, "SchematicChecksessions.csv"); sqlCSV(user, out, checkedSchems, "SchematicChecksessions.csv");
sqlCSV(user, out, elo, "Elo.csv"); sqlCSV(user, out, userElo, "UserElo.csv");
sqlCSV(user, out, fights, "Fights.csv"); sqlCSV(user, out, fights, "Fights.csv");
sqlCSV(user, out, ignoredPlayers, "IgnoredPlayers.csv"); sqlCSV(user, out, ignoredPlayers, "IgnoredPlayers.csv");
sqlCSV(user, out, ignoringPlayers, "IgnoringPlayers.csv"); sqlCSV(user, out, ignoringPlayers, "IgnoringPlayers.csv");
@ -88,8 +88,8 @@ public class GDPRQuery extends BasicCommand {
private static final Statement bauweltMember = new Statement("SELECT BauweltID AS Bauwelt, WorldEdit, World FROM BauweltMember WHERE MemberID = ?"); private static final Statement bauweltMember = new Statement("SELECT BauweltID AS Bauwelt, WorldEdit, World FROM BauweltMember WHERE MemberID = ?");
private static final Statement bauweltMembers = new Statement("SELECT u.UserName AS 'User', m.WorldEdit AS WorldEdit, m.World AS World FROM BauweltMember m INNER JOIN UserData u ON m.MemberID = u.id WHERE m.BauweltID = ?"); private static final Statement bauweltMembers = new Statement("SELECT u.UserName AS 'User', m.WorldEdit AS WorldEdit, m.World AS World FROM BauweltMember m INNER JOIN UserData u ON m.MemberID = u.id WHERE m.BauweltID = ?");
private static final Statement checkedSchems = new Statement("SELECT NodeName AS Schematic, StartTime, EndTime, DeclineReason AS Result FROM CheckedSchematic WHERE NodeOwner = ? ORDER BY StartTime ASC"); private static final Statement checkedSchems = new Statement("SELECT NodeName AS Schematic, StartTime, EndTime, DeclineReason AS Result FROM CheckedSchematic WHERE NodeOwner = ? ORDER BY StartTime ASC");
private static final Statement elo = new Statement("SELECT GameMode, Elo FROM Elo WHERE UserID = ?"); private static final Statement userElo = new Statement("SELECT GameMode, Elo, Season FROM Elo WHERE UserID = ?");
private static final Statement fights = new Statement("SELECT p.Team AS Team, p.Kit AS Kit, p.Kills AS Kills, p.IsOut AS Died, f.GameMode AS GameMode, f.Server AS Server, f.Arena AS Arena, f.StartTime AS StartTime, f.Duration AS Duration, (f.BlueLeader = p.UserID) AS IsBlueLeader, (f.RedLeader = p.UserID) AS IsRedLeader, f.Win AS Winner, f.WinCondition AS WinCondition FROM Fight f INNER JOIN FightPlayer p ON f.FightID = p.FightID WHERE p.UserID = ? ORDER BY StartTime ASC"); private static final Statement fights = new Statement("SELECT p.Team AS Team, p.Kit AS Kit, p.Kills AS Kills, p.IsOut AS Died, f.GameMode AS GameMode, f.Server AS Server, f.StartTime AS StartTime, f.Duration AS Duration, (f.BlueLeader = p.UserID) AS IsBlueLeader, (f.RedLeader = p.UserID) AS IsRedLeader, f.Win AS Winner, f.WinCondition AS WinCondition FROM Fight f INNER JOIN FightPlayer p ON f.FightID = p.FightID WHERE p.UserID = ? ORDER BY StartTime ASC");
private static final Statement ignoredPlayers = new Statement("SELECT u.UserName AS IgnoredPlayer FROM IgnoredPlayers i INNER JOIN UserData u ON i.Ignored = u.id WHERE Ignorer = ?"); private static final Statement ignoredPlayers = new Statement("SELECT u.UserName AS IgnoredPlayer FROM IgnoredPlayers i INNER JOIN UserData u ON i.Ignored = u.id WHERE Ignorer = ?");
private static final Statement ignoringPlayers = new Statement("SELECT Ignorer AS IgnoringPlayers FROM IgnoredPlayers WHERE Ignored = ?"); private static final Statement ignoringPlayers = new Statement("SELECT Ignorer AS IgnoringPlayers FROM IgnoredPlayers WHERE Ignored = ?");
private static final Statement schematicMember = new Statement("SELECT s.NodeName AS SchematicName, u.UserName AS SchematicOwner FROM NodeMember m INNER JOIN SchematicNode s ON m.NodeId = s.NodeId INNER JOIN UserData u ON s.NodeOwner = u.id WHERE m.UserId = ?"); private static final Statement schematicMember = new Statement("SELECT s.NodeName AS SchematicName, u.UserName AS SchematicOwner FROM NodeMember m INNER JOIN SchematicNode s ON m.NodeId = s.NodeId INNER JOIN UserData u ON s.NodeOwner = u.id WHERE m.UserId = ?");

Datei anzeigen

@ -1,36 +0,0 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2020 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.commands;
import net.md_5.bungee.api.CommandSender;
import java.util.ResourceBundle;
public class ResourcereloadCommand extends BasicCommand {
public ResourcereloadCommand() {
super("resourcereload", "bungeecore.softreload", "rr");
}
@Override
public void execute(CommandSender commandSender, String[] strings) {
ResourceBundle.clearCache();
}
}

Datei anzeigen

@ -129,7 +129,7 @@ public class TutorialCommand extends BasicCommand {
List<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
lore.add(Message.parse("TUTORIAL_BY", player, tutorial.creator().getUserName())); lore.add(Message.parse("TUTORIAL_BY", player, tutorial.creator().getUserName()));
lore.add(Message.parse("TUTORIAL_STARS", player, tutorial.stars())); lore.add(Message.parse("TUTORIAL_STARS", player, String.format("%.1f", tutorial.stars())));
if (personalHighlights) if (personalHighlights)
lore.add(Message.parse("TUTORIAL_DELETE", player)); lore.add(Message.parse("TUTORIAL_DELETE", player));

Datei anzeigen

@ -0,0 +1,142 @@
/*
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.mods;
import com.google.gson.*;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Storage;
import de.steamwar.bungeecore.listeners.BasicListener;
import de.steamwar.bungeecore.sql.Mod;
import de.steamwar.bungeecore.sql.Punishment;
import de.steamwar.bungeecore.sql.SteamwarUser;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.event.EventHandler;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.*;
import java.util.logging.Level;
public class Fabric extends BasicListener {
private final Set<String> neededMods = new HashSet<>();
{
neededMods.add("java");
neededMods.add("minecraft");
neededMods.add("fabricloader");
neededMods.add("steamwarmodsender");
}
@EventHandler
public void onPluginMessageEvent(PluginMessageEvent e){
if(!e.getTag().equals("fabricmodsender:mods"))
return;
if (!(e.getSender() instanceof ProxiedPlayer)) {
return;
}
ProxiedPlayer player = (ProxiedPlayer) e.getSender();
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
List<Mod> mods = new LinkedList<>();
byte[] data = e.getData();
Utils.VarInt varInt = Utils.readVarInt(data,0);
if(data.length != varInt.length + varInt.value) {
banPlayer(user,player);
return;
}
data = Arrays.copyOfRange(data,varInt.length, data.length);
String dataString;
try{
dataString = new String(data, StandardCharsets.UTF_8);
}catch (UnsupportedCharsetException exception) {
banPlayer(user, player);
return;
}
JsonArray array;
try {
array = new JsonParser().parse(dataString).getAsJsonArray();
}catch (JsonSyntaxException exception) {
banPlayer(user, player);
return;
}
for(JsonElement mod : array) {
mods.add(Mod.get(mod.getAsString(), Mod.Platform.FABRIC));
}
boolean isSorted = isSortedAlphabetically(mods);
if(!isSorted) {
banPlayer(user, player);
return;
}
if(!neededModsContained(mods)) {
banPlayer(user, player);
return;
}
if(Utils.handleMods(player,mods)) {
Storage.fabricPlayers.remove(player);
Message.send("MODIFICATION_CHECK_SUCCESS", player);
}
}
private boolean isSortedAlphabetically(List<Mod> mods) {
boolean isSorted = true;
for(int i = 0; i < mods.size() - 1; i++) {
if(mods.get(i).getModName().compareToIgnoreCase(mods.get(i + 1).getModName()) > 0) {
isSorted = false;
break;
}
}
return isSorted;
}
private boolean neededModsContained(List<Mod> mods) {
return mods.stream()
.map(Mod::getModName)
.filter(neededMods::contains)
.count() == neededMods.size();
}
public void banPlayer(SteamwarUser user, ProxiedPlayer player) {
user.punish(Punishment.PunishmentType.Ban,
Timestamp.from(Instant.now()),
Message.parse("MODIFICATION_BAN_MESSAGE", player, user.getUserName(), user.getId()),
0,
true);
BungeeCore.log(Level.SEVERE,Message.parse("MODIFICATION_BAN_LOG", player, user.getUserName()));
}
}

Datei anzeigen

@ -61,7 +61,8 @@ public class Mod {
public enum Platform{ public enum Platform{
FORGE(0), FORGE(0),
LABYMOD(1); LABYMOD(1),
FABRIC(2);
Platform(int value){ Platform(int value){
this.value = value; this.value = value;

Datei anzeigen

@ -26,15 +26,16 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
public class UserElo { public class UserElo {
private UserElo() {} private UserElo() {}
public static final int ELO_DEFAULT = 1000; public static final int ELO_DEFAULT = 1000;
private static final Map<String, Map<Integer, Optional<Integer>>> gameModeUserEloCache = new HashMap<>(); private static final Map<String, Map<Integer, Optional<Integer>>> gameModeUserEloCache = new ConcurrentHashMap<>();
private static final Map<String, Integer> maxEloCache = new HashMap<>(); private static final Map<String, Integer> maxEloCache = new ConcurrentHashMap<>();
private static final Map<Integer, String> emblemCache = new HashMap<>(); private static final Map<Integer, String> emblemCache = new ConcurrentHashMap<>();
private static final Statement elo = new Statement("SELECT Elo FROM UserElo WHERE UserID = ? AND GameMode = ? AND Season = ?"); private static final Statement elo = new Statement("SELECT Elo FROM UserElo WHERE UserID = ? AND GameMode = ? AND Season = ?");
private static final Statement setElo = new Statement("INSERT INTO UserElo (Season, GameMode, UserID, Elo) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE Elo = VALUES(Elo)"); private static final Statement setElo = new Statement("INSERT INTO UserElo (Season, GameMode, UserID, Elo) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE Elo = VALUES(Elo)");

Datei anzeigen

@ -583,3 +583,8 @@ RANK_UNPLACED=§eunplatziert
RANK_PLACED=§e{0}§8. §7mit §e{1} §7Elo§8. RANK_PLACED=§e{0}§8. §7mit §e{1} §7Elo§8.
RANK_EMBLEM=§eEmblem§8: {0} RANK_EMBLEM=§eEmblem§8: {0}
RANK_NEEDED_FIGHTS_LEFT={0} §8(§7noch §e{1}§7 Kämpfe nötig§8) RANK_NEEDED_FIGHTS_LEFT={0} §8(§7noch §e{1}§7 Kämpfe nötig§8)
#Fabric Mod Sender
MODIFICATION_BAN_MESSAGE=Du hast probiert den FabricModSender zu umgehen / zu modifizieren!
MODIFICATION_BAN_LOG={0} hat probiert den Fabric Mod Sender zu editieren / umzugehen!
MODIFICATION_CHECK_SUCCESS=§eDeine Mods wurden geprüft und du darfst nun auf Arenen joinen!