From 918ee5ed00a613022f5f5587d8197d8951fa2f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Wed, 9 Oct 2024 14:36:08 +0200 Subject: [PATCH 01/18] updated interfering listener --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 19 +++++++++--------- gradlew.bat | 20 +++++++++---------- .../listener/PlayerInvincibleListener.java | 7 ++++--- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9f4197d..a441313 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index fcb6fca..b740cf1 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..25da30d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/projectStart/listener/PlayerInvincibleListener.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/projectStart/listener/PlayerInvincibleListener.java index 4fd1c30..89e116f 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/projectStart/listener/PlayerInvincibleListener.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/projectStart/listener/PlayerInvincibleListener.java @@ -11,16 +11,17 @@ import org.bukkit.event.entity.FoodLevelChangeEvent; public class PlayerInvincibleListener extends ApplianceListener<ProjectStart> { @EventHandler public void onDamage(EntityDamageEvent event) { - if(event.getEntity() instanceof Player) event.setCancelled(getAppliance().isEnabled()); + if(!(event.getEntity() instanceof Player)) return; + if(getAppliance().isEnabled()) event.setCancelled(true); } @EventHandler public void onHunger(FoodLevelChangeEvent event) { - event.setCancelled(getAppliance().isEnabled()); + if(getAppliance().isEnabled()) event.setCancelled(true); } @EventHandler public void onHit(PrePlayerAttackEntityEvent event) { - event.setCancelled(getAppliance().isEnabled()); + if(getAppliance().isEnabled()) event.setCancelled(true); } } From b1427ac90e980eb043c9b9682fe9a931d45052cc Mon Sep 17 00:00:00 2001 From: Hannes Frommann <elias@elias-mueller.com> Date: Sat, 19 Oct 2024 15:46:34 +0200 Subject: [PATCH 02/18] added playertime command --- .../spawn/appliances/playtime/Playtime.java | 31 +++++++++++++++++++ .../appliances/playtime/PlaytimeCommand.java | 31 +++++++++++++++++++ .../spawn/util/text/DataSizeConverter.java | 14 +++++++++ src/main/resources/plugin.yml | 3 +- 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/Playtime.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/PlaytimeCommand.java diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/Playtime.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/Playtime.java new file mode 100644 index 0000000..d1d6203 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/Playtime.java @@ -0,0 +1,31 @@ +package eu.mhsl.craftattack.spawn.appliances.playtime; + +import eu.mhsl.craftattack.spawn.appliance.Appliance; +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.util.text.DataSizeConverter; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.util.Ticks; +import org.bukkit.OfflinePlayer; +import org.bukkit.Statistic; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Objects; + +public class Playtime extends Appliance { + public Component getFormattedPlayerTime(OfflinePlayer player){ + int playtimeInTicks = player.getStatistic(Statistic.PLAY_ONE_MINUTE); + String playtime = DataSizeConverter.formatSecondsToHumanReadable(playtimeInTicks / Ticks.TICKS_PER_SECOND); + return Component.text() + .append(Component.text("Der Spieler ", NamedTextColor.GRAY)) + .append(Component.text(Objects.requireNonNull(player.getName()))) + .append(Component.text(" hat eine Spielzeit von ", NamedTextColor.GRAY)) + .append(Component.text(playtime, NamedTextColor.GOLD)) + .build(); + } + @Override + protected @NotNull List<ApplianceCommand<?>> commands() { + return List.of(new PlaytimeCommand()); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/PlaytimeCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/PlaytimeCommand.java new file mode 100644 index 0000000..f24e14c --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/PlaytimeCommand.java @@ -0,0 +1,31 @@ +package eu.mhsl.craftattack.spawn.appliances.playtime; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class PlaytimeCommand extends ApplianceCommand.PlayerChecked<Playtime> { + public PlaytimeCommand() { + super("playtime"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { + String playerName = getPlayer().getName(); + if(args.length == 1) { + playerName = args[0]; + } + + OfflinePlayer player = Bukkit.getOfflinePlayer(playerName); + if (!player.hasPlayedBefore()) { + sender.sendMessage(Component.text("Der Spieler existiert nicht!", NamedTextColor.RED)); + return; + } + sender.sendMessage(getAppliance().getFormattedPlayerTime(player)); + } +} \ No newline at end of file diff --git a/src/main/java/eu/mhsl/craftattack/spawn/util/text/DataSizeConverter.java b/src/main/java/eu/mhsl/craftattack/spawn/util/text/DataSizeConverter.java index 2154c3c..43a24a8 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/util/text/DataSizeConverter.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/util/text/DataSizeConverter.java @@ -38,4 +38,18 @@ public class DataSizeConverter { hours %= 60; return String.format("%dd%dh%dm%ds", days, hours, minutes, seconds); } + + public static String formatSecondsToHumanReadable(int seconds) { + if (seconds < 0) return "unsupported"; + + int minutes = seconds / 60; + int hours = minutes / 60; + int days = hours / 24; + + seconds %= 60; + minutes %= 60; + hours %= 60; + + return String.format("%dd %dh %dm %ds", days, hours, minutes, seconds); + } } \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0a3437b..fe67e51 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -41,4 +41,5 @@ commands: maintanance: yearRank: msg: - r: \ No newline at end of file + r: + playtime: From bc84b06f0df35354067bac05cc00ced8870500e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Sat, 19 Oct 2024 18:11:19 +0200 Subject: [PATCH 03/18] added AdminChat --- .../spawn/appliances/adminChat/AdminChat.java | 37 +++++++++++++++++++ .../adminChat/AdminChatCommand.java | 24 ++++++++++++ src/main/resources/plugin.yml | 2 + 3 files changed, 63 insertions(+) create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChat.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChatCommand.java diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChat.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChat.java new file mode 100644 index 0000000..8891bba --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChat.java @@ -0,0 +1,37 @@ +package eu.mhsl.craftattack.spawn.appliances.adminChat; + +import eu.mhsl.craftattack.spawn.appliance.Appliance; +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class AdminChat extends Appliance { + public void sendMessage(Player sender, String message) { + Component privatePrefix = Component + .text("[Admin] ", NamedTextColor.LIGHT_PURPLE) + .clickEvent(ClickEvent.suggestCommand(AdminChatCommand.commandName)); + + Bukkit.getOnlinePlayers().stream() + .filter(player -> player.hasPermission("admin")) + .forEach(player -> { + Component formattedMessage = Component.text() + .append(privatePrefix) + .append(sender.displayName()) + .append(Component.text(" > ", NamedTextColor.DARK_GRAY)) + .append(Component.text(message)) + .build(); + player.sendMessage(formattedMessage); + }); + } + + @Override + protected @NotNull List<ApplianceCommand<?>> commands() { + return List.of(new AdminChatCommand()); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChatCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChatCommand.java new file mode 100644 index 0000000..7adaa72 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChatCommand.java @@ -0,0 +1,24 @@ +package eu.mhsl.craftattack.spawn.appliances.adminChat; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class AdminChatCommand extends ApplianceCommand.PlayerChecked<AdminChat> { + public static final String commandName = "adminchat"; + + public AdminChatCommand() { + super(commandName); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { + if(!sender.hasPermission("admin")) { + return; + } + + String message = String.join(" ", args); + getAppliance().sendMessage(getPlayer(), message); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index fe67e51..4847a79 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -43,3 +43,5 @@ commands: msg: r: playtime: + adminchat: + aliases: [ "sc" ] From 125b604393ae7b0be928e53377d4975cc30761b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Sun, 20 Oct 2024 14:24:12 +0200 Subject: [PATCH 04/18] small refactoring and added missing async task --- .../adminChat/AdminChatCommand.java | 4 +--- .../spawn/appliances/playtime/Playtime.java | 3 ++- .../appliances/playtime/PlaytimeCommand.java | 20 +++++++++---------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChatCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChatCommand.java index 7adaa72..71b2522 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChatCommand.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/adminChat/AdminChatCommand.java @@ -14,9 +14,7 @@ public class AdminChatCommand extends ApplianceCommand.PlayerChecked<AdminChat> @Override protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { - if(!sender.hasPermission("admin")) { - return; - } + if(!sender.hasPermission("admin")) return; String message = String.join(" ", args); getAppliance().sendMessage(getPlayer(), message); diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/Playtime.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/Playtime.java index d1d6203..6a59694 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/Playtime.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/Playtime.java @@ -14,7 +14,7 @@ import java.util.List; import java.util.Objects; public class Playtime extends Appliance { - public Component getFormattedPlayerTime(OfflinePlayer player){ + public Component getFormattedPlaytime(OfflinePlayer player) { int playtimeInTicks = player.getStatistic(Statistic.PLAY_ONE_MINUTE); String playtime = DataSizeConverter.formatSecondsToHumanReadable(playtimeInTicks / Ticks.TICKS_PER_SECOND); return Component.text() @@ -24,6 +24,7 @@ public class Playtime extends Appliance { .append(Component.text(playtime, NamedTextColor.GOLD)) .build(); } + @Override protected @NotNull List<ApplianceCommand<?>> commands() { return List.of(new PlaytimeCommand()); diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/PlaytimeCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/PlaytimeCommand.java index f24e14c..03cffc7 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/PlaytimeCommand.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/playtime/PlaytimeCommand.java @@ -1,5 +1,6 @@ package eu.mhsl.craftattack.spawn.appliances.playtime; +import eu.mhsl.craftattack.spawn.Main; import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -16,16 +17,15 @@ public class PlaytimeCommand extends ApplianceCommand.PlayerChecked<Playtime> { @Override protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { - String playerName = getPlayer().getName(); - if(args.length == 1) { - playerName = args[0]; - } + String playerName = args.length == 1 ? args[0] : getPlayer().getName(); - OfflinePlayer player = Bukkit.getOfflinePlayer(playerName); - if (!player.hasPlayedBefore()) { - sender.sendMessage(Component.text("Der Spieler existiert nicht!", NamedTextColor.RED)); - return; - } - sender.sendMessage(getAppliance().getFormattedPlayerTime(player)); + Bukkit.getScheduler().runTaskAsynchronously(Main.instance(), () -> { + OfflinePlayer player = Bukkit.getOfflinePlayer(playerName); + if (!player.hasPlayedBefore()) { + sender.sendMessage(Component.text("Der Spieler existiert nicht!", NamedTextColor.RED)); + return; + } + sender.sendMessage(getAppliance().getFormattedPlaytime(player)); + }); } } \ No newline at end of file From e7075140e35e9102c9a218190a1997d6a53e27d3 Mon Sep 17 00:00:00 2001 From: lars <larslukasneuhaus@gmx.de> Date: Tue, 5 Nov 2024 20:48:42 +0100 Subject: [PATCH 05/18] added anticheat info command --- .../spawn/appliances/acInform/AcInform.java | 132 ++++++++++++++++++ .../appliances/acInform/AcInformCommand.java | 18 +++ src/main/resources/plugin.yml | 1 + 3 files changed, 151 insertions(+) create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInformCommand.java diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java new file mode 100644 index 0000000..bd976c3 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java @@ -0,0 +1,132 @@ +package eu.mhsl.craftattack.spawn.appliances.acInform; + +import eu.mhsl.craftattack.spawn.appliance.Appliance; +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentBuilder; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class AcInform extends Appliance { + public void processCommand(@NotNull String[] args) { + String anticheatName = null; + String playerName = null; + String checkName = null; + Integer violationCount = null; + + for(int i = 0; i < args.length; i++) { + if(!args[i].startsWith("--")) continue; + if(i == args.length-1) continue; + String nextArgument = args[i+1]; + if(nextArgument.startsWith("--")) continue; + + switch(args[i]) { + case "--anticheatName" -> anticheatName = nextArgument; + case "--playerName" -> playerName = nextArgument; + case "--check" -> checkName = nextArgument; + case "--violationCount" -> violationCount = Integer.valueOf(nextArgument); + } + } + + this.notifyAdmins(anticheatName, playerName, checkName, violationCount); + } + + public void notifyAdmins(@Nullable String anticheatName, @Nullable String playerName, @Nullable String checkName, @Nullable Integer violationCount) { + ComponentBuilder<TextComponent, TextComponent.Builder> component = Component.text(); + Component prefix = Component.text("# ", NamedTextColor.DARK_RED); + NamedTextColor textColor = NamedTextColor.GRAY; + + if(playerName == null || playerName.isBlank()) return; + + if(anticheatName != null && !anticheatName.isBlank()) { + component.append( + Component.newline() + .append(prefix) + .append(Component.text("[", textColor)) + .append(Component.text("Anticheat", NamedTextColor.RED)) + .append(Component.text("] ", textColor)) + .append(Component.text(anticheatName, NamedTextColor.WHITE)) + .append(Component.text(":", textColor)) + ); + } + + component.append( + Component.newline() + .append(prefix) + .append(Component.text("Player ", textColor)) + .append(Component.text(playerName, NamedTextColor.WHITE)) + .append(Component.text(" ")) + ); + + if(checkName == null || checkName.isBlank()) { + component.append(Component.text("got detected by Anticheat", textColor)); + } else if(violationCount != null){ + component.append( + Component.text("failed ", textColor) + .append(Component.text(String.format("%sx ", violationCount), NamedTextColor.WHITE)) + .append(Component.text("'", textColor)) + .append(Component.text(checkName, NamedTextColor.WHITE)) + .append(Component.text("'", textColor)) + ); + } else { + component.append( + Component.text("failed ", textColor) + .append(Component.text("'", textColor)) + .append(Component.text(checkName, NamedTextColor.WHITE)) + .append(Component.text("'", textColor)) + ); + } + + component.append( + Component.newline() + .append(prefix) + + .append(Component.text("[", NamedTextColor.GRAY)) + .append(Component.text("Report", NamedTextColor.GOLD)) + .append(Component.text("] ", NamedTextColor.GRAY)) + .clickEvent(ClickEvent.suggestCommand(String.format("/report %s anticheat %s flagged %s", playerName, anticheatName, checkName))) + ); + + component.append( + Component.text(" [", NamedTextColor.GRAY) + .append(Component.text("Kick", NamedTextColor.GOLD)) + .append(Component.text("] ", NamedTextColor.GRAY)) + .clickEvent(ClickEvent.suggestCommand(String.format("/kick %s", playerName))) + ); + + component.append( + Component.text(" [", NamedTextColor.GRAY) + .append(Component.text("Panic Ban", NamedTextColor.GOLD)) + .append(Component.text("]", NamedTextColor.GRAY)) + .clickEvent(ClickEvent.suggestCommand(String.format("/panicban %s", playerName))) + ); + + component.append( + Component.text(" [", NamedTextColor.GRAY) + .append(Component.text("Teleport", NamedTextColor.GOLD)) + .append(Component.text("]", NamedTextColor.GRAY)) + .clickEvent(ClickEvent.suggestCommand(String.format("/tp %s", playerName))) + ); + + component.appendNewline(); + TextComponent finalMessage = component.build(); + + Bukkit.getOnlinePlayers().stream() + .filter(player -> player.hasPermission("admin")) + .forEach(player -> player.sendMessage(finalMessage)); + + } + + @Override + protected @NotNull List<ApplianceCommand<?>> commands() { + return List.of( + new AcInformCommand() + ); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInformCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInformCommand.java new file mode 100644 index 0000000..15707e5 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInformCommand.java @@ -0,0 +1,18 @@ +package eu.mhsl.craftattack.spawn.appliances.acInform; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class AcInformCommand extends ApplianceCommand<AcInform> { + public AcInformCommand() { + super("acInform"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { +// if(sender instanceof Player) throw new ApplianceCommand.Error("Dieser Command ist nicht für Spieler!"); + getAppliance().processCommand(args); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 4847a79..f7108d5 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -45,3 +45,4 @@ commands: playtime: adminchat: aliases: [ "sc" ] + acInform: From 01d1926104b9578d3a62b47cd93d904855366543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Tue, 5 Nov 2024 21:23:43 +0100 Subject: [PATCH 06/18] removed webserver shutdown --- src/main/java/eu/mhsl/craftattack/spawn/Main.java | 5 ++--- src/main/java/eu/mhsl/craftattack/spawn/api/HttpServer.java | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/Main.java b/src/main/java/eu/mhsl/craftattack/spawn/Main.java index 56d8198..00f837d 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/Main.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/Main.java @@ -19,7 +19,6 @@ public final class Main extends JavaPlugin { private static Logger logger; private List<Appliance> appliances; - private HttpServer httpApi; @Override public void onEnable() { @@ -62,7 +61,7 @@ public final class Main extends JavaPlugin { Main.logger().info(String.format("Initialized %d appliances!", appliances.size())); Main.logger().info("Starting HTTP API..."); - this.httpApi = new HttpServer(); + new HttpServer(); getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); Main.logger().info("Startup complete!"); @@ -76,7 +75,7 @@ public final class Main extends JavaPlugin { appliance.onDisable(); appliance.destruct(this); }); - this.httpApi.stop(); + HandlerList.unregisterAll(this); Bukkit.getScheduler().cancelTasks(this); Main.logger().info("Disabled " + appliances.size() + " appliances!"); diff --git a/src/main/java/eu/mhsl/craftattack/spawn/api/HttpServer.java b/src/main/java/eu/mhsl/craftattack/spawn/api/HttpServer.java index 4961f1d..412d95b 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/api/HttpServer.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/api/HttpServer.java @@ -24,10 +24,6 @@ public class HttpServer { Main.instance().getAppliances().forEach(appliance -> appliance.httpApi(new ApiBuilder(appliance))); } - public void stop() { - Spark.stop(); - } - public record Response(Status status, Object error, Object response) { public enum Status { FAILURE, From 3abf5a95e8c64a43ae6b86bbde446cea5c35c6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Tue, 5 Nov 2024 21:24:06 +0100 Subject: [PATCH 07/18] updated maintenance command feedback --- .../appliances/maintenance/MaintenanceCommand.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/MaintenanceCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/MaintenanceCommand.java index 9372b17..d23e3e2 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/MaintenanceCommand.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/MaintenanceCommand.java @@ -1,6 +1,8 @@ package eu.mhsl.craftattack.spawn.appliances.maintenance; import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -18,9 +20,14 @@ public class MaintenanceCommand extends ApplianceCommand<Maintenance> { @Override protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { - if(args.length != 1 || !arguments.containsKey(args[0])) throw new Error("Argument 'enable' oder 'disable' gefordert!"); - getAppliance().setState(arguments.get(args[0])); - sender.sendMessage(String.format("Maintanance: %b", getAppliance().isInMaintenance())); + if(args.length == 1 && arguments.containsKey(args[0])) { + getAppliance().setState(arguments.get(args[0])); + sender.sendMessage(Component.text("Maintanance mode updated!", NamedTextColor.GREEN)); + } + sender.sendMessage(Component.text( + String.format("Maintanance mode is %b", getAppliance().isInMaintenance()), + NamedTextColor.GOLD + )); } @Override From e8534b42aca7a0788840e4f50358a49066453a67 Mon Sep 17 00:00:00 2001 From: lars <larslukasneuhaus@gmx.de> Date: Tue, 5 Nov 2024 22:28:11 +0100 Subject: [PATCH 08/18] prevented players from using ac inform command --- .../craftattack/spawn/appliances/acInform/AcInformCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInformCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInformCommand.java index 15707e5..149cd46 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInformCommand.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInformCommand.java @@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.appliances.acInform; import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class AcInformCommand extends ApplianceCommand<AcInform> { @@ -12,7 +13,7 @@ public class AcInformCommand extends ApplianceCommand<AcInform> { @Override protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { -// if(sender instanceof Player) throw new ApplianceCommand.Error("Dieser Command ist nicht für Spieler!"); + if(sender instanceof Player) throw new ApplianceCommand.Error("Dieser Command ist nicht für Spieler!"); getAppliance().processCommand(args); } } From 0a7052b6f5276fe91959f1bd5a4ff9d31fd33998 Mon Sep 17 00:00:00 2001 From: lars <larslukasneuhaus@gmx.de> Date: Wed, 6 Nov 2024 10:29:20 +0100 Subject: [PATCH 09/18] added error message for missing player name AcInform --- .../eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java index bd976c3..336ad42 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java @@ -42,7 +42,7 @@ public class AcInform extends Appliance { Component prefix = Component.text("# ", NamedTextColor.DARK_RED); NamedTextColor textColor = NamedTextColor.GRAY; - if(playerName == null || playerName.isBlank()) return; + if(playerName == null || playerName.isBlank()) throw new ApplianceCommand.Error("acinform command needs a player (--playerName)"); if(anticheatName != null && !anticheatName.isBlank()) { component.append( From fd902f4ec62bd279206e6fa6d8b118bd6b094ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Sun, 10 Nov 2024 12:23:44 +0100 Subject: [PATCH 10/18] updated maintenance kick message --- .../maintenance/PreventMaintenanceJoinListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/PreventMaintenanceJoinListener.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/PreventMaintenanceJoinListener.java index 9990d23..aacc3bd 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/PreventMaintenanceJoinListener.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/PreventMaintenanceJoinListener.java @@ -12,9 +12,9 @@ public class PreventMaintenanceJoinListener extends ApplianceListener<Maintenanc if(event.getPlayer().hasPermission("bypassMaintainance")) return; DisconnectInfo disconnectInfo = new DisconnectInfo( - "Wartunsarbeiten", + "Server für Spieler nicht verfügbar", "Zurzeit können nur Admins dem Server beitreten!", - "Bitte warte bis die Warungsarbeiten wieder deaktiviert werden.", + "Bitte versuche es später erneut.", event.getPlayer().getUniqueId() ); From 0f976d2316e312e4c4e8d402ce896728e31ec73a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Sun, 10 Nov 2024 17:28:02 +0100 Subject: [PATCH 11/18] added infobars --- .../spawn/appliances/infoBars/Bar.java | 67 ++++++++++++++ .../appliances/infoBars/InfoBarCommand.java | 32 +++++++ .../spawn/appliances/infoBars/InfoBars.java | 91 +++++++++++++++++++ .../infoBars/ShowPreviousBarsListener.java | 12 +++ .../appliances/infoBars/bars/MsptBar.java | 50 ++++++++++ .../infoBars/bars/PlayerCounterBar.java | 44 +++++++++ .../appliances/infoBars/bars/TpsBar.java | 48 ++++++++++ src/main/resources/plugin.yml | 1 + 8 files changed, 345 insertions(+) create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/Bar.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/InfoBarCommand.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/InfoBars.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/ShowPreviousBarsListener.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/MsptBar.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/PlayerCounterBar.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/TpsBar.java diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/Bar.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/Bar.java new file mode 100644 index 0000000..503a674 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/Bar.java @@ -0,0 +1,67 @@ +package eu.mhsl.craftattack.spawn.appliances.infoBars; + +import eu.mhsl.craftattack.spawn.Main; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.util.Ticks; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitTask; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; + +public abstract class Bar { + private BossBar bossBar; + private final BukkitTask updateTask; + + public Bar() { + long refreshRateInTicks = this.refresh().get(ChronoUnit.SECONDS) * Ticks.TICKS_PER_SECOND; + this.updateTask = Bukkit.getScheduler().runTaskTimerAsynchronously( + Main.instance(), + this::update, + refreshRateInTicks, + refreshRateInTicks + ); + } + + public BossBar getBossBar() { + if(this.bossBar == null) this.bossBar = this.createBar(); + return this.bossBar; + } + + private BossBar createBar() { + return BossBar.bossBar( + this.title(), + this.correctedProgress(), + this.color(), + this.overlay() + ); + } + + private void update() { + if(this.bossBar == null) return; + + this.beforeRefresh(); + this.bossBar.name(this.title()); + this.bossBar.progress(this.correctedProgress()); + this.bossBar.color(this.color()); + this.bossBar.overlay(this.overlay()); + } + + public void stopUpdate() { + this.updateTask.cancel(); + } + + private float correctedProgress() { + return Math.clamp(this.progress(), 0, 1); + } + + protected void beforeRefresh() {} + protected abstract Duration refresh(); + protected abstract String name(); + + protected abstract Component title(); + protected abstract float progress(); + protected abstract BossBar.Color color(); + protected abstract BossBar.Overlay overlay(); +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/InfoBarCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/InfoBarCommand.java new file mode 100644 index 0000000..d3aa097 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/InfoBarCommand.java @@ -0,0 +1,32 @@ +package eu.mhsl.craftattack.spawn.appliances.infoBars; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class InfoBarCommand extends ApplianceCommand.PlayerChecked<InfoBars> { + public InfoBarCommand() { + super("infobar"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { + if(args.length == 0) throw new Error("<show|hide|hideall> [bar name]"); + switch(args[0]) { + case "hideAll" -> getAppliance().hideAll(getPlayer()); + case "show" -> getAppliance().show(getPlayer(), args[1]); + case "hide" -> getAppliance().hide(getPlayer(), args[1]); + default -> throw new Error("Erlaubte Optionen sind 'show', 'hide', 'hideAll'!"); + } + } + + @Override + public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if(args.length == 1) return List.of("show", "hide", "hideAll"); + return getAppliance().getInfoBars().stream().map(Bar::name).toList(); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/InfoBars.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/InfoBars.java new file mode 100644 index 0000000..5e08c60 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/InfoBars.java @@ -0,0 +1,91 @@ +package eu.mhsl.craftattack.spawn.appliances.infoBars; + +import eu.mhsl.craftattack.spawn.Main; +import eu.mhsl.craftattack.spawn.appliance.Appliance; +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.appliances.infoBars.bars.MsptBar; +import eu.mhsl.craftattack.spawn.appliances.infoBars.bars.PlayerCounterBar; +import eu.mhsl.craftattack.spawn.appliances.infoBars.bars.TpsBar; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class InfoBars extends Appliance { + private final NamespacedKey infoBarKey = new NamespacedKey(Main.instance(), "infobars"); + private final List<Bar> infoBars = List.of( + new TpsBar(), + new MsptBar(), + new PlayerCounterBar() + ); + + public void showAll(Player player) { + this.getStoredBars(player).forEach(bar -> this.show(player, bar)); + } + + public void hideAll(Player player) { + this.getStoredBars(player).forEach(bar -> this.hide(player, bar)); + this.setStoredBars(player, List.of()); + } + + public void show(Player player, String bar) { + this.validateBarName(bar); + List<String> existingBars = new ArrayList<>(this.getStoredBars(player)); + existingBars.add(bar); + player.showBossBar(this.getBarByName(bar).getBossBar()); + this.setStoredBars(player, existingBars); + } + + public void hide(Player player, String bar) { + this.validateBarName(bar); + List<String> existingBars = new ArrayList<>(this.getStoredBars(player)); + existingBars.remove(bar); + player.hideBossBar(this.getBarByName(bar).getBossBar()); + this.setStoredBars(player, existingBars); + } + + private List<String> getStoredBars(Player player) { + PersistentDataContainer container = player.getPersistentDataContainer(); + if(!container.has(infoBarKey)) return List.of(); + return container.get(infoBarKey, PersistentDataType.LIST.strings()); + } + + private void setStoredBars(Player player, List<String> bars) { + player.getPersistentDataContainer().set(infoBarKey, PersistentDataType.LIST.strings(), bars); + } + + private Bar getBarByName(String name) { + return infoBars.stream() + .filter(bar -> bar.name().equalsIgnoreCase(name)) + .findFirst() + .orElse(null); + } + + private void validateBarName(String name) { + if(getBarByName(name) == null) throw new ApplianceCommand.Error(String.format("Ungültiger infobar name '%s'", name)); + } + + public List<Bar> getInfoBars() { + return infoBars; + } + + @Override + public void onDisable() { + infoBars.forEach(Bar::stopUpdate); + } + + @Override + protected @NotNull List<Listener> listeners() { + return List.of(new ShowPreviousBarsListener()); + } + + @Override + protected @NotNull List<ApplianceCommand<?>> commands() { + return List.of(new InfoBarCommand()); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/ShowPreviousBarsListener.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/ShowPreviousBarsListener.java new file mode 100644 index 0000000..fa5006a --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/ShowPreviousBarsListener.java @@ -0,0 +1,12 @@ +package eu.mhsl.craftattack.spawn.appliances.infoBars; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceListener; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; + +public class ShowPreviousBarsListener extends ApplianceListener<InfoBars> { + @EventHandler + public void onJoin(PlayerJoinEvent event) { + getAppliance().showAll(event.getPlayer()); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/MsptBar.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/MsptBar.java new file mode 100644 index 0000000..abdc4e0 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/MsptBar.java @@ -0,0 +1,50 @@ +package eu.mhsl.craftattack.spawn.appliances.infoBars.bars; + +import eu.mhsl.craftattack.spawn.appliances.infoBars.Bar; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; + +import java.time.Duration; + +public class MsptBar extends Bar { + @Override + protected Duration refresh() { + return Duration.ofSeconds(1); + } + + @Override + protected String name() { + return "mspt"; + } + + @Override + protected Component title() { + return Component.text() + .append(Component.text("M")) + .append(Component.text("illi", NamedTextColor.GRAY)) + .append(Component.text("S")) + .append(Component.text("econds ", NamedTextColor.GRAY)) + .append(Component.text("P")) + .append(Component.text("er ", NamedTextColor.GRAY)) + .append(Component.text("T")) + .append(Component.text("ick", NamedTextColor.GRAY)) + .build(); + } + + @Override + protected float progress() { + return Bukkit.getServer().getTickTimes()[0] / 50f; + } + + @Override + protected BossBar.Color color() { + return BossBar.Color.YELLOW; + } + + @Override + protected BossBar.Overlay overlay() { + return BossBar.Overlay.NOTCHED_10; + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/PlayerCounterBar.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/PlayerCounterBar.java new file mode 100644 index 0000000..eabc4bb --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/PlayerCounterBar.java @@ -0,0 +1,44 @@ +package eu.mhsl.craftattack.spawn.appliances.infoBars.bars; + +import eu.mhsl.craftattack.spawn.Main; +import eu.mhsl.craftattack.spawn.appliances.infoBars.Bar; +import eu.mhsl.craftattack.spawn.appliances.playerlimit.PlayerLimit; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; + +import java.time.Duration; + +public class PlayerCounterBar extends Bar { + @Override + protected Duration refresh() { + return Duration.ofSeconds(3); + } + + @Override + protected String name() { + return "playerCounter"; + } + + @Override + protected Component title() { + return Component.text("Spieler online"); + } + + @Override + protected float progress() { + int maxPlayers = Main.instance().getAppliance(PlayerLimit.class).getLimit(); + int currentPlayers = Bukkit.getOnlinePlayers().size(); + return (float) currentPlayers / maxPlayers; + } + + @Override + protected BossBar.Color color() { + return BossBar.Color.BLUE; + } + + @Override + protected BossBar.Overlay overlay() { + return BossBar.Overlay.NOTCHED_10; + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/TpsBar.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/TpsBar.java new file mode 100644 index 0000000..0e48657 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/TpsBar.java @@ -0,0 +1,48 @@ +package eu.mhsl.craftattack.spawn.appliances.infoBars.bars; + +import eu.mhsl.craftattack.spawn.appliances.infoBars.Bar; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; + +import java.time.Duration; + +public class TpsBar extends Bar { + @Override + protected Duration refresh() { + return Duration.ofSeconds(3); + } + + @Override + protected String name() { + return "tps"; + } + + @Override + protected Component title() { + return Component.text() + .append(Component.text("T")) + .append(Component.text("icks ", NamedTextColor.GRAY)) + .append(Component.text("P")) + .append(Component.text("er ", NamedTextColor.GRAY)) + .append(Component.text("S")) + .append(Component.text("econds", NamedTextColor.GRAY)) + .build(); + } + + @Override + protected float progress() { + return (float) (Bukkit.getTPS()[0] / 20); + } + + @Override + protected BossBar.Color color() { + return BossBar.Color.YELLOW; + } + + @Override + protected BossBar.Overlay overlay() { + return BossBar.Overlay.NOTCHED_20; + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f7108d5..dd31f27 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -46,3 +46,4 @@ commands: adminchat: aliases: [ "sc" ] acInform: + infobar: From 8470115a74f0fb57bcdec824b19910f7f6811e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Sun, 24 Nov 2024 02:33:36 +0100 Subject: [PATCH 12/18] added endPrevent --- .../appliances/endPrevent/EndPrevent.java | 39 +++++++++++++++++++ .../endPrevent/EndPreventCommand.java | 37 ++++++++++++++++++ .../PreventEnderEyeUseListener.java | 23 +++++++++++ .../maintenance/MaintenanceCommand.java | 2 +- src/main/resources/config.yml | 5 ++- src/main/resources/plugin.yml | 1 + 6 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/EndPrevent.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/EndPreventCommand.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/PreventEnderEyeUseListener.java diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/EndPrevent.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/EndPrevent.java new file mode 100644 index 0000000..2013ad9 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/EndPrevent.java @@ -0,0 +1,39 @@ +package eu.mhsl.craftattack.spawn.appliances.endPrevent; + +import eu.mhsl.craftattack.spawn.appliance.Appliance; +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.config.Configuration; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class EndPrevent extends Appliance { + private final String endDisabledKey = "endDisabled"; + private boolean endDisabled; + + public EndPrevent() { + super("endPrevent"); + this.endDisabled = localConfig().getBoolean(endDisabledKey); + } + + public void setEndDisabled(boolean disabled) { + localConfig().set(endDisabledKey, disabled); + Configuration.saveChanges(); + this.endDisabled = disabled; + } + + public boolean isEndDisabled() { + return endDisabled; + } + + @Override + protected @NotNull List<Listener> listeners() { + return List.of(new PreventEnderEyeUseListener()); + } + + @Override + protected @NotNull List<ApplianceCommand<?>> commands() { + return List.of(new EndPreventCommand()); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/EndPreventCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/EndPreventCommand.java new file mode 100644 index 0000000..863b703 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/EndPreventCommand.java @@ -0,0 +1,37 @@ +package eu.mhsl.craftattack.spawn.appliances.endPrevent; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +public class EndPreventCommand extends ApplianceCommand<EndPrevent> { + private final Map<String, Boolean> arguments = Map.of("preventEnd", true, "allowEnd", false); + + public EndPreventCommand() { + super("endPrevent"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { + if(args.length == 1 && arguments.containsKey(args[0])) { + getAppliance().setEndDisabled(arguments.get(args[0])); + sender.sendMessage(Component.text("Setting updated!", NamedTextColor.GREEN)); + } + sender.sendMessage(Component.text( + String.format("The End is %s!", getAppliance().isEndDisabled() ? "open" : "closed"), + NamedTextColor.GOLD + )); + } + + @Override + public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + return arguments.keySet().stream().toList(); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/PreventEnderEyeUseListener.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/PreventEnderEyeUseListener.java new file mode 100644 index 0000000..078c848 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/endPrevent/PreventEnderEyeUseListener.java @@ -0,0 +1,23 @@ +package eu.mhsl.craftattack.spawn.appliances.endPrevent; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceListener; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInteractEvent; + +public class PreventEnderEyeUseListener extends ApplianceListener<EndPrevent> { + @EventHandler + public void onEnderEyeInteraction(PlayerInteractEvent event) { + if(event.getClickedBlock() == null) return; + if(!event.getClickedBlock().getType().equals(Material.END_PORTAL_FRAME)) return; + if(event.getItem() == null) return; + if(!event.getItem().getType().equals(Material.ENDER_EYE)) return; + + if(!getAppliance().isEndDisabled()) return; + + event.setCancelled(true); + event.getPlayer().sendActionBar(Component.text("Das End ist noch nicht freigeschaltet!", NamedTextColor.RED)); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/MaintenanceCommand.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/MaintenanceCommand.java index d23e3e2..38ad1d9 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/MaintenanceCommand.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/maintenance/MaintenanceCommand.java @@ -12,7 +12,7 @@ import java.util.List; import java.util.Map; public class MaintenanceCommand extends ApplianceCommand<Maintenance> { - Map<String, Boolean> arguments = Map.of("enable", true, "disable", false); + private final Map<String, Boolean> arguments = Map.of("enable", true, "disable", false); public MaintenanceCommand() { super("maintanance"); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a6240d1..476f32b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -66,4 +66,7 @@ packselect: author: "Pack Author(s)" url: "https://example.com/download/pack.zip" hash: "" # SHA1 hash of ZIP file (will be auto determined by the server on startup when not set) - icon: "" # base64 player-head texture, can be obtained from sites like https://minecraft-heads.com/ under developers > Value \ No newline at end of file + icon: "" # base64 player-head texture, can be obtained from sites like https://minecraft-heads.com/ under developers > Value + +endPrevent: + endDisabled: true \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index dd31f27..b4a0607 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -47,3 +47,4 @@ commands: aliases: [ "sc" ] acInform: infobar: + endPrevent: From b9f88bc4b2002083d1a2ab2f211d32af40e599a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Sun, 24 Nov 2024 20:06:18 +0100 Subject: [PATCH 13/18] extended infobars, added coloring --- .../appliances/infoBars/bars/MsptBar.java | 17 +++++++++----- .../infoBars/bars/PlayerCounterBar.java | 22 ++++++++++++++----- .../appliances/infoBars/bars/TpsBar.java | 11 ++++++++-- .../spawn/util/statistics/ServerMonitor.java | 12 ++++++++++ .../spawn/util/text/ColorUtil.java | 9 ++++++++ .../spawn/util/text/ComponentUtil.java | 11 ++++------ 6 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/util/statistics/ServerMonitor.java diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/MsptBar.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/MsptBar.java index abdc4e0..60046a5 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/MsptBar.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/MsptBar.java @@ -1,17 +1,18 @@ package eu.mhsl.craftattack.spawn.appliances.infoBars.bars; import eu.mhsl.craftattack.spawn.appliances.infoBars.Bar; +import eu.mhsl.craftattack.spawn.util.statistics.ServerMonitor; +import eu.mhsl.craftattack.spawn.util.text.ColorUtil; import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; import java.time.Duration; public class MsptBar extends Bar { @Override protected Duration refresh() { - return Duration.ofSeconds(1); + return Duration.ofSeconds(3); } @Override @@ -30,21 +31,27 @@ public class MsptBar extends Bar { .append(Component.text("er ", NamedTextColor.GRAY)) .append(Component.text("T")) .append(Component.text("ick", NamedTextColor.GRAY)) + .append(Component.text(": ")) + .append(Component.text(String.format("%.2f", this.currentMSPT()), ColorUtil.msptColor(this.currentMSPT()))) .build(); } @Override protected float progress() { - return Bukkit.getServer().getTickTimes()[0] / 50f; + return this.currentMSPT() / 50f; } @Override protected BossBar.Color color() { - return BossBar.Color.YELLOW; + return BossBar.Color.BLUE; } @Override protected BossBar.Overlay overlay() { - return BossBar.Overlay.NOTCHED_10; + return BossBar.Overlay.PROGRESS; + } + + private float currentMSPT() { + return ServerMonitor.getServerMSPT(); } } diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/PlayerCounterBar.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/PlayerCounterBar.java index eabc4bb..32c6966 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/PlayerCounterBar.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/PlayerCounterBar.java @@ -3,8 +3,10 @@ package eu.mhsl.craftattack.spawn.appliances.infoBars.bars; import eu.mhsl.craftattack.spawn.Main; import eu.mhsl.craftattack.spawn.appliances.infoBars.Bar; import eu.mhsl.craftattack.spawn.appliances.playerlimit.PlayerLimit; +import eu.mhsl.craftattack.spawn.util.text.ColorUtil; import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; import org.bukkit.Bukkit; import java.time.Duration; @@ -22,14 +24,16 @@ public class PlayerCounterBar extends Bar { @Override protected Component title() { - return Component.text("Spieler online"); + TextColor color = ColorUtil.mapGreenToRed(this.getCurrentPlayerCount(), 0, this.getMaxPlayerCount(), true); + return Component.text() + .append(Component.text("Spieler online: ")) + .append(Component.text(this.getCurrentPlayerCount(), color)) + .build(); } @Override protected float progress() { - int maxPlayers = Main.instance().getAppliance(PlayerLimit.class).getLimit(); - int currentPlayers = Bukkit.getOnlinePlayers().size(); - return (float) currentPlayers / maxPlayers; + return (float) this.getCurrentPlayerCount() / this.getMaxPlayerCount(); } @Override @@ -39,6 +43,14 @@ public class PlayerCounterBar extends Bar { @Override protected BossBar.Overlay overlay() { - return BossBar.Overlay.NOTCHED_10; + return BossBar.Overlay.PROGRESS; + } + + private int getCurrentPlayerCount() { + return Bukkit.getOnlinePlayers().size(); + } + + private int getMaxPlayerCount() { + return Main.instance().getAppliance(PlayerLimit.class).getLimit(); } } diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/TpsBar.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/TpsBar.java index 0e48657..0d82b40 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/TpsBar.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/infoBars/bars/TpsBar.java @@ -1,6 +1,7 @@ package eu.mhsl.craftattack.spawn.appliances.infoBars.bars; import eu.mhsl.craftattack.spawn.appliances.infoBars.Bar; +import eu.mhsl.craftattack.spawn.util.text.ColorUtil; import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -28,21 +29,27 @@ public class TpsBar extends Bar { .append(Component.text("er ", NamedTextColor.GRAY)) .append(Component.text("S")) .append(Component.text("econds", NamedTextColor.GRAY)) + .append(Component.text(": ")) + .append(Component.text(String.format("%.2f", this.currentTps()), ColorUtil.tpsColor(this.currentTps()))) .build(); } @Override protected float progress() { - return (float) (Bukkit.getTPS()[0] / 20); + return this.currentTps() / 20; } @Override protected BossBar.Color color() { - return BossBar.Color.YELLOW; + return BossBar.Color.BLUE; } @Override protected BossBar.Overlay overlay() { return BossBar.Overlay.NOTCHED_20; } + + private float currentTps() { + return (float) Bukkit.getTPS()[0]; + } } diff --git a/src/main/java/eu/mhsl/craftattack/spawn/util/statistics/ServerMonitor.java b/src/main/java/eu/mhsl/craftattack/spawn/util/statistics/ServerMonitor.java new file mode 100644 index 0000000..6c3fc89 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/util/statistics/ServerMonitor.java @@ -0,0 +1,12 @@ +package eu.mhsl.craftattack.spawn.util.statistics; + +import org.bukkit.Bukkit; + +import java.util.Arrays; + +public class ServerMonitor { + public static float getServerMSPT() { + long[] times = Bukkit.getServer().getTickTimes(); + return ((float) Arrays.stream(times).sum() / times.length) * 1.0E-6f; + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/util/text/ColorUtil.java b/src/main/java/eu/mhsl/craftattack/spawn/util/text/ColorUtil.java index e64aa99..2fd9f47 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/util/text/ColorUtil.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/util/text/ColorUtil.java @@ -15,4 +15,13 @@ public class ColorUtil { return TextColor.color(Color.getHSBColor(hue / 360, 1f, 1f).getRGB()); } + + public static TextColor msptColor(float mspt) { + if(mspt > 50) return TextColor.color(255, 0, 0); + return ColorUtil.mapGreenToRed(mspt, 25, 60, true); + } + + public static TextColor tpsColor(float tps) { + return ColorUtil.mapGreenToRed(tps, 15, 20, false); + } } diff --git a/src/main/java/eu/mhsl/craftattack/spawn/util/text/ComponentUtil.java b/src/main/java/eu/mhsl/craftattack/spawn/util/text/ComponentUtil.java index 978ddd5..2364b27 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/util/text/ComponentUtil.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/util/text/ComponentUtil.java @@ -1,6 +1,7 @@ package eu.mhsl.craftattack.spawn.util.text; import eu.mhsl.craftattack.spawn.util.statistics.NetworkMonitor; +import eu.mhsl.craftattack.spawn.util.statistics.ServerMonitor; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentBuilder; import net.kyori.adventure.text.TextComponent; @@ -12,7 +13,6 @@ import org.bukkit.entity.Player; import java.awt.*; import java.lang.management.OperatingSystemMXBean; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -55,15 +55,12 @@ public class ComponentUtil { } public static Component getFormattedTickTimes(boolean detailed) { - long[] times = Bukkit.getServer().getTickTimes(); - float mspt = ((float) Arrays.stream(times).sum() / times.length) * 1.0E-6f; + float mspt = ServerMonitor.getServerMSPT(); float roundedMspt = Math.round(mspt * 100f) / 100f; int loadPercentage = (int) (Math.min(100, (mspt / 50.0) * 100)); float roundedTPS = Math.round(Bukkit.getTPS()[0] * 100f) / 100f; - TextColor msptColor = ColorUtil.mapGreenToRed(roundedMspt, 0, 50, true); TextColor percentageColor = ColorUtil.mapGreenToRed(loadPercentage, 80, 100, true); - TextColor tpsColor = ColorUtil.mapGreenToRed(roundedTPS, 15, 20, false); ComponentBuilder<TextComponent, TextComponent.Builder> tickTimes = Component.text() .append(Component.text("Serverlast: ", NamedTextColor.GRAY)) @@ -72,12 +69,12 @@ public class ComponentUtil { if(detailed) { tickTimes - .append(Component.text(roundedMspt + "mspt", msptColor)) + .append(Component.text(roundedMspt + "mspt", ColorUtil.msptColor(mspt))) .append(Component.text(" | ", NamedTextColor.GRAY)); } return tickTimes - .append(Component.text(roundedTPS + "tps", tpsColor)) + .append(Component.text(roundedTPS + "tps", ColorUtil.tpsColor(roundedTPS))) .build(); } From 7e3b043c98e5c7933c149424f28709ea14e469dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Sun, 24 Nov 2024 21:13:25 +0100 Subject: [PATCH 14/18] added afkTag --- .../appliances/afkTag/AfkResetListener.java | 30 ++++++++ .../spawn/appliances/afkTag/AfkTag.java | 71 +++++++++++++++++++ .../appliances/displayName/DisplayName.java | 9 ++- .../spawn/appliances/outlawed/Outlawed.java | 3 +- .../spawn/appliances/yearRank/YearRank.java | 4 +- 5 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkResetListener.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkResetListener.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkResetListener.java new file mode 100644 index 0000000..4c758f9 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkResetListener.java @@ -0,0 +1,30 @@ +package eu.mhsl.craftattack.spawn.appliances.afkTag; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceListener; +import io.papermc.paper.event.player.AsyncChatEvent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; + +public class AfkResetListener extends ApplianceListener<AfkTag> { + @EventHandler + public void onMove(PlayerMoveEvent event) { + getAppliance().resetTiming(event.getPlayer()); + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + getAppliance().resetTiming(event.getPlayer()); + } + + @EventHandler + public void onChat(AsyncChatEvent event) { + getAppliance().resetTiming(event.getPlayer()); + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + getAppliance().resetTiming(event.getPlayer()); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java new file mode 100644 index 0000000..055aa4e --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java @@ -0,0 +1,71 @@ +package eu.mhsl.craftattack.spawn.appliances.afkTag; + +import eu.mhsl.craftattack.spawn.Main; +import eu.mhsl.craftattack.spawn.appliance.Appliance; +import eu.mhsl.craftattack.spawn.appliances.displayName.DisplayName; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.util.Ticks; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.WeakHashMap; + +public class AfkTag extends Appliance implements DisplayName.DisplayNamed { + private final WeakHashMap<Player, Long> afkTimings = new WeakHashMap<>(); + private static final int updateIntervalSeconds = 30; + private static final int afkWhenMillis = 5 * 60 * 1000; + + @Override + public void onEnable() { + Bukkit.getScheduler().runTaskTimerAsynchronously( + Main.instance(), + this::checkAfkPlayers, + Ticks.TICKS_PER_SECOND, + Ticks.TICKS_PER_SECOND * updateIntervalSeconds + ); + } + + public void resetTiming(Player player) { + boolean wasAfk = isAfk(player); + this.afkTimings.put(player, System.currentTimeMillis()); + if (wasAfk) updateAfkPrefix(player); + } + + private void checkAfkPlayers() { + this.afkTimings.keySet().forEach((player) -> { + if(!isAfk(player)) return; + updateAfkPrefix(player); + }); + } + + private boolean isAfk(Player player) { + if(player.isSleeping()) return false; + + long lastTimeActive = this.afkTimings.getOrDefault(player, 0L); + long timeSinceLastActive = System.currentTimeMillis() - lastTimeActive; + return timeSinceLastActive >= afkWhenMillis; + } + + private void updateAfkPrefix(Player player) { + Main.instance().getAppliance(DisplayName.class).update(player); + } + + @Override + public @Nullable Component getNamePrefix(Player p) { + if(isAfk(p)) return Component.text("[\uD83D\uDECC]", NamedTextColor.GRAY) + .hoverEvent(HoverEvent.showText(Component.text("Der Spieler ist AFK"))); + + return null; + } + + @Override + protected @NotNull List<Listener> listeners() { + return List.of(new AfkResetListener()); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/displayName/DisplayName.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/displayName/DisplayName.java index 429cfdd..8271157 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/displayName/DisplayName.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/displayName/DisplayName.java @@ -4,6 +4,7 @@ import eu.mhsl.craftattack.spawn.Main; import eu.mhsl.craftattack.spawn.appliance.Appliance; import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker; import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarkerListener; +import eu.mhsl.craftattack.spawn.appliances.afkTag.AfkTag; import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed; import eu.mhsl.craftattack.spawn.appliances.yearRank.YearRank; import net.kyori.adventure.text.Component; @@ -13,17 +14,23 @@ import net.kyori.adventure.text.format.TextColor; import org.bukkit.entity.Player; import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.function.Supplier; import java.util.logging.Level; public class DisplayName extends Appliance { + public interface DisplayNamed { + @Nullable Component getNamePrefix(Player p); + } + public void update(Player player) { TextColor playerColor = queryAppliance(AdminMarker.class).getPlayerColor(player); List<Supplier<Component>> prefixes = List.of( () -> queryAppliance(Outlawed.class).getNamePrefix(player), - () -> queryAppliance(YearRank.class).getNamePrefix(player) + () -> queryAppliance(YearRank.class).getNamePrefix(player), + () -> queryAppliance(AfkTag.class).getNamePrefix(player) ); ComponentBuilder<TextComponent, TextComponent.Builder> playerName = Component.text(); diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/outlawed/Outlawed.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/outlawed/Outlawed.java index e71ffc0..3fb23fb 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/outlawed/Outlawed.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/outlawed/Outlawed.java @@ -17,7 +17,7 @@ import org.jetbrains.annotations.NotNull; import java.util.*; -public class Outlawed extends Appliance { +public class Outlawed extends Appliance implements DisplayName.DisplayNamed { public final int timeoutInMs = 1000 * 60 * 60 * 6; private final Map<UUID, Long> timeouts = new HashMap<>(); @@ -110,6 +110,7 @@ public class Outlawed extends Appliance { }; } + @Override public Component getNamePrefix(Player player) { if(isOutlawed(player)) { return Component.text("[☠]", NamedTextColor.RED) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/yearRank/YearRank.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/yearRank/YearRank.java index 75e3acb..0b97f9b 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/yearRank/YearRank.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/yearRank/YearRank.java @@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.appliances.yearRank; import eu.mhsl.craftattack.spawn.Main; import eu.mhsl.craftattack.spawn.appliance.Appliance; import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.appliances.displayName.DisplayName; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.ClickEvent; @@ -15,7 +16,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.*; -public class YearRank extends Appliance { +public class YearRank extends Appliance implements DisplayName.DisplayNamed { record CraftAttackYear(String name) {} private final Map<UUID, List<CraftAttackYear>> rankMap = new HashMap<>(); @@ -44,6 +45,7 @@ public class YearRank extends Appliance { }); } + @Override public @Nullable Component getNamePrefix(Player player) { if(!rankMap.containsKey(player.getUniqueId())) return null; int yearCount = rankMap.get(player.getUniqueId()).size(); From 39814dae05167ad700c0024af8931ffbe46d13eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Sun, 24 Nov 2024 22:44:48 +0100 Subject: [PATCH 15/18] added sleepTag --- .../spawn/appliances/afkTag/AfkTag.java | 8 +- .../appliances/displayName/DisplayName.java | 6 +- .../sleepTag/SleepStateChangeListener.java | 19 +++++ .../spawn/appliances/sleepTag/SleepTag.java | 74 +++++++++++++++++++ 4 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepStateChangeListener.java create mode 100644 src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java index 055aa4e..0ea049e 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java @@ -34,13 +34,13 @@ public class AfkTag extends Appliance implements DisplayName.DisplayNamed { public void resetTiming(Player player) { boolean wasAfk = isAfk(player); this.afkTimings.put(player, System.currentTimeMillis()); - if (wasAfk) updateAfkPrefix(player); + if (wasAfk) this.updateAfkPrefix(player); } private void checkAfkPlayers() { this.afkTimings.keySet().forEach((player) -> { if(!isAfk(player)) return; - updateAfkPrefix(player); + this.updateAfkPrefix(player); }); } @@ -57,8 +57,8 @@ public class AfkTag extends Appliance implements DisplayName.DisplayNamed { } @Override - public @Nullable Component getNamePrefix(Player p) { - if(isAfk(p)) return Component.text("[\uD83D\uDECC]", NamedTextColor.GRAY) + public @Nullable Component getNamePrefix(Player player) { + if(isAfk(player)) return Component.text("[\uD83D\uDEAB]", NamedTextColor.GRAY) .hoverEvent(HoverEvent.showText(Component.text("Der Spieler ist AFK"))); return null; diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/displayName/DisplayName.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/displayName/DisplayName.java index 8271157..8d19a54 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/displayName/DisplayName.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/displayName/DisplayName.java @@ -6,6 +6,7 @@ import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker; import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarkerListener; import eu.mhsl.craftattack.spawn.appliances.afkTag.AfkTag; import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed; +import eu.mhsl.craftattack.spawn.appliances.sleepTag.SleepTag; import eu.mhsl.craftattack.spawn.appliances.yearRank.YearRank; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentBuilder; @@ -22,7 +23,7 @@ import java.util.logging.Level; public class DisplayName extends Appliance { public interface DisplayNamed { - @Nullable Component getNamePrefix(Player p); + @Nullable Component getNamePrefix(Player player); } public void update(Player player) { @@ -30,7 +31,8 @@ public class DisplayName extends Appliance { List<Supplier<Component>> prefixes = List.of( () -> queryAppliance(Outlawed.class).getNamePrefix(player), () -> queryAppliance(YearRank.class).getNamePrefix(player), - () -> queryAppliance(AfkTag.class).getNamePrefix(player) + () -> queryAppliance(AfkTag.class).getNamePrefix(player), + () -> queryAppliance(SleepTag.class).getNamePrefix(player) ); ComponentBuilder<TextComponent, TextComponent.Builder> playerName = Component.text(); diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepStateChangeListener.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepStateChangeListener.java new file mode 100644 index 0000000..4179307 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepStateChangeListener.java @@ -0,0 +1,19 @@ +package eu.mhsl.craftattack.spawn.appliances.sleepTag; + +import eu.mhsl.craftattack.spawn.appliance.ApplianceListener; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerBedEnterEvent; +import org.bukkit.event.player.PlayerBedLeaveEvent; + +public class SleepStateChangeListener extends ApplianceListener<SleepTag> { + @EventHandler + public void onBedEnter(PlayerBedEnterEvent event) { + if(!event.getBedEnterResult().equals(PlayerBedEnterEvent.BedEnterResult.OK)) return; + getAppliance().updateSleeping(event.getPlayer(), true); + } + + @EventHandler + public void onBedLeave(PlayerBedLeaveEvent event) { + getAppliance().updateSleeping(event.getPlayer(), false); + } +} diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java new file mode 100644 index 0000000..b021cf6 --- /dev/null +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java @@ -0,0 +1,74 @@ +package eu.mhsl.craftattack.spawn.appliances.sleepTag; + +import eu.mhsl.craftattack.spawn.Main; +import eu.mhsl.craftattack.spawn.appliance.Appliance; +import eu.mhsl.craftattack.spawn.appliances.displayName.DisplayName; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.util.Ticks; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class SleepTag extends Appliance implements DisplayName.DisplayNamed { + private final Set<Player> sleepingPlayers = new HashSet<>(); + + @Override + public void onEnable() { + Bukkit.getScheduler().runTaskTimerAsynchronously( + Main.instance(), + this::cleanup, + Ticks.TICKS_PER_SECOND * 60, + Ticks.TICKS_PER_SECOND * 60 + ); + } + + public void updateSleeping(Player player, boolean isSleeping) { + if(isSleeping) { + this.sleepingPlayers.add(player); + } else { + this.sleepingPlayers.remove(player); + } + this.updateDisplayName(player); + } + + private void updateDisplayName(Player player) { + Main.instance().getAppliance(DisplayName.class).update(player); + } + + private void cleanup() { + System.out.println("before: " + this.sleepingPlayers); + List<Player> invalidEntries = this.sleepingPlayers.stream() + .filter(player -> !player.isConnected()) + .filter(player -> !player.isSleeping()) + .toList(); + + System.out.println("Found invalid: " + invalidEntries); + + invalidEntries.forEach(this.sleepingPlayers::remove); + invalidEntries.forEach(this::updateDisplayName); + System.out.println("after: " + this.sleepingPlayers); + } + + @Override + public @Nullable Component getNamePrefix(Player player) { + System.out.println("Testfor sleeping"); + if(this.sleepingPlayers.contains(player)) + return Component.text("[\uD83D\uDECC]", NamedTextColor.GRAY) + .hoverEvent(HoverEvent.showText(Component.text("Der Spieler liegt in einem Bett"))); + + return null; + } + + @Override + protected @NotNull List<Listener> listeners() { + return List.of(new SleepStateChangeListener()); + } +} From b35c5b9240181d77e0f5899181b7bbf6bdb87f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Mon, 25 Nov 2024 20:40:43 +0100 Subject: [PATCH 16/18] updated afk and sleep tag icons --- .../eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java | 2 +- .../eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java index 0ea049e..538efcd 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/afkTag/AfkTag.java @@ -58,7 +58,7 @@ public class AfkTag extends Appliance implements DisplayName.DisplayNamed { @Override public @Nullable Component getNamePrefix(Player player) { - if(isAfk(player)) return Component.text("[\uD83D\uDEAB]", NamedTextColor.GRAY) + if(isAfk(player)) return Component.text("[ᵃᶠᵏ]", NamedTextColor.GRAY) .hoverEvent(HoverEvent.showText(Component.text("Der Spieler ist AFK"))); return null; diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java index b021cf6..cefde9b 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java @@ -61,7 +61,7 @@ public class SleepTag extends Appliance implements DisplayName.DisplayNamed { public @Nullable Component getNamePrefix(Player player) { System.out.println("Testfor sleeping"); if(this.sleepingPlayers.contains(player)) - return Component.text("[\uD83D\uDECC]", NamedTextColor.GRAY) + return Component.text("[\uD83D\uDCA4]", NamedTextColor.GRAY) .hoverEvent(HoverEvent.showText(Component.text("Der Spieler liegt in einem Bett"))); return null; From c9935637b9ac5c9b8b0b82ac7c050becf9978766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Thu, 28 Nov 2024 21:22:28 +0100 Subject: [PATCH 17/18] removed inconsistent spacing in acinform --- .../mhsl/craftattack/spawn/appliances/acInform/AcInform.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java index 336ad42..b7db6f2 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/acInform/AcInform.java @@ -89,14 +89,14 @@ public class AcInform extends Appliance { .append(Component.text("[", NamedTextColor.GRAY)) .append(Component.text("Report", NamedTextColor.GOLD)) - .append(Component.text("] ", NamedTextColor.GRAY)) + .append(Component.text("]", NamedTextColor.GRAY)) .clickEvent(ClickEvent.suggestCommand(String.format("/report %s anticheat %s flagged %s", playerName, anticheatName, checkName))) ); component.append( Component.text(" [", NamedTextColor.GRAY) .append(Component.text("Kick", NamedTextColor.GOLD)) - .append(Component.text("] ", NamedTextColor.GRAY)) + .append(Component.text("]", NamedTextColor.GRAY)) .clickEvent(ClickEvent.suggestCommand(String.format("/kick %s", playerName))) ); From 3c829391208ee1bff39e1cca140629408330969d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com> Date: Thu, 28 Nov 2024 21:24:10 +0100 Subject: [PATCH 18/18] removed unwanted logging --- .../mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java b/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java index cefde9b..1d92aff 100644 --- a/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java +++ b/src/main/java/eu/mhsl/craftattack/spawn/appliances/sleepTag/SleepTag.java @@ -44,22 +44,17 @@ public class SleepTag extends Appliance implements DisplayName.DisplayNamed { } private void cleanup() { - System.out.println("before: " + this.sleepingPlayers); List<Player> invalidEntries = this.sleepingPlayers.stream() .filter(player -> !player.isConnected()) .filter(player -> !player.isSleeping()) .toList(); - System.out.println("Found invalid: " + invalidEntries); - invalidEntries.forEach(this.sleepingPlayers::remove); invalidEntries.forEach(this::updateDisplayName); - System.out.println("after: " + this.sleepingPlayers); } @Override public @Nullable Component getNamePrefix(Player player) { - System.out.println("Testfor sleeping"); if(this.sleepingPlayers.contains(player)) return Component.text("[\uD83D\uDCA4]", NamedTextColor.GRAY) .hoverEvent(HoverEvent.showText(Component.text("Der Spieler liegt in einem Bett")));