Archiviert
1
0

Merge branch 'master' into arena_merging_2.0

Dieser Commit ist enthalten in:
Chaoscaot 2022-04-16 16:13:18 +02:00
Commit c0f8f9274a
16 geänderte Dateien mit 201 neuen und 48 gelöschten Zeilen

Datei anzeigen

@ -20,6 +20,7 @@
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;
@ -32,6 +33,7 @@ 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 {
@ -49,16 +51,26 @@ public class DiscordTicketMessage {
builder.setTitle("Steamwar-Tickets");
builder.setColor(Color.RED);
List<Button> buttons = new ArrayList<>();
SteamwarDiscordBotConfig.TICKET_TYPES.forEach((s, discordTicketType) -> buttons.add(discordTicketType.toButton()));
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(ActionRow.of(buttons));
messageBuilder.setActionRows(buttons.stream().map(ActionRow::of).collect(Collectors.toList()));
if (message != null) {
message.editMessage(messageBuilder.build()).queue();
} else {
channel.sendMessage(messageBuilder.build()).queue();
}
}
private static <T> List<List<T>> chunked(List<T> list, int chunkSize) {
List<List<T>> chunks = new ArrayList<>();
for (int i = 0; i < list.size(); i += chunkSize) {
chunks.add(list.subList(i, Math.min(i + chunkSize, list.size())));
}
return chunks;
}
}

Datei anzeigen

@ -29,7 +29,6 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
@ -100,7 +99,6 @@ public class EventCommand extends BasicCommand {
Message.send("EVENT_USAGE", player);
List<EventFight> fights = EventFight.getEvent(currentEvent.getEventID());
Instant now = Instant.now();
Message.send("EVENT_CURRENT_EVENT", player, currentEvent.getEventName());
@ -111,7 +109,7 @@ public class EventCommand extends BasicCommand {
StringBuilder fline = new StringBuilder(Message.parse("EVENT_CURRENT_FIGHT", player, fight.getStartTime().toLocalDateTime().format(timeFormat), blue.getTeamColor(), blue.getTeamKuerzel(),
red.getTeamColor(), red.getTeamKuerzel()));
if(now.isAfter(fight.getStartTime().toInstant().plus(35, ChronoUnit.MINUTES))){
if(fight.hasFinished()){
switch(fight.getErgebnis()){
case 1:
fline.append(Message.parse("EVENT_CURRENT_FIGHT_WIN", player, blue.getTeamColor(), blue.getTeamKuerzel()));

Datei anzeigen

@ -92,7 +92,7 @@ public class PunishmentCommand {
public static Timestamp parseTime(CommandSender sender, String arg) {
if (arg.equalsIgnoreCase("perma")) {
return Timestamp.from(Instant.ofEpochSecond(946674800));
return Punishment.PERMA_TIME;
} else {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy_HH:mm");
try {

Datei anzeigen

@ -90,7 +90,8 @@ public class TpCommand extends BasicCommand {
return false;
// Check if player is allowed to join fights
if (Subserver.getSubserver(server).getType() == Servertype.ARENA) {
Subserver subserver = Subserver.getSubserver(server);
if (subserver != null && subserver.getType() == Servertype.ARENA) {
SteamwarUser steamwarUser = SteamwarUser.get(player);
if (steamwarUser.isPunishedWithMessage(player, Punishment.PunishmentType.NoFightServer)) {
return true;

Datei anzeigen

@ -23,18 +23,29 @@ import com.google.common.io.ByteArrayDataInput;
import de.steamwar.bungeecore.ArenaMode;
import de.steamwar.bungeecore.comms.SpigotHandler;
import de.steamwar.bungeecore.comms.packets.FightEndsPacket;
import de.steamwar.bungeecore.sql.SchemElo;
import de.steamwar.bungeecore.sql.SchematicNode;
import de.steamwar.bungeecore.sql.SchematicType;
import de.steamwar.bungeecore.sql.UserElo;
import de.steamwar.bungeecore.sql.*;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
public class FightEndsHandler implements SpigotHandler {
private Map<String, LinkedList<Game>> gameModeGames = new HashMap<>();
private int K = 20;
private long defaultFightRange = 1000 /* Milliseconds */ * 60 /* Seconds */ * 15L /* Minutes */;
private Map<String, Long> fightRanges = new HashMap<>();
private long defaultFightCount = 1;
private Map<String, Long> fightCounts = new HashMap<>();
{
fightRanges.put("miniwargear", 1000 /* Milliseconds */ * 60 /* Seconds */ * 30L /* Minutes */);
fightCounts.put("miniwargear", 3L);
}
@Override
public void handle(ByteArrayDataInput in, ServerInfo info) {
FightEndsPacket fightEndsPacket = new FightEndsPacket(in);
@ -66,6 +77,23 @@ public class FightEndsHandler implements SpigotHandler {
blueResult = 0;
}
// Die nächsten Zeilen filtern ein Fight innerhalb eines Teams nicht gewertet wird, bzw auch wenn nur Teile beider Teams im
// gleichen Team sind dieser ungewertet ist.
Set<Integer> teamsIds = fightEndsPacket.getBluePlayers().stream().map(SteamwarUser::get).map(SteamwarUser::getTeam).collect(Collectors.toSet());
for (int redPlayer : fightEndsPacket.getRedPlayers()) {
if (teamsIds.contains(SteamwarUser.get(redPlayer).getTeam())) {
return;
}
}
try {
if (teamComboExistedAlready(fightEndsPacket.getBluePlayers(), fightEndsPacket.getRedPlayers(), fightEndsPacket.getGameMode())) {
return;
}
} finally {
gameModeGames.computeIfAbsent(fightEndsPacket.getGameMode(), s -> new LinkedList<>()).add(new Game(fightEndsPacket.getBluePlayers(), fightEndsPacket.getRedPlayers()));
}
int blueSchemElo = SchemElo.getElo(fightEndsPacket.getBlueSchem());
int redSchemElo = SchemElo.getElo(fightEndsPacket.getRedSchem());
@ -77,14 +105,55 @@ public class FightEndsHandler implements SpigotHandler {
}
private void calculateEloOfTeam(int schemId, int eloSchemOwn, int eloSchemEnemy, int eloTeamOwn, int eloTeamEnemy, double result, List<Integer> players, String gameMode, boolean noPlayerRank) {
double winSchemExpectation = 1 / (1 + Math.pow(10, (eloSchemEnemy - eloSchemOwn) / 600f));
double winSchemExpectation = calsWinExpectation(eloSchemOwn, eloSchemEnemy);
SchemElo.setElo(schemId, (int) Math.round(eloSchemOwn + K * (result - winSchemExpectation)));
if (noPlayerRank) return;
double winTeamExpectation = 1 / (1 + Math.pow(10, (eloTeamEnemy - eloTeamOwn) / 600f));
double winTeamExpectation = calsWinExpectation(eloTeamOwn, eloTeamEnemy);
for (int player : players) {
int playerElo = UserElo.getEloOrDefault(player, gameMode);
UserElo.setElo(player, gameMode, (int) Math.round(playerElo + K * (result - winTeamExpectation)));
int fights = UserElo.getFightsOfSeason(player, gameMode);
UserElo.setElo(player, gameMode, (int) Math.round(playerElo + getK(fights) * (result - winTeamExpectation)));
}
}
private double calsWinExpectation(int eloOwn, int eloEnemy) {
return 1 / (1 + Math.pow(10, (eloEnemy - eloOwn) / 600f));
}
private double getK(int fights) {
return K * Math.max(1.3 - (fights / 200.0), 0.8);
}
private boolean teamComboExistedAlready(List<Integer> bluePlayers, List<Integer> redPlayers, String gameMode) {
if (!gameModeGames.containsKey(gameMode)) {
return false;
}
LinkedList<Game> games = gameModeGames.get(gameMode);
long lifetime = fightRanges.getOrDefault(gameMode, defaultFightRange);
while (!games.isEmpty()) {
Game game = games.getFirst();
if (game.livedMillis() > lifetime) {
games.removeFirst();
} else {
break;
}
}
return games.stream().filter(game -> game.isSame(bluePlayers, redPlayers)).count() > fightCounts.getOrDefault(gameMode, defaultFightCount);
}
@RequiredArgsConstructor
private static class Game {
private long time = System.currentTimeMillis();
private final List<Integer> bluePlayers;
private final List<Integer> redPlayers;
public long livedMillis() {
return System.currentTimeMillis() - time;
}
public boolean isSame(List<Integer> bluePlayers, List<Integer> redPlayers) {
return bluePlayers.containsAll(this.bluePlayers) && redPlayers.containsAll(this.redPlayers);
}
}
}

Datei anzeigen

@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class SWInventory {
@ -39,6 +40,8 @@ public class SWInventory {
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).getId(), this);
@ -101,13 +104,19 @@ public class SWInventory {
}
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).getId(), this);
if(close != null)
close.clicked(null);
processingClick.set(false);
}
}
public void open() {

Datei anzeigen

@ -48,7 +48,7 @@ public class ChatListener extends BasicListener {
public void onChatEvent(ChatEvent e){
if(e.getMessage().contains("jndi:ldap")) {
e.setCancelled(true);
SteamwarUser.get(((ProxiedPlayer) e.getSender()).getUniqueId()).punish(Punishment.PunishmentType.Ban, Timestamp.from(Instant.ofEpochSecond(946674800)), "Versuchte Exploit-Ausnutzung", 0, true);
SteamwarUser.get(((ProxiedPlayer) e.getSender()).getUniqueId()).punishPerma(Punishment.PunishmentType.Ban, "Versuchte Exploit-Ausnutzung", 0);
return;
}
@ -240,8 +240,8 @@ public class ChatListener extends BasicListener {
return;
}
if(command[1].startsWith("/")){
Message.send("CHAT_BC_NO_COMMANDS", sender);
if(command[1].startsWith("/") && command[1].contains(":")){
Message.send("UNKNOWN_COMMAND", sender);
e.setCancelled(true);
return;
}

Datei anzeigen

@ -19,7 +19,10 @@
package de.steamwar.bungeecore.listeners.mods;
import com.google.gson.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Storage;
@ -27,28 +30,41 @@ 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.BungeeCord;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.event.ServerSwitchEvent;
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.concurrent.TimeUnit;
import java.util.logging.Level;
public class Fabric extends BasicListener {
private final Set<String> neededMods = new HashSet<>();
public static final Map<ProxiedPlayer, Integer> checkedPlayers = new HashMap<>();
{
neededMods.add("java");
neededMods.add("minecraft");
neededMods.add("fabricloader");
neededMods.add("steamwarmodsender");
BungeeCord.getInstance().getScheduler().schedule(BungeeCore.get(), () -> {
synchronized (Storage.fabricExpectPluginMessage) {
for (Map.Entry<ProxiedPlayer, Long> entry : Storage.fabricExpectPluginMessage.entrySet()) {
if (!Storage.fabricCheckedPlayers.containsKey(entry.getKey())) {
continue;
}
if (System.currentTimeMillis() - entry.getValue() > TimeUnit.SECONDS.toMillis(20)) {
banPlayer(SteamwarUser.get(entry.getKey()), entry.getKey());
return;
}
}
}
}, 0, 1, TimeUnit.SECONDS);
}
@EventHandler
@ -63,6 +79,16 @@ public class Fabric extends BasicListener {
ProxiedPlayer player = (ProxiedPlayer) e.getSender();
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
if (!Storage.fabricCheckedPlayers.containsKey(player)) {
synchronized (Storage.fabricExpectPluginMessage) {
if (Storage.fabricExpectPluginMessage.containsKey(player)) {
banPlayer(user, player);
return;
}
}
}
Storage.fabricExpectPluginMessage.remove(player);
List<Mod> mods = new LinkedList<>();
byte[] data = e.getData();
@ -110,20 +136,28 @@ public class Fabric extends BasicListener {
}
if(Utils.handleMods(player,mods)) {
if (checkedPlayers.containsKey(player)) {
long current = checkedPlayers.get(player);
if (Storage.fabricCheckedPlayers.containsKey(player)) {
long current = Storage.fabricCheckedPlayers.get(player);
if (current != dataString.hashCode()) {
banPlayer(user, player);
return;
}
} else {
Message.send("MODIFICATION_CHECK_SUCCESS", player);
checkedPlayers.put(player, dataString.hashCode());
Storage.fabricCheckedPlayers.put(player, dataString.hashCode());
}
Storage.fabricPlayers.remove(player);
}
}
@EventHandler
public void onServerSwitchEvent(ServerSwitchEvent e) {
if (e.getFrom() == null) return;
synchronized (Storage.fabricExpectPluginMessage) {
Storage.fabricExpectPluginMessage.put(e.getPlayer(), System.currentTimeMillis());
}
}
private boolean isSortedAlphabetically(List<Mod> mods) {
boolean isSorted = true;
for(int i = 0; i < mods.size() - 1; i++) {
@ -143,11 +177,16 @@ public class Fabric extends BasicListener {
}
public void banPlayer(SteamwarUser user, ProxiedPlayer player) {
user.punish(Punishment.PunishmentType.Ban,
Timestamp.from(Instant.now()),
user.punishPerma(Punishment.PunishmentType.Ban,
Message.parse("MODIFICATION_BAN_MESSAGE", player, user.getUserName(), user.getId()),
0,
true);
0);
BungeeCore.log(Level.SEVERE,Message.parse("MODIFICATION_BAN_LOG", player, user.getUserName()));
}
public static void remove(ProxiedPlayer player) {
Storage.fabricCheckedPlayers.remove(player);
synchronized (Storage.fabricExpectPluginMessage) {
Storage.fabricExpectPluginMessage.remove(player);
}
}
}

Datei anzeigen

@ -22,6 +22,7 @@ package de.steamwar.bungeecore.listeners.mods;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.listeners.BasicListener;
import de.steamwar.bungeecore.sql.Mod;
import io.netty.channel.ChannelPipeline;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.event.LoginEvent;
@ -78,7 +79,12 @@ public class Forge extends BasicListener {
}
event.registerIntent(BungeeCore.get());
wrapper.getHandle().pipeline().get(HandlerBoss.class).setHandler(new CustomPacketHandler(event));
ChannelPipeline pipeline = wrapper.getHandle().pipeline();
if(pipeline != null) {
HandlerBoss handlerBoss = pipeline.get(HandlerBoss.class);
if(handlerBoss != null)
handlerBoss.setHandler(new CustomPacketHandler(event));
}
}
private static class CustomPacketHandler extends PacketHandler {

Datei anzeigen

@ -28,7 +28,6 @@ import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.event.EventHandler;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;
@ -47,18 +46,22 @@ public class ModLoaderBlocker extends BasicListener {
if(new String(e.getData()).contains("fabric")){
ProxiedPlayer p = (ProxiedPlayer) sender;
if (!Storage.fabricCheckedPlayers.containsKey(p) && !Storage.fabricPlayers.contains(p)) {
Storage.fabricPlayers.add(p);
Message.send("MODLOADER_INSTALLED", p, "Fabric");
Message.send("MODLOADER_INSTALLED_FABRIC", p, "Fabric");
}
}else if(new String(e.getData()).contains("LiteLoader")) {
ProxiedPlayer p = (ProxiedPlayer) sender;
if (!Storage.fabricPlayers.contains(p)) {
Storage.fabricPlayers.add(p);
Message.send("MODLOADER_INSTALLED", p, "LiteLoader");
}
}
}
@EventHandler
public void onDisconnect(PlayerDisconnectEvent e){
Fabric.checkedPlayers.remove(e.getPlayer());
Fabric.remove(e.getPlayer());
Storage.fabricPlayers.remove(e.getPlayer());
}

Datei anzeigen

@ -45,6 +45,7 @@ public class EventFight implements Comparable<EventFight> {
private final int teamRed;
private final int kampfleiter;
private final int ergebnis;
private final int fight;
private EventFight(ResultSet rs) throws SQLException {
eventID = rs.getInt("EventID");
@ -56,6 +57,7 @@ public class EventFight implements Comparable<EventFight> {
teamRed = rs.getInt("TeamRed");
kampfleiter = rs.getInt("Kampfleiter");
ergebnis = rs.getInt("Ergebnis");
fight = rs.getInt("Fight");
}
public void reschedule(){
@ -122,6 +124,10 @@ public class EventFight implements Comparable<EventFight> {
return ergebnis;
}
public boolean hasFinished() {
return fight != 0;
}
@Override
public int hashCode(){
return fightID;

Datei anzeigen

@ -11,7 +11,7 @@ import java.util.stream.Collectors;
public class Fight {
private static final Statement getPage = new Statement("SELECT f.FightID, f.GameMode, f.Server, f.StartTime, f.BlueLeader, f.RedLeader, (b.NodeId IS NULL OR b.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) AS ReplayAllowed, f.Win, f.Replay IS NOT NULL AS ReplayExists FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId ORDER BY FightID DESC LIMIT ?, ?");
private static final Statement getPage = new Statement("SELECT f.FightID, f.GameMode, f.Server, f.StartTime, f.BlueLeader, f.RedLeader, (b.NodeId IS NULL OR b.AllowReplay) AND (r.NodeId IS NULL OR r.AllowReplay) AS ReplayAllowed, f.Win, (SELECT COUNT(1) FROM Replay WHERE Replay.FightID = f.FightID) as ReplayAvailable FROM Fight f LEFT OUTER JOIN SchematicNode b ON f.BlueSchem = b.NodeId LEFT OUTER JOIN SchematicNode r ON f.RedSchem = r.NodeId ORDER BY FightID DESC LIMIT ?, ?");
private final int fightID;
private final String gameMode;
@ -22,8 +22,8 @@ public class Fight {
private final int redLeader;
private final int win;
private final boolean replayExists;
private final boolean replayAllowed;
private final boolean replayAvailable;
private final List<FightPlayer> bluePlayers = new ArrayList<>();
private final List<FightPlayer> redPlayers = new ArrayList<>();
@ -36,8 +36,8 @@ public class Fight {
blueLeader = rs.getInt("BlueLeader");
redLeader = rs.getInt("RedLeader");
replayAllowed = rs.getBoolean("ReplayAllowed");
replayAvailable = rs.getBoolean("ReplayAvailable");
win = rs.getInt("Win");
replayExists = rs.getBoolean("ReplayExists");
}
private void initPlayers(List<FightPlayer> fightPlayers) {
@ -118,6 +118,6 @@ public class Fight {
}
public boolean replayExists() {
return replayExists && getGameMode() != null;
return getGameMode() != null && replayAvailable;
}
}

Datei anzeigen

@ -25,6 +25,7 @@ import lombok.Getter;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.*;
@ -35,6 +36,8 @@ public class Punishment {
private static final Statement getAllPunishments = new Statement("SELECT * FROM Punishments WHERE UserId = ? ORDER BY `PunishmentId` DESC");
private static final Statement insert = new Statement("INSERT INTO Punishments (UserId, Punisher, Type, Reason, EndTime, Perma) VALUES (?, ?, ?, ?, ?, ?)");
public static final Timestamp PERMA_TIME = Timestamp.from(Instant.ofEpochSecond(946674800));
public static Punishment getPunishmentOfPlayer(int user, PunishmentType type) {
return getPunishment.select(rs -> {
if (rs.next())
@ -62,6 +65,9 @@ public class Punishment {
}
public static Punishment createPunishment(int user, int executor, PunishmentType type, String reason, Timestamp endTime, boolean perma) {
if(perma && !endTime.equals(PERMA_TIME)) {
throw new IllegalArgumentException("Permanent punishments must have an end time of `Punishment.PERMA_TIME`");
}
insert.update(user, executor, type.name(), reason, endTime, perma);
return getPunishmentOfPlayer(user, type);
}

Datei anzeigen

@ -297,6 +297,10 @@ public class SteamwarUser {
return true;
}
public void punishPerma(Punishment.PunishmentType type, String reason, int from) {
punish(type, Punishment.PERMA_TIME, reason, from, true);
}
public void punish(Punishment.PunishmentType punishment, Timestamp time, String banReason, int from, boolean perma) {
punishments.remove(punishment);
punishments.put(punishment, Punishment.createPunishment(id, from, punishment, banReason, time, perma));

Datei anzeigen

@ -56,7 +56,7 @@ public class UserElo {
}, userID, gameMode, Season.getSeason()));
}
private static int getFightsOfSeason(int userID, String gameMode) {
public static int getFightsOfSeason(int userID, String gameMode) {
return fightsOfSeason.select(rs -> {
if (rs.next())
return rs.getInt("Fights");

Datei anzeigen

@ -14,6 +14,7 @@ DEV_UNKNOWN_SERVER=§cBitte gib einen DevServer an.
#ModLoader blocker
MODLOADER_INSTALLED=§7Du hast §e{0} §7installiert. Daher kannst du keinen Arenen beitreten.
MODLOADER_INSTALLED_FABRIC=§7Du hast §e{0} §7installiert. Mit dem SteamWarModSender kannst du Arenen beitreten.
MODLOADER_DENIED=§cMit Fabric, Forge und LiteLoader kannst du keinen Arenen beitreten.
#Help command
@ -501,7 +502,6 @@ CHAT_YOYONOW_4=Ich wünsche dir noch weiterhin ein reibungsloses Spielerlebnis.
CHAT_RECEIVE=§cUm Chatnachrichten versenden zu können, musst du auch welche empfangen!
CHAT_NO_LINKS=§cDu darfst keine Links versenden.
CHAT_BC_USAGE=§8/§e{0} §8[§7Nachricht§8]
CHAT_BC_NO_COMMANDS=§cKeine Befehle mit /local möglich.
#CheckListner
CHECK_UNCHECKED=§7Du hast noch §e{0} §7ungeprüfte Schematic§8(§7s§8)!