From 32cbbe6c516b8af2bcd7de3667a401e07ac14824 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com>
Date: Fri, 11 Apr 2025 19:16:13 +0200
Subject: [PATCH] made displayName independent of other appliances

---
 .../metaGameplay/displayName/DisplayName.java | 37 ++++++++++++-------
 .../DisplayNameUpdateListener.java            |  2 +-
 .../java/eu/mhsl/craftattack/core/Main.java   | 13 +++++--
 .../gameplay/outlawed/Outlawed.java           |  4 +-
 .../metaGameplay/adminMarker/AdminMarker.java |  7 +++-
 .../metaGameplay/afkTag/AfkTag.java           |  2 +-
 .../metaGameplay/sleepTag/SleepTag.java       |  2 +-
 .../metaGameplay/yearRank/YearRank.java       |  2 +-
 8 files changed, 43 insertions(+), 26 deletions(-)
 rename {craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack => common/src/main/java/eu/mhsl/craftattack/spawn/common}/appliances/metaGameplay/displayName/DisplayName.java (67%)
 rename {craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack => common/src/main/java/eu/mhsl/craftattack/spawn/common}/appliances/metaGameplay/displayName/DisplayNameUpdateListener.java (83%)

diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/displayName/DisplayName.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/metaGameplay/displayName/DisplayName.java
similarity index 67%
rename from craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/displayName/DisplayName.java
rename to common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/metaGameplay/displayName/DisplayName.java
index 78a036e..63c21ff 100644
--- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/displayName/DisplayName.java
+++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/metaGameplay/displayName/DisplayName.java
@@ -1,12 +1,7 @@
-package eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.displayName;
+package eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.displayName;
 
 import eu.mhsl.craftattack.core.Main;
 import eu.mhsl.craftattack.core.appliance.Appliance;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.outlawed.Outlawed;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.adminMarker.AdminMarker;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.afkTag.AfkTag;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.sleepTag.SleepTag;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.yearRank.YearRank;
 import eu.mhsl.craftattack.core.util.server.Floodgate;
 import eu.mhsl.craftattack.core.util.text.ComponentUtil;
 import net.kyori.adventure.text.Component;
@@ -20,7 +15,6 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 import java.util.Objects;
-import java.util.function.Supplier;
 import java.util.logging.Level;
 
 public class DisplayName extends Appliance {
@@ -29,18 +23,33 @@ public class DisplayName extends Appliance {
         Component getNamePrefix(Player player);
     }
 
+    public interface Colored {
+        @Nullable
+        TextColor getNameColor(Player player);
+    }
+
     public void update(Player player) {
-        TextColor playerColor = this.queryAppliance(AdminMarker.class).getPlayerColor(player);
-        List<Supplier<Prefixed>> prefixes = List.of(
-            () -> this.queryAppliance(Outlawed.class),
-            () -> this.queryAppliance(YearRank.class),
-            () -> this.queryAppliance(AfkTag.class),
-            () -> this.queryAppliance(SleepTag.class)
+        List<Colored> coloring = Main.instance().getAppliances().stream()
+            .filter(appliance -> appliance instanceof Colored)
+            .map(appliance -> (Colored) appliance)
+            .toList();
+
+        if(coloring.size() > 1) throw new IllegalStateException(
+            "There are two or more appliances which provide coloring for player names. This is currently not supported!"
         );
 
+        TextColor playerColor = coloring.isEmpty()
+            ? NamedTextColor.WHITE
+            : coloring.getFirst().getNameColor(player);
+
+        List<Prefixed> prefixes = Main.instance().getAppliances().stream()
+            .filter(appliance -> appliance instanceof Prefixed)
+            .map(appliance -> (Prefixed) appliance)
+            .toList();
+
         ComponentBuilder<TextComponent, TextComponent.Builder> playerName = Component.text();
         prefixes.stream()
-            .map(prefixed -> prefixed.get().getNamePrefix(player))
+            .map(prefixed -> prefixed.getNamePrefix(player))
             .filter(Objects::nonNull)
             .forEach(prefix -> playerName
                 .append(prefix)
diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/displayName/DisplayNameUpdateListener.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/metaGameplay/displayName/DisplayNameUpdateListener.java
similarity index 83%
rename from craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/displayName/DisplayNameUpdateListener.java
rename to common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/metaGameplay/displayName/DisplayNameUpdateListener.java
index 4308fd8..c4ab190 100644
--- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/displayName/DisplayNameUpdateListener.java
+++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/metaGameplay/displayName/DisplayNameUpdateListener.java
@@ -1,4 +1,4 @@
-package eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.displayName;
+package eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.displayName;
 
 import eu.mhsl.craftattack.core.appliance.ApplianceListener;
 import org.bukkit.event.EventHandler;
diff --git a/core/src/main/java/eu/mhsl/craftattack/core/Main.java b/core/src/main/java/eu/mhsl/craftattack/core/Main.java
index a232c7d..c1bc84b 100644
--- a/core/src/main/java/eu/mhsl/craftattack/core/Main.java
+++ b/core/src/main/java/eu/mhsl/craftattack/core/Main.java
@@ -21,6 +21,7 @@ public final class Main extends JavaPlugin {
 
     private List<Appliance> appliances;
     private RepositoryLoader repositoryLoader;
+    private Reflections reflections;
 
     @Override
     public void onEnable() {
@@ -39,15 +40,15 @@ public final class Main extends JavaPlugin {
         Configuration.readConfig();
         List<String> disabledAppliances = Configuration.pluginConfig.getStringList("disabledAppliances");
 
+        Main.logger().info("Initializing reflections...");
+        this.reflections = new Reflections("eu.mhsl.craftattack.spawn");
+
         Main.logger().info("Loading Repositories...");
         this.repositoryLoader = new RepositoryLoader();
         Main.logger().info(String.format("Loaded %d repositories!", this.repositoryLoader.getRepositories().size()));
 
         Main.logger().info("Loading appliances...");
-        Reflections reflections = new Reflections("eu.mhsl.craftattack.spawn");
-        Set<Class<? extends Appliance>> applianceClasses = reflections.getSubTypesOf(Appliance.class);
-
-        this.appliances = applianceClasses.stream()
+        this.appliances = this.findSubtypesOf(Appliance.class).stream()
             .filter(applianceClass -> !disabledAppliances.contains(applianceClass.getSimpleName()))
             .map(applianceClass -> {
                 try {
@@ -97,6 +98,10 @@ public final class Main extends JavaPlugin {
             .orElseThrow(() -> new RuntimeException(String.format("Appliance %s not loaded or instantiated!", clazz)));
     }
 
+    public <T> Set<Class<? extends T>> findSubtypesOf(Class<T> type) {
+        return this.reflections.getSubTypesOf(type);
+    }
+
     @SuppressWarnings("unchecked")
     public static <T> Class<T> getApplianceType(Class<?> clazz) {
         return (Class<T>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/Outlawed.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/Outlawed.java
index 044dc51..c027fcd 100644
--- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/Outlawed.java
+++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/Outlawed.java
@@ -3,7 +3,7 @@ package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.outlawed;
 import eu.mhsl.craftattack.core.Main;
 import eu.mhsl.craftattack.core.appliance.Appliance;
 import eu.mhsl.craftattack.core.appliance.ApplianceCommand;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.displayName.DisplayName;
+import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.displayName.DisplayName;
 import eu.mhsl.craftattack.spawn.craftattack.appliances.tooling.whitelist.Whitelist;
 import eu.mhsl.craftattack.core.config.Configuration;
 import eu.mhsl.craftattack.core.util.text.DisconnectInfo;
@@ -48,7 +48,7 @@ public class Outlawed extends Appliance implements DisplayName.Prefixed {
         );
     }
 
-    public void switchLawStatus(Player player) throws OutlawChangeNotPermitted {
+    void switchLawStatus(Player player) throws OutlawChangeNotPermitted {
         if(this.getLawStatus(player).equals(Status.FORCED)) {
             throw new OutlawChangeNotPermitted("Dein Vogelfreistatus wurde als Strafe auferlegt und kann daher nicht verändert werden.");
         }
diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/adminMarker/AdminMarker.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/adminMarker/AdminMarker.java
index 9edf678..b2ae54d 100644
--- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/adminMarker/AdminMarker.java
+++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/adminMarker/AdminMarker.java
@@ -1,12 +1,15 @@
 package eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.adminMarker;
 
 import eu.mhsl.craftattack.core.appliance.Appliance;
+import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.displayName.DisplayName;
 import net.kyori.adventure.text.format.TextColor;
 import org.bukkit.Color;
 import org.bukkit.entity.Player;
+import org.jetbrains.annotations.Nullable;
 
-public class AdminMarker extends Appliance {
-    public TextColor getPlayerColor(Player player) {
+public class AdminMarker extends Appliance implements DisplayName.Colored {
+    @Override
+    public @Nullable TextColor getNameColor(Player player) {
         if(player.hasPermission("chatcolor"))
             return TextColor.color(Color.AQUA.asRGB()); // TODO read permission from config
         return TextColor.color(Color.WHITE.asRGB());
diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/afkTag/AfkTag.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/afkTag/AfkTag.java
index 2f38916..a63f4b3 100644
--- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/afkTag/AfkTag.java
+++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/afkTag/AfkTag.java
@@ -2,7 +2,7 @@ package eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.afkTag;
 
 import eu.mhsl.craftattack.core.Main;
 import eu.mhsl.craftattack.core.appliance.Appliance;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.displayName.DisplayName;
+import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.displayName.DisplayName;
 import net.kyori.adventure.text.Component;
 import net.kyori.adventure.text.event.HoverEvent;
 import net.kyori.adventure.text.format.NamedTextColor;
diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/sleepTag/SleepTag.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/sleepTag/SleepTag.java
index e42e26b..8ec9958 100644
--- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/sleepTag/SleepTag.java
+++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/sleepTag/SleepTag.java
@@ -2,7 +2,7 @@ package eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.sleepTag;
 
 import eu.mhsl.craftattack.core.Main;
 import eu.mhsl.craftattack.core.appliance.Appliance;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.displayName.DisplayName;
+import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.displayName.DisplayName;
 import net.kyori.adventure.text.Component;
 import net.kyori.adventure.text.event.HoverEvent;
 import net.kyori.adventure.text.format.NamedTextColor;
diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/yearRank/YearRank.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/yearRank/YearRank.java
index ce80fdb..2b06997 100644
--- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/yearRank/YearRank.java
+++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/metaGameplay/yearRank/YearRank.java
@@ -3,7 +3,7 @@ package eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.yearRank;
 import eu.mhsl.craftattack.core.Main;
 import eu.mhsl.craftattack.core.appliance.Appliance;
 import eu.mhsl.craftattack.core.appliance.ApplianceCommand;
-import eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.displayName.DisplayName;
+import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.displayName.DisplayName;
 import net.kyori.adventure.text.Component;
 import net.kyori.adventure.text.TextComponent;
 import net.kyori.adventure.text.event.ClickEvent;