SteamWar/BungeeCore
Archiviert
13
2

Forge Mod detection #292

Zusammengeführt
Lixfel hat 11 Commits von ModDetection1.13+ nach master 2022-02-03 22:06:16 +01:00 zusammengeführt
8 geänderte Dateien mit 329 neuen und 122 gelöschten Zeilen

Datei anzeigen

@ -78,6 +78,7 @@ public class BungeeCore extends Plugin {
errorLogger = new ErrorLogger();
new ConnectionListener();
new Forge();
new Forge12();
new LabyMod();
new Badlion();
new ChatListener();

Datei anzeigen

@ -44,24 +44,26 @@ public class Message {
};
public static TextComponent parseToComponent(String message, boolean prefixed, CommandSender sender, Object... params){
return new TextComponent(TextComponent.fromLegacyText(parse(message, prefixed, sender, params)));
return new TextComponent(TextComponent.fromLegacyText(parse(message, prefixed, locale(sender), params)));
}
public static String parsePrefixed(String message, CommandSender sender, Object... params){
return parse(message, true, sender, params);
return parse(message, true, locale(sender), params);
}
public static String parse(String message, CommandSender sender, Object... params){
return parse(message, false, sender, params);
return parse(message, false, locale(sender), params);
}
private static String parse(String message, boolean prefixed, CommandSender sender, Object... params){
Locale locale = null;
if(sender instanceof ProxiedPlayer)
locale = ((ProxiedPlayer)sender).getLocale();
if(locale == null)
locale = Locale.getDefault();
public static String parse(String message, Locale locale, Object... params){
return parse(message, false, locale, params);
}
private static Locale locale(CommandSender sender) {
return sender instanceof ProxiedPlayer ? ((ProxiedPlayer)sender).getLocale() : Locale.getDefault();
}
private static String parse(String message, boolean prefixed, Locale locale, Object... params){
ResourceBundle resourceBundle = ResourceBundle.getBundle("de.steamwar.messages.BungeeCore", locale, CONTROL);
String pattern = "";
if(prefixed)
@ -72,7 +74,7 @@ public class Message {
for (int i = 0; i < params.length; i++) {
if(params[i] instanceof Message) {
Message msg = (Message) params[i];
params[i] = parse(msg.getMessage(), sender, msg.getParams());
params[i] = parse(msg.getMessage(), false, locale, msg.getParams());
} else if(params[i] instanceof Date) {
params[i] = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale).format((Date) params[i]);
}
@ -120,7 +122,7 @@ public class Message {
public static void broadcast(String message, String onHover, ClickEvent onClick, Object... params){
for(ProxiedPlayer player : ProxyServer.getInstance().getPlayers())
send(message, player, parse(onHover, false, player, params), onClick, params);
send(message, player, parse(onHover, player, params), onClick, params);
}
public static void broadcast(String message, Object... params){

Datei anzeigen

@ -0,0 +1,86 @@
/*
zOnlyKroks markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Fehlender License-Header

Fehlender License-Header
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 net.md_5.bungee.api.ServerPing;
import java.util.*;
public class FMLPing extends ServerPing {
private final ForgeData forgeData;
zOnlyKroks markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Man könnte noch argumentieren, dass es äußerst schade ist, dass wir hier für jeden Ping die ForeData neu erstellen und danach wieder verwerfen, aber das ist so schon in Ordnung.

Man könnte noch argumentieren, dass es äußerst schade ist, dass wir hier für jeden Ping die ForeData neu erstellen und danach wieder verwerfen, aber das ist so schon in Ordnung.
Veraltet
Review

Könnte man das nicht einfach mit einem 'static' beheben?

Könnte man das nicht einfach mit einem 'static' beheben?
Veraltet
Review

wird morgn als erledigt markiert.

wird morgn als erledigt markiert.
Lixfel markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Also von einem static block war nicht die rede nur den static modifier. Also sowas wie 'private static ForgeData forgeData = new ForgeData();'.

Also von einem static block war nicht die rede nur den static modifier. Also sowas wie 'private static ForgeData forgeData = new ForgeData();'.
Veraltet
Review

Wo wird das überhaupt genutzt?

Wo wird das überhaupt genutzt?
Veraltet
Review

GSON-Serializer des ServerListPings.

Anmerkung meinerseits: Ob das korrekt serialisiert wird, wenn die ForgeData als static final deklariert wird, muss getestet werden.

GSON-Serializer des ServerListPings. Anmerkung meinerseits: Ob das korrekt serialisiert wird, wenn die ForgeData als static final deklariert wird, muss getestet werden.
Veraltet
Review

Naja es ist static also gar nicht serializiert? Ansonsten mach halt mit einem instance ansatz, im ForgeData selber.

Naja es ist static also gar nicht serializiert? Ansonsten mach halt mit einem instance ansatz, im ForgeData selber.
Veraltet
Review

Ist unbekannt ob, muss daher getestet werden.

Ist unbekannt ob, muss daher getestet werden.
Veraltet
Review

Ich glaube, das muss weiterhin forgeData heißen, ansonsten erkennt Forge die Modliste nicht... du solltest auch mal probieren, mit Minecraft-Versionen anders als 1.15.2, ob dann immer noch die Kompatibilität gemeldet wird (da wir ja minecraft 1.15.2 als Mod drin haben...

Ich glaube, das muss weiterhin forgeData heißen, ansonsten erkennt Forge die Modliste nicht... du solltest auch mal probieren, mit Minecraft-Versionen anders als 1.15.2, ob dann immer noch die Kompatibilität gemeldet wird (da wir ja minecraft 1.15.2 als Mod drin haben...
Veraltet
Review

static mact hier in diesem Falle nur probleme

static mact hier in diesem Falle nur probleme
Veraltet
Review

Kompatibilität wird verneint. Forge 1.16.5

Kompatibilität wird verneint. Forge 1.16.5
public FMLPing(ServerPing existing, int version) {
super(existing.getVersion(), existing.getPlayers(), existing.getDescriptionComponent(), existing.getFaviconObject());
forgeData = new ForgeData(version);
}
private static class ForgeData {
private final List<ForgeChannel> channels = new ArrayList<>();
private final List<ForgeMod> mods = new ArrayList<>();
Review

Style?

Style?
private final int fmlNetworkVersion = 2;
public ForgeData(int versionNumber) {
channels.add(new ForgeChannel("minecraft:unregister"));
channels.add(new ForgeChannel("minecraft:register"));
channels.add(new ForgeChannel("fml:handshake"));
mods.add(new ForgeMod("minecraft", ProtocolVersion.getVersion(versionNumber)));
mods.add(new ForgeMod("forge", "ANY"));
}
public final static class ProtocolVersion {
private static final HashMap<Integer, String> versions;
static {
versions = new HashMap();
versions.put(757, "1.18");
versions.put(756, "1.17.1");
versions.put(754, "1.16.5");
versions.put(578, "1.15.2");
versions.put(498, "1.14.1");
versions.put(393, "1.13");
}
public static String getVersion(int version) {
return versions.get(version);
}
}
private static class ForgeChannel {
private final String res;
private final String version = "FML2";
private final boolean required = true;
private ForgeChannel(String res) {
this.res = res;
}
}
private static class ForgeMod {
private final String modId;
private final String modmarker;
private ForgeMod(String modId, String modmarker) {
this.modId = modId;
this.modmarker = modmarker;
}
Veraltet
Review

Wäre es nicht einfacher, statt dem Enum einfach direkt eine HashMap<Integer, String> zu machen?

Wäre es nicht einfacher, statt dem Enum einfach direkt eine HashMap<Integer, String> zu machen?
}
}
}

Datei anzeigen

@ -22,102 +22,112 @@ 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.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.Connection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.protocol.packet.LoginPayloadRequest;
import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
public class Forge extends BasicListener {
private static final String FMLHS = "FML|HS";
private static final String FMLHS13 = "fml:handshake";
private static final byte[] REGISTER;
private static final byte[] REGISTER13;
private static final byte[] HELLO = new byte[]{0, 2, 0, 0, 0, 0};
private static final Set<UUID> unlocked = new HashSet<>();
private static final String WRAPPER = "fml:loginwrapper";
private static final Field initialHandlerCh;
static{
ByteBuf buf = UnpooledByteBufAllocator.DEFAULT.directBuffer(7);
buf.writeByte(6);
buf.writeCharSequence(FMLHS, StandardCharsets.UTF_8);
REGISTER = new byte[buf.readableBytes()];
buf.readBytes(REGISTER);
buf.clear();
buf.writeByte(13);
buf.writeCharSequence(FMLHS13, StandardCharsets.UTF_8);
REGISTER13 = new byte[buf.readableBytes()];
buf.readBytes(REGISTER13);
try {
initialHandlerCh = InitialHandler.class.getDeclaredField("ch");
} catch (NoSuchFieldException e) {
throw new SecurityException("Could not initialize Reflection", e);
zOnlyKroks markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Bitte nicht vergessen, den alten 1.13 Forge-Support auszubauen :) (Aber bitte den 1.12- Support drin lassen!)

Du kannst dann auch ich glaube im Fabric-Modhandler? den Arenenblock für Forge-Spieler ausbauen.

Bitte nicht vergessen, den alten 1.13 Forge-Support auszubauen :) (Aber bitte den 1.12- Support drin lassen!) Du kannst dann auch ich glaube im Fabric-Modhandler? den Arenenblock für Forge-Spieler ausbauen.
}
initialHandlerCh.setAccessible(true);
}
@EventHandler
public void onPostLogin(PostLoginEvent event) {
ProxiedPlayer player = event.getPlayer();
public void onServerPing(ProxyPingEvent event) {
event.setResponse(new FMLPing(event.getResponse(), event.getConnection().getVersion()));
}
synchronized (unlocked) {
if(unlocked.contains(player.getUniqueId())){
unlocked.remove(player.getUniqueId());
@EventHandler
public void onServerConnected(LoginEvent event){
if(event.getConnection().getVersion() < 340) return; //1.13+
//fml:handshake without mods, channels and registries
//for more information see https://wiki.vg/Minecraft_Forge_Handshake#FML2_protocol_.281.13_-_Current.29
event.getConnection().unsafe().sendPacket(new LoginPayloadRequest(1, WRAPPER, new byte[]{13,102,109,108,58,104,97,110,100,115,104,97,107,101,4,1,0,0,0}));
InitialHandler handler = (InitialHandler) event.getConnection();
ChannelWrapper wrapper;
try{
wrapper = (ChannelWrapper) initialHandlerCh.get(handler);
zOnlyKroks markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Die Kommentarzeile (und ggf. noch die Zeilen drüber) können weg.

Die Kommentarzeile (und ggf. noch die Zeilen drüber) können weg.
} catch (IllegalAccessException e) {
BungeeCore.get().getLogger().log(Level.SEVERE, "Could not get Channel", e);
zOnlyKroks markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Hier vorher noch eine Prüfung, dass der Client 1.13 oder höhere Version hat (in dem Fall einfach return). 1.12 und niedriger kennt nämlich keine LoginPayloadRequests.

Hier vorher noch eine Prüfung, dass der Client 1.13 oder höhere Version hat (in dem Fall einfach return). 1.12 und niedriger kennt nämlich keine LoginPayloadRequests.
return;
}
event.registerIntent(BungeeCore.get());
wrapper.getHandle().pipeline().get(HandlerBoss.class).setHandler(new CustomPacketHandler(event));
}
private static class CustomPacketHandler extends PacketHandler {
private final LoginEvent event;
public CustomPacketHandler(LoginEvent event) {
this.event = event;
}
zOnlyKroks markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Ach ja, hier einen ordentlichen Logger benutzen, so wie BungeeCore.get().getLogger().log(Level.SEVERE, "Could not get Channel", e);

Und danach returnen.

Und vllt. auch erst nach der Reflection den Intent registrieren...

Ach ja, hier einen ordentlichen Logger benutzen, so wie BungeeCore.get().getLogger().log(Level.SEVERE, "Could not get Channel", e); Und danach returnen. Und vllt. auch erst nach der Reflection den Intent registrieren...
@Override
public String toString() {
return "SteamWar Forge Handler";
}
@Override
public void handle(LoginPayloadResponse response){
byte[] data = response.getData();
if(data == null) {
event.completeIntent(BungeeCore.get());
return;
}
}
if(player.getPendingConnection().getVersion() > 340) {
player.sendData("minecraft:register", REGISTER13); //1.13+
player.sendData(FMLHS13, Forge.HELLO);
}else{
player.sendData("REGISTER", REGISTER); //1.12-
player.sendData(FMLHS, Forge.HELLO);
}
}
//for more information see https://wiki.vg/Minecraft_Forge_Handshake#FML2_protocol_.281.13_-_Current.29
Utils.VarInt channelLength = Utils.readVarInt(data, 0);
int pos = channelLength.length;
assert new String(data, pos, channelLength.value).equals("fml:handshake");
@EventHandler
public void onPluginMessageEvent(PluginMessageEvent e){
if(!e.getTag().equals(FMLHS) && !e.getTag().equals(FMLHS13))
return;
Utils.VarInt length = Utils.readVarInt(data, pos);
pos += length.length;
assert channelLength.length + channelLength.value + length.length + length.value == data.length;
e.setCancelled(true);
byte[] data = e.getData();
Utils.VarInt packetId = Utils.readVarInt(data, pos);
pos += packetId.length;
assert packetId.value == 2;
Connection sender = e.getSender();
if(!(sender instanceof ProxiedPlayer))
return;
ProxiedPlayer p = (ProxiedPlayer) sender;
Utils.VarInt modCount = Utils.readVarInt(data, pos);
pos += modCount.length;
if (data[0] == 2) {
Utils.VarInt numMods = Utils.readVarInt(data, 1);
List<Mod> mods = new LinkedList<>();
List<Mod> mods = new ArrayList<>();
for(int i = 0; i < modCount.value; i++) {
Utils.VarInt nameLength = Utils.readVarInt(data, pos);
pos += nameLength.length;
int bytePos = 1 + numMods.length;
for (int i = 0; i < numMods.value; i++) {
byte[] name = Arrays.copyOfRange(data, bytePos + 1, bytePos + data[bytePos] + 1);
bytePos += 1 + data[bytePos];
//Version information is unused
bytePos += 1 + data[bytePos];
mods.add(Mod.get(new String(name), Mod.Platform.FORGE));
mods.add(Mod.get(new String(data, pos, nameLength.value), Mod.Platform.FORGE));
pos += nameLength.value;
}
if (Utils.handleMods(p, mods)) {
synchronized (unlocked) {
unlocked.add(p.getUniqueId());
}
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(),
() -> p.disconnect(BungeeCore.stringToText("§7Deine installierten Mods wurden überprüft\n§aDu kannst nun §eSteam§8War §abetreten")),
2, TimeUnit.SECONDS);
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> {
synchronized (unlocked) {
unlocked.remove(p.getUniqueId());
}
}, 30, TimeUnit.SECONDS);
}
PendingConnection connection = event.getConnection();
if(Utils.handleMods(connection.getUniqueId(), Locale.getDefault(), connection::disconnect, mods))
event.completeIntent(BungeeCore.get());
}
}
}

Datei anzeigen

@ -0,0 +1,113 @@
/*
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.listeners.mods;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.listeners.BasicListener;
import de.steamwar.bungeecore.sql.Mod;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.Connection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.event.EventHandler;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class Forge12 extends BasicListener {
private static final String FMLHS = "FML|HS";
private static final byte[] REGISTER;
private static final byte[] HELLO = new byte[]{0, 2, 0, 0, 0, 0};
private static final Set<UUID> unlocked = new HashSet<>();
static {
ByteBuf buf = UnpooledByteBufAllocator.DEFAULT.directBuffer(7);
buf.writeByte(6);
buf.writeCharSequence(FMLHS, StandardCharsets.UTF_8);
REGISTER = new byte[buf.readableBytes()];
buf.readBytes(REGISTER);
}
@EventHandler
public void onPostLogin(PostLoginEvent event) {
ProxiedPlayer player = event.getPlayer();
synchronized (unlocked) {
if(unlocked.contains(player.getUniqueId())){
unlocked.remove(player.getUniqueId());
return;
}
}
if(player.getPendingConnection().getVersion() <= 340) {
player.sendData("REGISTER", REGISTER); //1.12-
player.sendData(FMLHS, HELLO);
}
}
@EventHandler
public void onPluginMessageEvent(PluginMessageEvent e){
if(!e.getTag().equals(FMLHS))
return;
e.setCancelled(true);
byte[] data = e.getData();
Connection sender = e.getSender();
if(!(sender instanceof ProxiedPlayer))
return;
ProxiedPlayer p = (ProxiedPlayer) sender;
if (data[0] == 2) {
Utils.VarInt numMods = Utils.readVarInt(data, 1);
List<Mod> mods = new LinkedList<>();
int bytePos = 1 + numMods.length;
for (int i = 0; i < numMods.value; i++) {
byte[] name = Arrays.copyOfRange(data, bytePos + 1, bytePos + data[bytePos] + 1);
bytePos += 1 + data[bytePos];
//Version information is unused
bytePos += 1 + data[bytePos];
mods.add(Mod.get(new String(name), Mod.Platform.FORGE));
}
if (Utils.handleMods(p, mods)) {
synchronized (unlocked) {
unlocked.add(p.getUniqueId());
}
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(),
() -> p.disconnect(BungeeCore.stringToText("§7Deine installierten Mods wurden überprüft\n§aDu kannst nun §eSteam§8War §abetreten")),
2, TimeUnit.SECONDS);
ProxyServer.getInstance().getScheduler().schedule(BungeeCore.get(), () -> {
synchronized (unlocked) {
unlocked.remove(p.getUniqueId());
}
}, 30, TimeUnit.SECONDS);
}
}
}
}

Datei anzeigen

@ -56,26 +56,6 @@ public class ModLoaderBlocker extends BasicListener {
}
}
@EventHandler
public void onPluginMessage(PluginMessageEvent e){
if(!e.getTag().equals("minecraft:register"))
return;
Connection sender = e.getSender();
if(!(sender instanceof ProxiedPlayer))
return;
ProxiedPlayer p = (ProxiedPlayer) sender;
if(p.getPendingConnection().getVersion() <= 340)
return;
String registered = new String(e.getData(), StandardCharsets.UTF_8);
if(registered.contains("fml:loginwrapper") || registered.contains("fml:handshake") || registered.contains("fml:play")){
Storage.fabricPlayers.add(p);
Message.send("MODLOADER_INSTALLED", p, "Forge");
}
}
@EventHandler
public void onDisconnect(PlayerDisconnectEvent e){
Storage.fabricPlayers.remove(e.getPlayer());

Datei anzeigen

@ -25,6 +25,8 @@ import de.steamwar.bungeecore.sql.Mod;
import de.steamwar.bungeecore.sql.Mod.ModType;
import de.steamwar.bungeecore.sql.Punishment;
import de.steamwar.bungeecore.sql.SteamwarUser;
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 java.sql.Timestamp;
@ -32,6 +34,9 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.logging.Level;
class Utils {
@ -55,9 +60,13 @@ class Utils {
return new VarInt(numRead, result);
}
static boolean handleMods(ProxiedPlayer player, List<Mod> mods){
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
boolean privileged = player.hasPermission("bungeecore.youtubermods");
static boolean handleMods(ProxiedPlayer player, List<Mod> mods) {
return handleMods(player.getUniqueId(), player.getLocale(), player::disconnect, mods);
}
static boolean handleMods(UUID uuid, Locale locale, Consumer<BaseComponent[]> disconnect, List<Mod> mods){
SteamwarUser user = SteamwarUser.get(uuid);
boolean privileged = user.getUserGroup().privilegedMods();
ModType max = ModType.YELLOW;
Iterator<Mod> it = mods.iterator();
@ -74,9 +83,9 @@ class Utils {
if(mods.size() == 1){
if(max == ModType.YELLOW)
player.disconnect(BungeeCore.stringToText(Message.parse("MOD_YELLOW_SING", player, mods.get(0).getModName())));
disconnect.accept(TextComponent.fromLegacyText(Message.parse("MOD_YELLOW_SING", locale, mods.get(0).getModName())));
else{
user.punish(Punishment.PunishmentType.Ban, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), Message.parse("MOD_RED_SING", player, mods.get(0).getModName()), 0, false);
user.punish(Punishment.PunishmentType.Ban, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), Message.parse("MOD_RED_SING", locale, mods.get(0).getModName()), 0, false);
BungeeCore.log(Level.SEVERE, user.getUserName() + " " + user.getId() + " wurde automatisch wegen des Mods " + mods.get(0).getModName() + " gebannt.");
}
}else{
@ -84,10 +93,10 @@ class Utils {
mods.forEach(mod -> sb.append(mod.getModName()).append('\n'));
if(max == ModType.YELLOW)
player.disconnect(BungeeCore.stringToText(Message.parse("MOD_YELLOW_PLUR", player, sb.toString())));
disconnect.accept(TextComponent.fromLegacyText(Message.parse("MOD_YELLOW_PLUR", locale, sb.toString())));
else{
user.punish(Punishment.PunishmentType.Ban, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), Message.parse("MOD_RED_PLUR", player, sb.toString()), 0, false);
BungeeCore.log(Level.SEVERE, user.getUserName() + " " + user.getId() + " wurde automatisch wegen der Mods " + sb.toString() + " gebannt.");
user.punish(Punishment.PunishmentType.Ban, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), Message.parse("MOD_RED_PLUR", locale, sb.toString()), 0, false);
BungeeCore.log(Level.SEVERE, user.getUserName() + " " + user.getId() + " wurde automatisch wegen der Mods " + sb + " gebannt.");
}
}

Datei anzeigen

@ -24,26 +24,28 @@ import java.util.stream.Collectors;
public enum UserGroup {
Admin("§4", "§e", true, true, true),
Developer("§3", "§f", true, true, true),
Moderator("§c", "§f", true, true, true),
Supporter("§9", "§f", false, true, true),
Builder("§2", "§f", false, true, false),
YouTuber("§5", "§f", false, false, false),
Member("§7", "§7", false, false, false);
Admin("§4", "§e", true, true, true, true),
Developer("§3", "§f", true, true, true, true),
Moderator("§c", "§f", true, true, true, true),
Supporter("§9", "§f", false, true, true, true),
Builder("§2", "§f", false, true, false, true),
YouTuber("§5", "§f", false, false, false, true),
Member("§7", "§7", false, false, false, false);
private final String colorCode;
private final String chatColorCode;
private final boolean adminGroup;
private final boolean teamGroup;
private final boolean checkSchematics;
private final boolean privilegedMods;
UserGroup(String colorCode, String chatColorCode, boolean adminGroup, boolean teamGroup, boolean checkSchematics) {
UserGroup(String colorCode, String chatColorCode, boolean adminGroup, boolean teamGroup, boolean checkSchematics, boolean privilegedMods) {
this.colorCode = colorCode;
this.chatColorCode = chatColorCode;
this.adminGroup = adminGroup;
this.teamGroup = teamGroup;
this.checkSchematics = checkSchematics;
this.privilegedMods = privilegedMods;
}
public String getColorCode() {
@ -62,6 +64,10 @@ public enum UserGroup {
return checkSchematics;
}
public boolean privilegedMods() {
return privilegedMods;
}
public String getChatColorCode() {
return chatColorCode;
}