diff --git a/src/de/steamwar/bungeecore/BungeeCore.java b/src/de/steamwar/bungeecore/BungeeCore.java
index 846dd5c..7b9d428 100644
--- a/src/de/steamwar/bungeecore/BungeeCore.java
+++ b/src/de/steamwar/bungeecore/BungeeCore.java
@@ -67,6 +67,7 @@ public class BungeeCore extends Plugin {
@Override
public void onEnable(){
getProxy().registerChannel("sw:bridge");
+ getProxy().registerChannel("fabricmodsender:mods");
setInstance(this);
loadConfig();
@@ -83,6 +84,7 @@ public class BungeeCore extends Plugin {
new ModLoaderBlocker();
new WorldDownloader();
new BrandListener();
+ new Fabric();
new Node.LocalNode();
//new Node.RemoteNode("lx");
@@ -102,7 +104,6 @@ public class BungeeCore extends Plugin {
new JoinmeCommand();
new TpCommand();
new HelpCommand();
- new DenyCommand("watchcat", "wc");
new TeamCommand();
new ServerTeamchatCommand();
new DevCommand();
@@ -116,7 +117,6 @@ public class BungeeCore extends Plugin {
new IgnoreCommand();
new UnIgnoreCommand();
new PollresultCommand();
- new ResourcereloadCommand();
new ListCommand();
new StatCommand();
new VerifyCommand();
diff --git a/src/de/steamwar/bungeecore/ServerStarter.java b/src/de/steamwar/bungeecore/ServerStarter.java
index 622b7a4..1128b7d 100644
--- a/src/de/steamwar/bungeecore/ServerStarter.java
+++ b/src/de/steamwar/bungeecore/ServerStarter.java
@@ -26,6 +26,7 @@ public class ServerStarter {
private static final String EVENT_PATH = BACKBONE + "event/";
public static final String TEMP_WORLD_PATH = BACKBONE + "arenaserver/";
public static final String TUTORIAL_PATH = BACKBONE + "tutorials/";
+ public static final String WORLDS18_PATH = BACKBONE + "userworlds18/";
private File directory = null;
private String worldDir = null;
@@ -46,7 +47,7 @@ public class ServerStarter {
public ServerStarter arena(ArenaMode mode, String map) {
portrange = ARENA_PORTS;
- serverNameProvider = port -> mode.getChatName() + (port - portrange.start);
+ serverNameProvider = port -> mode.getDisplayName() + (port - portrange.start);
serverJar = mode.serverJar();
directory = new File(SERVER_PATH, mode.getFolder());
arguments.put("config", mode.getConfig());
@@ -100,6 +101,15 @@ public class ServerStarter {
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) {
directory = new File(SERVER_PATH, "Bau15");
worldDir = BungeeCore.USERWORLDS15;
diff --git a/src/de/steamwar/bungeecore/commands/BauCommand.java b/src/de/steamwar/bungeecore/commands/BauCommand.java
index 5a58a73..93c4866 100644
--- a/src/de/steamwar/bungeecore/commands/BauCommand.java
+++ b/src/de/steamwar/bungeecore/commands/BauCommand.java
@@ -33,7 +33,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
public class BauCommand extends BasicCommand {
public BauCommand(){
- super("bau", null, "b", "gs");
+ super("bau", null, "b", "build", "gs");
}
@Override
@@ -44,58 +44,44 @@ public class BauCommand extends BasicCommand {
ProxiedPlayer p = (ProxiedPlayer) sender;
- if(args.length == 0){
- (bau15(p, args, 0) ? new ServerStarter().build15(p.getUniqueId()) : new ServerStarter().build12(p.getUniqueId())).send(p).start();
- return;
- }
-
- 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":
- addmember(p, args);
- break;
- case "tp":
- case "teleport":
- teleport(p, args);
- break;
- case "info":
- p.chat("/bauinfo");
- break;
- case "togglewe":
- togglewe(p, args);
- break;
- case "toggleworld":
- toggleworld(p, args);
- break;
- case "delmember":
- delmember(p, args);
- break;
- case "resetall":
- case "delete":
- delete(p, args);
- break;
- case "testarena":
- case "test":
- testarena(p, args);
- break;
- default:
- HelpCommand.sendBauHelp(p);
- }
+ versionSelector(p, args, 0,
+ () -> new ServerStarter().build18(p.getUniqueId()).send(p).start(),
+ () -> new ServerStarter().build15(p.getUniqueId()).send(p).start(),
+ () -> new ServerStarter().build12(p.getUniqueId()).send(p).start(),
+ () -> {
+ switch (args[0].toLowerCase()) {
+ case "addmember":
+ addmember(p, args);
+ break;
+ case "tp":
+ case "teleport":
+ teleport(p, args);
+ break;
+ case "info":
+ p.chat("/bauinfo");
+ break;
+ case "togglewe":
+ togglewe(p, args);
+ break;
+ case "toggleworld":
+ toggleworld(p, args);
+ break;
+ case "delmember":
+ delmember(p, args);
+ break;
+ case "resetall":
+ case "delete":
+ delete(p, args);
+ break;
+ case "testarena":
+ case "test":
+ testarena(p, args);
+ break;
+ default:
+ HelpCommand.sendBauHelp(p);
+ }
+ }
+ );
}
private static void addmember(ProxiedPlayer p, String[] args){
@@ -140,19 +126,31 @@ public class BauCommand extends BasicCommand {
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){
- if(args.length <= pos)
- return p.getPendingConnection().getVersion() > 340; // Version > 1.12.2
+ private static void versionSelector(ProxiedPlayer p, String[] args, int pos, Runnable run18, Runnable run15, Runnable run12, Runnable runElse) {
+ if(args.length <= pos) {
+ 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 "warship":
- case "12":
- case "1.12":
- return false;
case "as":
case "airship":
case "mwg":
@@ -161,9 +159,14 @@ public class BauCommand extends BasicCommand {
case "wargear":
case "15":
case "1.15":
- return true;
+ run15.run();
+ break;
+ case "12":
+ case "1.12":
+ run12.run();
+ break;
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){
+ 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));
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 ->
+ worldDeletion.run()
);
- inventory.addItem(0, new SWItem(Message.parse("BAU_DELETE_GUI_DELETE", p), 10), click -> {
- if(bau15(p, args, 1)){
- SteamwarUser user = SteamwarUser.get(p.getUniqueId());
- deleteWorld(p, BungeeCore.USERWORLDS15 + user.getId());
- }else{
- deleteWorld(p, BungeeCore.WORLD_FOLDER + p.getUniqueId().toString());
- }
- });
inventory.open();
}
diff --git a/src/de/steamwar/bungeecore/commands/DenyCommand.java b/src/de/steamwar/bungeecore/commands/DenyCommand.java
deleted file mode 100644
index b6738d8..0000000
--- a/src/de/steamwar/bungeecore/commands/DenyCommand.java
+++ /dev/null
@@ -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 .
-*/
-
-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);
- }
- }
-}
diff --git a/src/de/steamwar/bungeecore/commands/GDPRQuery.java b/src/de/steamwar/bungeecore/commands/GDPRQuery.java
index bb98fca..444a22c 100644
--- a/src/de/steamwar/bungeecore/commands/GDPRQuery.java
+++ b/src/de/steamwar/bungeecore/commands/GDPRQuery.java
@@ -60,7 +60,7 @@ public class GDPRQuery extends BasicCommand {
sqlCSV(user, out, bauweltMember, "BuildMember.csv");
sqlCSV(user, out, bauweltMembers, "BuildMembers.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, ignoredPlayers, "IgnoredPlayers.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 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 elo = new Statement("SELECT GameMode, Elo 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 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.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 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 = ?");
diff --git a/src/de/steamwar/bungeecore/commands/ResourcereloadCommand.java b/src/de/steamwar/bungeecore/commands/ResourcereloadCommand.java
deleted file mode 100644
index 0789c48..0000000
--- a/src/de/steamwar/bungeecore/commands/ResourcereloadCommand.java
+++ /dev/null
@@ -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 .
- */
-
-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();
- }
-}
diff --git a/src/de/steamwar/bungeecore/commands/TutorialCommand.java b/src/de/steamwar/bungeecore/commands/TutorialCommand.java
index 3a031e5..4f55742 100644
--- a/src/de/steamwar/bungeecore/commands/TutorialCommand.java
+++ b/src/de/steamwar/bungeecore/commands/TutorialCommand.java
@@ -129,7 +129,7 @@ public class TutorialCommand extends BasicCommand {
List lore = new ArrayList<>();
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)
lore.add(Message.parse("TUTORIAL_DELETE", player));
diff --git a/src/de/steamwar/bungeecore/listeners/mods/Fabric.java b/src/de/steamwar/bungeecore/listeners/mods/Fabric.java
new file mode 100644
index 0000000..90365cd
--- /dev/null
+++ b/src/de/steamwar/bungeecore/listeners/mods/Fabric.java
@@ -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 .
+*/
+
+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 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 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 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 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()));
+ }
+}
diff --git a/src/de/steamwar/bungeecore/sql/Mod.java b/src/de/steamwar/bungeecore/sql/Mod.java
index 9aad08b..dcd69ae 100644
--- a/src/de/steamwar/bungeecore/sql/Mod.java
+++ b/src/de/steamwar/bungeecore/sql/Mod.java
@@ -61,7 +61,8 @@ public class Mod {
public enum Platform{
FORGE(0),
- LABYMOD(1);
+ LABYMOD(1),
+ FABRIC(2);
Platform(int value){
this.value = value;
diff --git a/src/de/steamwar/bungeecore/sql/UserElo.java b/src/de/steamwar/bungeecore/sql/UserElo.java
index ca7e723..6740966 100644
--- a/src/de/steamwar/bungeecore/sql/UserElo.java
+++ b/src/de/steamwar/bungeecore/sql/UserElo.java
@@ -26,15 +26,16 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
public class UserElo {
private UserElo() {}
public static final int ELO_DEFAULT = 1000;
- private static final Map>> gameModeUserEloCache = new HashMap<>();
- private static final Map maxEloCache = new HashMap<>();
- private static final Map emblemCache = new HashMap<>();
+ private static final Map>> gameModeUserEloCache = new ConcurrentHashMap<>();
+ private static final Map maxEloCache = new ConcurrentHashMap<>();
+ private static final Map emblemCache = new ConcurrentHashMap<>();
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)");
diff --git a/src/de/steamwar/messages/BungeeCore.properties b/src/de/steamwar/messages/BungeeCore.properties
index 19226ef..d8b87bf 100644
--- a/src/de/steamwar/messages/BungeeCore.properties
+++ b/src/de/steamwar/messages/BungeeCore.properties
@@ -583,3 +583,8 @@ RANK_UNPLACED=§eunplatziert
RANK_PLACED=§e{0}§8. §7mit §e{1} §7Elo§8.
RANK_EMBLEM=§eEmblem§8: {0}
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!