Ban System Rework #150
Keine Reviewer
Label
Kein Label
Bug
Codeverbesserung
Einsteiger Freundlich
Idee
In Arbeit
Neues Feature
Prio A
Security Breach
Überprüfung notwendig
Verbesserung
Zu Beobachten
Kein Meilenstein
Niemand zuständig
3 Beteiligte
Fällig am
Kein Fälligkeitsdatum gesetzt.
Abhängigkeiten
Keine Abhängigkeiten gesetzt.
Referenz: SteamWar/BungeeCore#150
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren
Keine Beschreibung angegeben.
Branch "ban-rework" löschen
Das Löschen eines Branches ist permanent. Obwohl der Branch für eine kurze Zeit weiter existieren könnte, kann diese Aktion in den meisten Fällen NICHT rückgängig gemacht werden. Fortfahren?
Dieser MergeRequest wird einen MergeConflict mit BungeeCore#146 auslösen, d.h. solltest du diesen MergeRequest auf dem anderen Branch aufbauen.
@ -56,7 +56,8 @@ public class BanCommand extends BasicCommand {
}
String msg = banReason.toString();
BungeeCore.send(sender, BungeeCore.CHAT_PREFIX + "Du hast " + target.getUserName() + " gebannt. Grund: §c" + msg);
Wenn du das ganze Team benachrichtigst, brauchst du nicht mehr den Spieler persönlich zu benachrichtigen.
@ -58,2 +58,3 @@
BungeeCore.send(sender, BungeeCore.CHAT_PREFIX + "Du hast " + target.getUserName() + " gebannt. Grund: §c" + msg);
target.ban(banTime, msg);
ServerTeamchatCommand.sendToTeam(BungeeCore.CHAT_PREFIX + "§c" + target.getUserName() + " wurde von " + sender.getName() + " " + (args[1].equalsIgnoreCase("perma")?"Permanent":"bis zum " + banTime.toLocalDateTime().format(BungeeCore.DATE_FORMAT)) + " gebannt. §f§lGrund: §f" + banReason);
target.ban(banTime, msg, SteamwarUser.get(sender.getName()).getId(), args[1].equalsIgnoreCase("perma"));
Bitte erst die Aktion ausführen, dann die Aktion verkünden (im Fehlerfall kein Fehlannouncement).
@ -52,3 +52,4 @@
}
String msg = muteReason.toString();
ServerTeamchatCommand.sendToTeam(BungeeCore.CHAT_PREFIX + "§c" + target.getUserName() + " wurde von " + sender.getName() + " " + (args[1].equalsIgnoreCase("perma")?"Permanent":"bis zum " + muteTime.toLocalDateTime().format(BungeeCore.DATE_FORMAT)) + " gemuted. §f§lGrund: §f" + muteReason);
BungeeCore.send(sender, BungeeCore.CHAT_PREFIX + "Du hast " + target.getUserName() + " gemuted. Grund: §c" + msg);
Hier genauso.
@ -54,2 +54,3 @@
ServerTeamchatCommand.sendToTeam(BungeeCore.CHAT_PREFIX + "§c" + target.getUserName() + " wurde von " + sender.getName() + " " + (args[1].equalsIgnoreCase("perma")?"Permanent":"bis zum " + muteTime.toLocalDateTime().format(BungeeCore.DATE_FORMAT)) + " gemuted. §f§lGrund: §f" + muteReason);
BungeeCore.send(sender, BungeeCore.CHAT_PREFIX + "Du hast " + target.getUserName() + " gemuted. Grund: §c" + msg);
target.mute(muteTime, msg);
target.mute(muteTime, msg, SteamwarUser.get(sender.getName()).getId(), args[1].equalsIgnoreCase("perma"));
Hier genauso.
@ -75,3 +74,1 @@
}
if(user.isMuted()){
player.sendMessage(user.muteMessage());
BungeeCore.send(player, "§7Bestrafungen: ");
Strafen
@ -50,0 +55,4 @@
ips.removeIf(bannedUserIPs -> bannedUserIPs.getUserID() == user.getId());
if(ips.isEmpty())
return;
}
Was soll der Schmarrn und das Rausentfernen der ganzen immer noch gültigen Werte?
Die Einträge die da Entfernt werden sind, wenn der Joinende Spieler, welcher nicht gebannt ist, dieselbe IP hat wie einer der Einträge. Dann ist dieser Eintrag für mich ungültig, weil der Spieler kommt ja drauf, wieso sollte er dann noch IPBanned sein?
Weil ggf. gerade kein Teammitglied online ist, was die Situation bewerten kann? Wenn er entbannt wird/der Bann ausgelaufen ist), dann werden die IPs gelöscht, vorher nicht (VPNs etc.).
Sofern in der ips Liste sich ein Spieler mit der ID vom grade beigetretener Spieler befindet wird dieser aus der Liste entfernt, weil dieser kann ja wieder darauf spielen, warum sollte man den dann noch einen nicht gebannten Spieler in der List lassen?
Das macht bereits ein anderes Codestück, die IPs nach einer Entbannung zu entfernen.
@ -0,0 +28,4 @@
public class Punishment {
public static Punishment getPunishmentByPlayer(int user, PunishmentType type) {
ResultSet set = SQL.select("SELECT * FROM `Punishments` WHERE `PunishmentId` IN (SELECT MAX(`PunishmentId`) FROM Punishments WHERE UserId = ? AND Type = ?)", user, type.toDb());
Rekursive SELECT-Statements sind ein Performancekiller & du bekommst ggf. ein veraltetes Punishment zurück. Nutze doch lieber WHERE EndTime < NOW() AND UserId = ? AND Type = ? LIMIT 1
Das Problem ist, dass man hier ggf. ein älteres bereits überschriebenes Punishment zurückbekommt.
Und es soll ja so sein, dass immer das letzte Punishment genommen wird.
Also: Das ändert nichts am Sachverhalt. Was für einen Sinn hat es, das Letzte zu bekommen? Nur weil dann eine weitere Strafe dazukommt, soll die alte Ungültig sein?!? (PS: Das geht einfach mit einem ORDER BY und LIMIT, du brauchst da kein recursive SELECT)
Der Sinn den Letzten zu bekommen ist, dass ich so die Alte EndTime behalten kann und somit bei einem remute oder Bann der alte überschrieben wird.
Nein, das macht keinen Sinn, denn dann änderst du ja trotzdem den alten Mute oder Bann (indem du ihn invalidierst), nur wird das so nicht in der Datenbank vermerkt, dass die Mute/Bannzeit dann durch das Überschreiben automatisch geändert wurde. Das ist mein Problem damit. Zudem sollte meiner Meinung nach der Längere (mit weiter entfernterer EndTime) Mute/Bann Priorität über andere Mutes/Banns haben.
Also ich habe mir das System so überlegt: Ich mache einen Mute/Bann und dieser kann dann später von irgendjemanden mit einem erneuten Mute/Bann verkürzt oder entfernt werden, wobei als der aktuelle Mute/Bann immer der neuste genommen wird und nicht der längste, weil der Plan mit dieser Tabelle ist ja das alles auch Protokolliert wird. Und weshalb will ich immer den Aktuellsten brauch.
Dann möchte ich, dass du dann die EndZeit des vorherigen Banns dann auf die StartZeit des neuen Banns setzt, damit das auch für sich so korrekt protokolliert ist, und nicht, dass dann über irgendeine ID das ganze Sortiert wird, wenn du bereits einen StartTimestamp hast (nach dem du i.ü. auch sortieren könntest).
Nein genau das möchte ich nicht. Ich möchte gerne im nachhinein sehen, wie lange er eigentlich gemutet oder gebannt war. Mit deiner Lösung würdest du Daten, welche wichtig sind und wichtig zum entscheiden über neue Banns/Mutes verändert, womit diese eh nicht mehr aussagekräftig sind!
Nein, weil er war ja dann nicht mehr so lange gebannt/gemutet! Die Daten sind damit faktisch verändert worden, nur steht dass dann nicht mehr in der Datenbank! Sein Bann/Mute war solange angedacht, aber dann ja verkürzt worden! Entweder also es wird der längste Bann genommen, oder der neuste Bann verändert ggf. den letzten älteren Bann.
Aktuelles Problem: Der Perma Ban Timestamp ist vor allen anderen, das macht mir das Selecten des Aktiven Banns um einiger Schwieriger-.
@ -0,0 +34,4 @@
return null;
return new Punishment(set);
} catch (SQLException throwable) {
throwable.printStackTrace();
Nicht extra den Stacktrace "printen", das passiert automatisch bei der Fehlermeldung & ist dann auch richtig als [ERROR] markiert. S o spammst du nur die Konsole zu
@ -0,0 +40,4 @@
}
public static Map<PunishmentType, Punishment> getPunishmentsByPlayer(int user) {
ResultSet set = SQL.select("SELECT * FROM `Punishments` WHERE `PunishmentId` IN (SELECT MAX(`PunishmentId`) FROM Punishments WHERE UserId = ? GROUP BY Type)", user);
Siehe oben.
@ -0,0 +81,4 @@
private final String reason;
private final int id;
private final int punisher;
private final boolean perma;
Gut, ist eher eine Stilfrage, ob man da ein separates Feld nimmt, oder ob man das nicht wie z.B. bisher über endTime macht.
@ -0,0 +131,4 @@
Mute;
public String toDb() {
return name().toLowerCase();
Schreib doch nur name(), dann kannst du beim Type-Getten auch einfach valueOf() machen.
@ -0,0 +135,4 @@
}
public static PunishmentType getTypeFromDB(String str) {
return Arrays.stream(values()).filter(punishmentType -> punishmentType.name().equalsIgnoreCase(str)).collect(Collectors.toList()).get(0);
Siehe toDb()
@ -169,2 +152,2 @@
return false;
}
return punishments.containsKey(Punishment.PunishmentType.Ban) &&
(punishments.get(Punishment.PunishmentType.Ban).getEndTime().after(new Date()) || punishments.get(Punishment.PunishmentType.Ban).isPerma());
Nicht multiple get() auf die Map machen, wenn dann einmal .get(), dann auf null überprüfen (z.B. kein Bann vorliegend), dann Zeiten prüfen.
Das macht das ganze dann auch übersichtlicher.
Und ggf. eine Methode isCurrent() in Punishment implementieren, wo angezeigt wird, ob die Strafe derzeit aktiv ist, das macht es einfacher und weniger Code duplication.
@ -223,2 +197,2 @@
muteTime = time;
this.muteReason = muteReason;
public void mute(Timestamp time, String muteReason, int from, boolean perma){
punishments.remove(Punishment.PunishmentType.Mute);
Das fixt das Problem nur temporär, aber nicht in der Datenbank. Du musst entweder das alte Punishment aufräumen (Zeit entsprechend verkürzen) oder beim Selecten einer Strafe automatisch immer die am längesten noch andauernde Strafe SELECTen (dann würdest du mehrere Punishments zeitgleich handeln können).
@ -55,3 +55,3 @@
public static final String SERVER_TEAMCHAT_PREFIX = "§8STC §e";
public static final String TEAMCHAT_PREFIX = "§8TC §e";
public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("dd.MM.yyyy");
public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("HH:mm dd.MM.yyyy");
Ich glaube, Datum Uhrzeit statt Uhrzeit Datum wäre grammatikalisch besser.
@ -58,2 +58,2 @@
BungeeCore.send(sender, BungeeCore.CHAT_PREFIX + "Du hast " + target.getUserName() + " gebannt. Grund: §c" + msg);
target.ban(banTime, msg);
target.ban(banTime, msg, SteamwarUser.get(sender.getName()).getId(), args[1].equalsIgnoreCase("perma"));
ServerTeamchatCommand.sendToTeam(BungeeCore.CHAT_PREFIX + target.getUserGroup().getColorCode() + target.getUserName() + "§c wurde von " + SteamwarUser.get(sender.getName()).getUserGroup().getColorCode() + sender.getName() + " §c" + (args[1].equalsIgnoreCase("perma")?"Permanent":"bis zum " + banTime.toLocalDateTime().format(BungeeCore.DATE_FORMAT)) + " gebannt. §f§lGrund: §f" + banReason);
In internen Messages musst du nicht die Person colorcoden.
@ -0,0 +63,4 @@
}
}
public static Punishment createPunishment(int user, int executor, PunishmentType type, String reason, Timestamp endTime, Boolean perma) {
Warum Boolean und nicht boolean?
@ -163,3 +154,1 @@
return true;
} else {
SQL.update("UPDATE UserData SET BanTime = NULL, BanReason = '' WHERE id = ?", id);
if(!isCurrent(punishments.get(Punishment.PunishmentType.Ban))) {
Das funktioniert nicht so ganz, da der SteamwarUser-Cache einmal pro Stunde geleert wird. Daher kann es sein, dass der Key rausfällt, ohne dass je die BannedUserIPs geleert werden. Damit aber auch nicht ständig bei allen die BannedUserIPs gelöscht werden, brauchst du irgendwo ein Indikator, ob die Strafe abgesessen wurde.
@ -224,1 +211,3 @@
this.muteReason = muteReason;
public void mute(Timestamp time, String muteReason, int from, boolean perma){
if(isMuted()) {
punishments.get(Punishment.PunishmentType.Ban).updateEndTime(from, muteReason, time, perma);
Whoops! Mute/Ban.
Achja: Immernoch das MergeConflict-Potential mit dem MoreMultilingualTransfer.
Jetzt hat er keinen Merge konflikt mehr
@ -157,2 +150,4 @@
}
public ProxiedPlayer getPlayer() {
return BungeeCore.get().getProxy().getPlayer(uuid);
Wenn schon, dann über ProxyServer.getInstance().getPlayer(), Problem: Diese Funktion kann den Anschein erwecken, immer einen ProxiedPlayer zurückgeben zu können, was nicht der Fall ist, daher würde ich diese Funktion entfernen.
Dann wurden wir mal ein Cache von den Sprachen gebrauchen, weil wenn der Spieler nicht Online ist weiß das Programm nicht auf welcher Sprache es bannen soll.
Wenn der Spieler nicht online ist, kommt hier null zurück. Und ja, das brauchen wir auch.
Hier besteht weiterhin das Problem: Wenn der User nicht online ist, kommt hier null zurück. Bitte diese Methode hier entfernen, das ist wenn überall woanders im Code. Und nutze eher ProxyServer.getInstance() als BungeeCore.get().getProxy()
Chaoscaot könnte man in dieses System auch die kicks mit auf nehmen?
Kicks haben damit nix zu tun. Kicks sind nicht als längerfristige Bestrafung gedacht, daher: Nein.
Ich finde trotzdem, dass dieses wichtig ist, weil man dann auch mal nachgucken kann das jmd gegickt wurde und warum genau. Und dann auch einfacher herausfinden kann wie lang man nun bannen muten oder wie auch immer soll, wenn leute vieles schon angestellt haben. Deswegen!
Nein, wenn Kicks zu Bestrafungszwecken verwendet werden, werde ich sie ganz entfernen, weil dafür sind sie nicht gedacht.
@ -78,0 +74,4 @@
BungeeCore.send(player, "§7Strafen: ");
for (Punishment punishment : Punishment.getAllPunishmentsOfPlayer(user.getId())) {
BungeeCore.send(player, "§7" + SteamwarUser.get(punishment.getPunisher()).getUserName() + "§8» §f§l" + punishment.getType().name() + ": §e"
+ punishment.getStartTime().toLocalDateTime().format(BungeeCore.DATE_FORMAT) + " - " + (punishment.isPerma()?"Perma":punishment.getEndTime().toLocalDateTime().format(BungeeCore.DATE_FORMAT)) + " §c" + punishment.getReason());
Wenn wir die Mute & Bannsachen schon Multilingual haben, sollten wir auch das Multilingual machen. Um das Timestamp-Formatting müsste sich dann glaube ich auch das ML-Framework kümmern.
Dafür wurden wir dann ein Cache wo wir die Sprache speichern könnten, weil sonst müsste man dies von dem gemacht, der den Spieler bannt
Hier in dem Fall ist das Ziel klar player. Und player hat eine Sprache. Den Cache bräuchten wir wenn für den BanListener, aber nicht hier. Daher kann das schon mit umgezogen werden.
@ -75,3 +75,3 @@
player.disconnect(BungeeCore.stringToText("§7Deaktiviere den Mod §e" + mods.get(0).getModName() + "§7, um weiter auf §eSteam§8War §7spielen zu können."));
else{
user.ban(Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), "Versuchte Benutzung des Mods " + mods.get(0).getModName());
user.ban(Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), "Versuchte Benutzung des Mods " + mods.get(0).getModName(), 0, false);
Bitte ML
@ -85,3 +85,3 @@
player.disconnect(BungeeCore.stringToText("§7Deaktiviere die Mods\n§e" + sb.toString() + "§7um weiter auf §eSteam§8War §7spielen zu können."));
else{
user.ban(Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), "Versuchte Benutzung der Mods\n" + sb.toString());
user.ban(Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), "Versuchte Benutzung der Mods\n" + sb.toString(), 0, false);
Bitte ML
@ -0,0 +43,4 @@
public static Map<PunishmentType, Punishment> getPunishmentsOfPlayer(int user) {
Map<PunishmentType, Punishment> punishmentMap = new HashMap<>();
for (PunishmentType type : PunishmentType.values()) {
Punishment punishment = getPunishmentOfPlayer(user, type);
Da das immer aufgerufen wird, wenn wir einen SW-User brauchen (brauchen wir häufig): Bitte auf einmal beide möglichen Punishments holen und nicht nacheinander die einzelnen PunishmentTypes. Die Datenbank braucht da nämlich immer ein paar ms.
Immer noch zu fixen.
@ -184,0 +170,4 @@
return isCurrent(punishments.get(Punishment.PunishmentType.Mute));
}
private boolean isCurrent(Punishment punishment) {
Die Methode scheint mir eher in Punishment zu passen.
@ -189,3 +181,2 @@
} else {
return BungeeCore.stringToText(BungeeCore.CHAT_PREFIX + " Du bist bis zum " +
banTime.toLocalDateTime().format(BungeeCore.DATE_FORMAT) + " gebannt. §r§lGrund§r: §c" + banReason);
return BungeeCore.stringToText(Message.parsePrefixed("BANNED_MESSAGE_UNTIL", getPlayer(), punishment.getEndTime().toLocalDateTime().format(BungeeCore.DATE_FORMAT),
Ich meine, das ML-Framework müsste selbst (mit Optionen, die in den {} angegeben werden können) Dates oder sogar Timestamps parsen können. Schließlich ist die Datumsnotation in verschiedenen Teilen der Welt unterschiedlich.
@ -198,3 +191,2 @@
} else {
return BungeeCore.stringToText(BungeeCore.CHAT_PREFIX + " Du bist bis zum " +
muteTime.toLocalDateTime().format(BungeeCore.DATE_FORMAT) + " gemuted. §r§lGrund§r: §c" + muteReason);
return BungeeCore.stringToText(Message.parsePrefixed("MUTED_MESSAGE_UNTIL",getPlayer(), punishment.getEndTime().toLocalDateTime().format(BungeeCore.DATE_FORMAT), punishment.getReason()));
Siehe banMessage()
@ -37,3 +38,2 @@
public static TextComponent parseToComponent(String message, boolean prefixed, CommandSender sender, Object... params){
return new TextComponent(TextComponent.fromLegacyText(parse(message, prefixed, sender, params)));
public static TextComponent parseToComponent(String message, boolean prefixed, CommandSender sender, int[] useFormatter, Object... params){
Ich würde mir da wenn wünschen (weil das eine API-Funktion ist), dass es die alte Funktion weiterhin gibt und dazu eine neue mit den neuen Aufrufparametern (damit das System nicht umständlich für Sonderfälle ist). Und dass dann entsprechend die alte Funktion verwendet wird, soweit der Formatter nicht benötigt wird.
@ -79,6 +93,10 @@ public class Message {
send(message, false, sender, type, null, null, params);
}
public static void sendPrefixless(String message, CommandSender sender, ChatMessageType type, int[] useFormatter, Object... params) {
Hier genauso
@ -88,3 +106,3 @@
}
public static void send(String message, boolean prefixed, CommandSender sender, ChatMessageType type, String onHover, ClickEvent onClick, Object... params){
public static void send(String message, boolean prefixed, CommandSender sender, ChatMessageType type, String onHover, ClickEvent onClick, int[] useFormatter, Object... params){
Hier auch.
@ -124,3 +150,3 @@
}
public static void team(String message, ChatMessageType type, Object... params){
public static void team(String message, ChatMessageType type, int[] useFormatter, Object... params){
Arrrg.
@ -58,2 +58,2 @@
Message.send("BAN_MESSAGE_YOU", sender, target.getUserName(), msg);
target.ban(banTime, msg);
target.ban(banTime, msg, SteamwarUser.get(sender.getName()).getId(), args[1].equalsIgnoreCase("perma"));
Message.team("BAN_TEAM_BANNED", new int[]{2}, target.getUserName(), sender.getName(), (args[1].equalsIgnoreCase("perma")?"BAN_PERMA":"BAN_UNTIL"), msg, banTime);
Ok, das gefällt mir doch nicht so ganz mit dem IntArray etc. Evtl. wäre es eleganter, man macht da etwas a la new Message(...equals() ? "BAN_PERMA": "BAN_UNTIL") und wenn das object eine Message ist, (welche sich einfach nur zu merken Braucht, welchen String sie hat, ggf. auch noch parameter) und dann diese Message parst und den String entsprechend einfügt.
@ -77,1 +76,3 @@
player.sendMessage(user.muteMessage());
BungeeCore.send(player, "§7Strafen: ");
for (Punishment punishment : Punishment.getAllPunishmentsOfPlayer(user.getId())) {
BungeeCore.send(player, "§7" + SteamwarUser.get(punishment.getPunisher()).getUserName() + "§8» §f§l" + punishment.getType().name() + ": §e"
Da kannste aber auch mal aufs Multilinguale-System zurückgreifen
@ -0,0 +126,4 @@
getBantime(endTime, this.perma),
getBantime(newUpdate, perma),
newreason);
//TODO Add User
Offenes TODO?
@ -1,5 +1,6 @@
PREFIX=§eSteam§8War»
SPACER=
TIMEFORMAT=dd.MM.yyyy HH:mm
Das TIMEFORMAT sollte hier nicht eingespeichert werden müssen (ist ja auch nur das deutsche Timeformat)
@ -97,0 +101,4 @@
BANNED_MESSAGE_UNTIL=Du bist bis zum {0} gebannt. §r§lGrund§r: §c{1}
MUTE_TEAM_MUTED=§c {0} wurde von {1} {2} gemuted. §f§lGrund: §f{3}
MUTED_MESSAGE_PERMA=§cDu bist permanent gemuted. §r§lGrund§r: §c{0}
MUTED_MESSAGE_UNTIL=Du bist bis zum {0} gemuted. §r§lGrund§r: §c{1}
Können wir bitte im Farbschema bleiben?
@ -45,3 +44,3 @@
user.updateBanIP(event.getConnection().getAddress().getAddress().getHostAddress());
event.setCancelled(true);
event.setCancelReason(user.banMessage());
event.setCancelReason(user.banMessage((ProxiedPlayer) event.getConnection()));
Das geht so leider nicht, da die Connection hier noch kein ProxiedPlayer ist.
@ -0,0 +46,4 @@
Map<PunishmentType, Punishment> punishments = new HashMap<>();
Punishment banPunishment = getPunishmentOfPlayer(user, PunishmentType.Ban);
if(banPunishment != null) punishments.put(PunishmentType.Ban, banPunishment);
Punishment mutePunishment = getPunishmentOfPlayer(user, PunishmentType.Mute);
Da diese Funktion beim Laden eines jeden SWUsers aufgerufen wird: Bitte beide Punishments auf einmal laden.
@ -156,48 +151,53 @@ public class SteamwarUser {
return team;
}
private void loadPunishments() {
Das hier zu softloaden bringt kaum etwas, da bei jedem Join als allererstes der Gebannt-Status abgefragt wird.
@ -184,0 +176,4 @@
return isCurrent(punishments.get(Punishment.PunishmentType.Mute));
}
private boolean isCurrent(Punishment punishment) {
Die Funktion gehört eher public in Punishment
@ -248,2 +257,3 @@
} catch (SQLException throwables) {
throwables.printStackTrace();
throw new SecurityException("Could not load Online Time", throwables);
} catch (NullPointerException e) { //When no Sessions are recorded
Fliegt hier wirklich eine NPE? Sollte durch das Überprüfen auf !set.next() doch abgefangen sein?
Trotzdem gibt COUNT() NULL in der Spalte zurück.
@ -88,2 +89,4 @@
HELP_BAU_TESTARENA=§8/§ebau testarena §8- §7Starte eine Testarena
HELP_BAU_TESTARENA_HOVER=§eTestarena starten
HELP_BAU_BAU=§8/§ehelp bau §8- §7Hilfe zu nützlichen Werkzeugen
HELP_BAU_BAU_HOVER=§eNützliche Zusatzfunktionen
Scheint mir nicht ganz in den PR zu gehören?
@ -99,2 +108,3 @@
BAN_MESSAGE_YOU=§7Du hast §e{0} §7gebannt§8. §7Grund§8: §c{1}
#Ban&Mute-Command
BAN_TEAM_BANNED=§8[§4☣§8]» §c{0} wurde von {1} {2} gebannt. §f§lGrund: §f{3}
Da brauchen wir kein spezielles Präfix. Und so schön du dir das gedacht hast: Die eckigen Klammern machens irgendwie wieder hässlich. ;) (Persönliche Meinung)
@ -101,0 +110,4 @@
BAN_TEAM_BANNED=§8[§4☣§8]» §c{0} wurde von {1} {2} gebannt. §f§lGrund: §f{3}
BANNED_MESSAGE_PERMA=§cDu bist permanent gebannt. §r§lGrund§r: §c{0}
BANNED_MESSAGE_UNTIL=§cDu bist bis zum {0} gebannt. §r§lGrund§r: §c{1}
MUTE_TEAM_MUTED=§8[§4☣§8]» §c{0} wurde von {1} {2} gemuted. §f§lGrund: §f{3}
same
@ -101,0 +114,4 @@
MUTED_MESSAGE_PERMA=§cDu bist permanent gemuted. §r§lGrund§r: §c{0}
MUTED_MESSAGE_UNTIL=§cDu bist bis zum {0} gemuted. §r§lGrund§r: §c{1}
BAN_CHANGED={0}verändert von {1} von {2} auf {3} wegen {4}
BAN_PERMA=Permanent
klein schreiben
@ -149,1 +164,4 @@
CHECK_DECLINED_TEAM=§7Die Schematic §e{0} §7von §e{1} §awurde aufgrund von §e{2} §7abgelehnt!
#WhoisCommand
Ich glaube, das haben wir generell USAGE_WHOIS genannt. Auch wenn SYNTAX ne gute idee ist, sollte das doch im Stil der USAGE messages oben und auch dort oben sein.
Bis auf das (für mich) offensichtliche Problem bin ich ansonsten ganz zufrieden. Würde dich bitten, das ganze einmal auf dem DevBungee auf Herz und Nieren durchzuprüfen & nach Behebung aller noch aufgefallenen Probleme hier soweit drunterschreiben, dass der PR fertig ist. Dann können wir uns (endlich) mal ans mergen machen :).
@ -45,3 +44,3 @@
user.updateBanIP(event.getConnection().getAddress().getAddress().getHostAddress());
event.setCancelled(true);
event.setCancelReason(user.banMessage());
event.setCancelReason(user.banMessage(ProxyServer.getInstance().getPlayer(event.getConnection().getUniqueId())));
Nein, das geht auch so nicht: Der Spieler ist noch nicht verbunden/existent. Du bekommst hier keinen entsprechenden ProxiedPlayer (egal wie) zurück!
Doch das geht! Habe ich schonmal auf dem DevBungee leicht getestet und da hat diese Methode gefunzt.
Mit einer Person, die Nicht online ist? (Login-Sequenz heißt noch nicht online)
Jup, mit einer grad joinenden Person
Hatte mich verklickt, wollte eigentlich (insbesondere wegen des Bugs) nochmal ablehnen.
Inwieweit wurde der PR auf Herz und Nieren geprüft?
👍