From c0a8cb529546135de658c207dc1424592c12264f Mon Sep 17 00:00:00 2001 From: Ryan <7389646+ryanbarlow97@users.noreply.github.com> Date: Sat, 26 Sep 2026 21:13:34 +0000 Subject: [PATCH 1/3] Let other plugins pause station countdowns Adds a ConstructionFreeze service. SimpleFactions registers one to hold vehicle projects of players whose war battle was postponed. A paused station keeps its time and shows why under the timer. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../vfbuilders/api/ConstructionFreeze.java | 16 +++++++++ .../vfbuilders/api/ConstructionFreezes.java | 34 +++++++++++++++++++ .../vfbuilders/core/ActiveStation.java | 12 ++++++- .../display/StationTimerDisplay.java | 10 +++++- 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreeze.java create mode 100644 src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreezes.java diff --git a/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreeze.java b/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreeze.java new file mode 100644 index 0000000..36326f2 --- /dev/null +++ b/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreeze.java @@ -0,0 +1,16 @@ +package net.tfminecraft.vfbuilders.api; + +import java.util.UUID; + +/** + * Lets another plugin pause station countdowns. Register an implementation with + * Bukkit's ServicesManager; every registration is asked once per station per second. + */ +public interface ConstructionFreeze { + + /** + * @param constructorUuid player who started the project + * @return why the project is paused, shown under the station timer, or null to keep counting down + */ + String freezeReason(UUID constructorUuid); +} diff --git a/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreezes.java b/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreezes.java new file mode 100644 index 0000000..abd53e5 --- /dev/null +++ b/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreezes.java @@ -0,0 +1,34 @@ +package net.tfminecraft.vfbuilders.api; + +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.RegisteredServiceProvider; + +/** Asks every registered {@link ConstructionFreeze} whether a project should hold. */ +public final class ConstructionFreezes { + + private ConstructionFreezes() { + } + + /** @return the first freeze reason for this constructor, or null when nothing pauses it */ + public static String reason(UUID constructorUuid) { + if (constructorUuid == null) { + return null; + } + for (RegisteredServiceProvider registration + : Bukkit.getServicesManager().getRegistrations(ConstructionFreeze.class)) { + String reason; + try { + reason = registration.getProvider().freezeReason(constructorUuid); + } catch (RuntimeException e) { + // A broken provider must not stall every station on the server. + continue; + } + if (reason != null) { + return reason; + } + } + return null; + } +} diff --git a/src/main/java/net/tfminecraft/vfbuilders/core/ActiveStation.java b/src/main/java/net/tfminecraft/vfbuilders/core/ActiveStation.java index 0c0d75e..dbe759f 100644 --- a/src/main/java/net/tfminecraft/vfbuilders/core/ActiveStation.java +++ b/src/main/java/net/tfminecraft/vfbuilders/core/ActiveStation.java @@ -8,6 +8,7 @@ import org.bukkit.Sound; import org.bukkit.entity.TextDisplay; +import net.tfminecraft.vfbuilders.api.ConstructionFreezes; import net.tfminecraft.vfbuilders.display.StationTimerDisplay; import net.tfminecraft.vfbuilders.events.VehicleConstructEvent; import net.tfminecraft.vfbuilders.loaders.BlueprintLoader; @@ -28,6 +29,7 @@ public class ActiveStation { private UUID constructorUuid; private TextDisplay timerDisplay; + private String freezeReason; public ActiveStation(Location loc, Station stored) { @@ -81,6 +83,14 @@ public boolean tick() { return true; } + String reason = ConstructionFreezes.reason(constructorUuid); + if (reason != null) { + freezeReason = reason; + ensureDisplay(); + return false; + } + freezeReason = null; + timeLeft--; ensureDisplay(); @@ -220,7 +230,7 @@ public void ensureDisplay() { StationTimerDisplay.purgeAtStationBlock(loc); StationTimerDisplay.purgeLegacyArmorStands(loc); - String text = StationTimerDisplay.formatText(blueprint.getVehicle().getName(), timeLeft); + String text = StationTimerDisplay.formatText(blueprint.getVehicle().getName(), timeLeft, freezeReason); if (timerDisplay == null || timerDisplay.isDead()) { timerDisplay = StationTimerDisplay.spawn(loc.getWorld(), loc, text); } else { diff --git a/src/main/java/net/tfminecraft/vfbuilders/display/StationTimerDisplay.java b/src/main/java/net/tfminecraft/vfbuilders/display/StationTimerDisplay.java index 7cf4724..d8e8b18 100644 --- a/src/main/java/net/tfminecraft/vfbuilders/display/StationTimerDisplay.java +++ b/src/main/java/net/tfminecraft/vfbuilders/display/StationTimerDisplay.java @@ -44,9 +44,17 @@ public static Location displayAnchor(Location stationBlock) { } public static String formatText(String vehicleName, int timeLeftSeconds) { + return formatText(vehicleName, timeLeftSeconds, null); + } + + public static String formatText(String vehicleName, int timeLeftSeconds, String freezeReason) { String name = vehicleName == null ? "Vehicle" : vehicleName; - return "§eConstructing §6" + name + String text = "§eConstructing §6" + name + "\n§7Time: §f" + TimeFormatter.formatTime(timeLeftSeconds); + if (freezeReason != null) { + text += "\n§cPaused: §7" + freezeReason; + } + return text; } public static TextDisplay spawn(World world, Location stationBlock, String text) { From ba0651065c0f5e3bb314ef347d83e3ff6cef800b Mon Sep 17 00:00:00 2001 From: Ryan <7389646+ryanbarlow97@users.noreply.github.com> Date: Sat, 26 Sep 2026 21:37:49 +0000 Subject: [PATCH 2/3] Say providers are asked until one pauses the station Co-Authored-By: Claude Opus 5.5 (1M context) --- .../net/tfminecraft/vfbuilders/api/ConstructionFreeze.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreeze.java b/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreeze.java index 36326f2..53a7480 100644 --- a/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreeze.java +++ b/src/main/java/net/tfminecraft/vfbuilders/api/ConstructionFreeze.java @@ -4,7 +4,8 @@ /** * Lets another plugin pause station countdowns. Register an implementation with - * Bukkit's ServicesManager; every registration is asked once per station per second. + * Bukkit's ServicesManager. Each second, registrations are asked in turn for every + * station still counting down, stopping at the first one that returns a reason. */ public interface ConstructionFreeze { From e0d0fe5f94a88670b8aa830e356ba56b60fb8fd5 Mon Sep 17 00:00:00 2001 From: Ryan <7389646+ryanbarlow97@users.noreply.github.com> Date: Sat, 26 Sep 2026 21:40:47 +0000 Subject: [PATCH 3/3] Clear the pause reason when a project is picked or cancelled Co-Authored-By: Claude Opus 5.5 (1M context) --- .../java/net/tfminecraft/vfbuilders/core/ActiveStation.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/net/tfminecraft/vfbuilders/core/ActiveStation.java b/src/main/java/net/tfminecraft/vfbuilders/core/ActiveStation.java index dbe759f..31b8201 100644 --- a/src/main/java/net/tfminecraft/vfbuilders/core/ActiveStation.java +++ b/src/main/java/net/tfminecraft/vfbuilders/core/ActiveStation.java @@ -74,6 +74,7 @@ public void selectBlueprint(Blueprint b, UUID constructorUuid) { blueprint = b; timeLeft = b.getTime(); this.constructorUuid = constructorUuid; + freezeReason = null; ensureDisplay(); } @@ -148,6 +149,7 @@ public void cancelConstruction() { spawnLoc = null; blueprint = null; constructorUuid = null; + freezeReason = null; timeLeft = 0; }