From 818c86d1560b6df5fe6e5c92bb032ee81ab8c102 Mon Sep 17 00:00:00 2001 From: Drefvelin <54400154+Drefvelin@users.noreply.github.com> Date: Mon, 28 Sep 2026 08:27:33 +0000 Subject: [PATCH 1/2] Register the voting booth furniture and start a due election when its law passes. Co-authored-by: Cursor --- .github/dependencies.sha256 | 1 + .github/scripts/install-local-dependencies.sh | 3 + .github/scripts/prepare-release.sh | 1 + pom.xml | 6 ++ .../simplefactions/government/Government.java | 19 +++-- .../government/VotingBlock.java | 45 ++++++++++++ .../simplefactions/loaders/ConfigLoader.java | 2 +- .../managers/FactionManager.java | 69 ++++++++++++++++--- .../simplefactions/objects/Faction.java | 12 ++++ src/main/resources/config.yml | 2 +- src/main/resources/plugin.yml | 2 +- .../government/ElectionCountdownTest.java | 25 +++++++ .../government/VotingBlockTest.java | 27 ++++++++ 13 files changed, 196 insertions(+), 18 deletions(-) create mode 100644 src/main/java/net/tfminecraft/simplefactions/government/VotingBlock.java create mode 100644 src/test/java/net/tfminecraft/simplefactions/government/ElectionCountdownTest.java create mode 100644 src/test/java/net/tfminecraft/simplefactions/government/VotingBlockTest.java diff --git a/.github/dependencies.sha256 b/.github/dependencies.sha256 index 69fe82d9..06ffd345 100644 --- a/.github/dependencies.sha256 +++ b/.github/dependencies.sha256 @@ -3,3 +3,4 @@ a37f7789fcdcd11c9e5890a2fac742aa4501749588af23182991953e06ee1d17 libs/MMOItems-6.10.1-SNAPSHOT.jar 225aa7f75d4e6e6ae6b3ad87a7ca678c025c027f00374ab1062275d24f3a73c9 libs/MythicLib-1.7.1-SNAPSHOT.jar 81d511d0830951f988615b6533cc93e82d00a83fb31e8ccbb36441ae3e8157ef libs/MMOCore-1.13.1-SNAPSHOT.jar +5a01b37bd7442fb0f2c809cadac82ba70f75173956e04efac3336595cc070368 libs/ItemsAdder-4.0.18.jar diff --git a/.github/scripts/install-local-dependencies.sh b/.github/scripts/install-local-dependencies.sh index ccfc5faa..3a0a1b7a 100644 --- a/.github/scripts/install-local-dependencies.sh +++ b/.github/scripts/install-local-dependencies.sh @@ -19,3 +19,6 @@ mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1. mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \ -Dfile="libs/MMOCore-1.13.1-SNAPSHOT.jar" -DgroupId="local" -DartifactId="MMOCore" \ -Dversion="1.13.1-SNAPSHOT-tfmc-81d511d08309" -Dpackaging=jar -DgeneratePom=true "$@" +mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \ + -Dfile="libs/ItemsAdder-4.0.18.jar" -DgroupId="local" -DartifactId="ItemsAdder" \ + -Dversion="4.0.18-tfmc-5a01b37bd744" -Dpackaging=jar -DgeneratePom=true "$@" diff --git a/.github/scripts/prepare-release.sh b/.github/scripts/prepare-release.sh index 7229af17..d0e533e6 100644 --- a/.github/scripts/prepare-release.sh +++ b/.github/scripts/prepare-release.sh @@ -8,4 +8,5 @@ curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/a37f7789fcdc/MMOItems-6.10.1-SNAPSHOT.jar?ref=$ref" > "libs/MMOItems-6.10.1-SNAPSHOT.jar" curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/225aa7f75d4e/MythicLib-1.7.1-SNAPSHOT.jar?ref=$ref" > "libs/MythicLib-1.7.1-SNAPSHOT.jar" curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/81d511d08309/MMOCore-1.13.1-SNAPSHOT.jar?ref=$ref" > "libs/MMOCore-1.13.1-SNAPSHOT.jar" +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/5a01b37bd744/ItemsAdder-4.0.18.jar?ref=$ref" > "libs/ItemsAdder-4.0.18.jar" bash .github/scripts/install-local-dependencies.sh "$@" diff --git a/pom.xml b/pom.xml index cf4b160b..0e55c4cc 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,12 @@ 1.13.1-SNAPSHOT-tfmc-81d511d08309 provided + + local + ItemsAdder + 4.0.18-tfmc-5a01b37bd744 + provided + io.papermc.paper paper-api diff --git a/src/main/java/net/tfminecraft/simplefactions/government/Government.java b/src/main/java/net/tfminecraft/simplefactions/government/Government.java index c277300b..5c076303 100644 --- a/src/main/java/net/tfminecraft/simplefactions/government/Government.java +++ b/src/main/java/net/tfminecraft/simplefactions/government/Government.java @@ -290,6 +290,9 @@ public void tick() { } election.tick(); if(!hasElections()) lastElectionDate = new Date(0); + // Elections otherwise start only when factions load. The day tick is what + // catches a Monday that begins while the server is already running. + ping(); validateFavoursAndRepressions(); replace(); } @@ -617,20 +620,22 @@ public String getTimeUntilNextElection() { LocalDate nextDate = getNextElectionStartDate(); + ZoneId zone = ZoneId.systemDefault(); Instant now = Instant.now(); - Instant next = nextDate - .atStartOfDay(ZoneId.systemDefault()) - .toInstant(); + Instant next = nextDate.atStartOfDay(zone).toInstant(); + if (!next.isAfter(now) && nextDate.equals(LocalDate.ofInstant(now, zone))) { + return "Today"; + } + return formatTimeUntil(now, next); + } - if (next.isBefore(now)) { + public static String formatTimeUntil(Instant now, Instant next) { + if (now == null || next == null || !next.isAfter(now)) { return "0d 0h"; } - long seconds = ChronoUnit.SECONDS.between(now, next); - long days = seconds / 86400; long hours = (seconds % 86400) / 3600; - return days + "d " + hours + "h"; } diff --git a/src/main/java/net/tfminecraft/simplefactions/government/VotingBlock.java b/src/main/java/net/tfminecraft/simplefactions/government/VotingBlock.java new file mode 100644 index 00000000..78f177d8 --- /dev/null +++ b/src/main/java/net/tfminecraft/simplefactions/government/VotingBlock.java @@ -0,0 +1,45 @@ +package net.tfminecraft.simplefactions.government; + +public final class VotingBlock { + private VotingBlock() { + } + + public static String furnitureId(String configPath) { + String path = typedPath(configPath, "iaf"); + return path == null || path.isBlank() ? null : path; + } + + public static boolean matches(String configPath, String namespacedId) { + if (namespacedId == null || namespacedId.isBlank()) { + return false; + } + String configured = furnitureId(configPath); + return configured != null && configured.equalsIgnoreCase(namespacedId); + } + + private static String typedPath(String configPath, String expectedType) { + if (configPath == null || configPath.isBlank()) { + return null; + } + String trimmed = configPath.trim(); + int openParen = trimmed.indexOf('('); + int closeParen = trimmed.indexOf(')', openParen + 1); + String type; + String path; + if (openParen >= 0 && closeParen > openParen) { + type = trimmed.substring(0, openParen); + path = trimmed.substring(openParen + 1, closeParen); + } else { + int dot = trimmed.indexOf('.'); + if (dot <= 0) { + return null; + } + type = trimmed.substring(0, dot); + path = trimmed.substring(dot + 1); + } + if (!type.equalsIgnoreCase(expectedType)) { + return null; + } + return path.trim(); + } +} diff --git a/src/main/java/net/tfminecraft/simplefactions/loaders/ConfigLoader.java b/src/main/java/net/tfminecraft/simplefactions/loaders/ConfigLoader.java index 2501f845..5cb27b68 100644 --- a/src/main/java/net/tfminecraft/simplefactions/loaders/ConfigLoader.java +++ b/src/main/java/net/tfminecraft/simplefactions/loaders/ConfigLoader.java @@ -106,7 +106,7 @@ public void loadConfig(File configFile) { Cache.branchUpgradeCost = config.getDouble("branch-upgrade-cost", 100.0); Cache.branchUpgradeExponent = config.getDouble("branch-upgrade-exponent", 1.1); - Cache.votingBlock = config.getString("voting-block", "v(chiseled_bookshelf)"); + Cache.votingBlock = config.getString("voting-block", "iaf(tfmc:voting_booth)"); Cache.baseYear = config.getString("starting-year", "372 AE"); if(config.contains("terrain-modifiers")) { diff --git a/src/main/java/net/tfminecraft/simplefactions/managers/FactionManager.java b/src/main/java/net/tfminecraft/simplefactions/managers/FactionManager.java index 900e021a..7fcf25a5 100644 --- a/src/main/java/net/tfminecraft/simplefactions/managers/FactionManager.java +++ b/src/main/java/net/tfminecraft/simplefactions/managers/FactionManager.java @@ -10,6 +10,7 @@ import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.block.Block; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -19,6 +20,10 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.scheduler.BukkitRunnable; +import dev.lone.itemsadder.api.Events.FurnitureBreakEvent; +import dev.lone.itemsadder.api.Events.FurnitureInteractEvent; +import dev.lone.itemsadder.api.Events.FurniturePlaceSuccessEvent; + import net.tfminecraft.simplefactions.database.Database; import net.tfminecraft.simplefactions.database.LoanData; import net.tfminecraft.simplefactions.diplomacy.Attitude; @@ -52,6 +57,7 @@ import net.tfminecraft.simplefactions.player.PlayerEconomyManager; import net.tfminecraft.simplefactions.vehicles.maintenance.DenarEconomyPlayerBank; import net.tfminecraft.simplefactions.government.Government; +import net.tfminecraft.simplefactions.government.VotingBlock; import net.tfminecraft.simplefactions.government.movement.Movement; import net.tfminecraft.simplefactions.government.movement.cause.Cause; import net.tfminecraft.tlibs.TLibs; @@ -1154,7 +1160,10 @@ public static void acceptMovementLeaderTargetRequest(Player p) { //Elections and stuff + private final Map boothOpenedAt = new HashMap<>(); + public Faction getByVotingBooth(Block b) { + if (b == null) return null; for(Faction f : factions) { Government gov = f.getGovernment(); if(gov.isVotingBooth(b.getLocation())) return f; @@ -1165,30 +1174,62 @@ public Faction getByVotingBooth(Block b) { @EventHandler public void openBooth(PlayerInteractEvent e) { if(!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return; - Block b = e.getClickedBlock(); - Player p = e.getPlayer(); + if (presentBooth(e.getPlayer(), e.getClickedBlock())) { + e.setCancelled(true); + } + } + + @EventHandler + public void openVotingFurniture(FurnitureInteractEvent e) { + Action action = e.getAction(); + if (action != null && action != Action.RIGHT_CLICK_AIR && action != Action.RIGHT_CLICK_BLOCK) return; + if (!VotingBlock.matches(Cache.votingBlock, e.getNamespacedID())) return; + Entity entity = e.getBukkitEntity(); + if (entity == null) return; + if (presentBooth(e.getPlayer(), entity.getLocation().getBlock())) { + e.setCancelled(true); + } + } + + private boolean presentBooth(Player p, Block b) { Faction f = getByVotingBooth(b); - if(f == null) return; - e.setCancelled(true); + if(f == null) return false; + long now = System.currentTimeMillis(); + Long openedAt = boothOpenedAt.get(p.getUniqueId()); + if (openedAt != null && now - openedAt < 400) return true; + boothOpenedAt.put(p.getUniqueId(), now); if(!f.getGovernment().hasElections()) { p.sendMessage("§cThis faction has no elections"); p.playSound(p.getLocation(), Sound.ENTITY_VILLAGER_NO, 1f, 1f); - return; + return true; } if(!f.canVote(p.getName())) { p.sendMessage("§cYou have no voting rights in this faction"); p.playSound(p.getLocation(), Sound.ENTITY_VILLAGER_NO, 1f, 1f); - return; + return true; } InventoryManager inv = new InventoryManager(); inv.electionView(p, f); + return true; } @EventHandler public void placeVotingBooth(BlockPlaceEvent e) { + if (VotingBlock.furnitureId(Cache.votingBlock) != null) return; Block b = e.getBlock(); - Player p = e.getPlayer(); if(!TLibs.getBlockAPI().getChecker().checkBlock(b, Cache.votingBlock)) return; + registerVotingBooth(e.getPlayer(), b); + } + + @EventHandler + public void placeVotingFurniture(FurniturePlaceSuccessEvent e) { + if (!VotingBlock.matches(Cache.votingBlock, e.getNamespacedID())) return; + Entity entity = e.getBukkitEntity(); + if (entity == null) return; + registerVotingBooth(e.getPlayer(), entity.getLocation().getBlock()); + } + + private void registerVotingBooth(Player p, Block b) { Faction f = FactionManager.getByMember(p.getName()); if(f == null) return; Government gov = f.getGovernment(); @@ -1200,9 +1241,21 @@ public void placeVotingBooth(BlockPlaceEvent e) { @EventHandler public void breakVotingBooth(BlockBreakEvent e) { + if (VotingBlock.furnitureId(Cache.votingBlock) != null) return; Block b = e.getBlock(); - Player p = e.getPlayer(); if(!TLibs.getBlockAPI().getChecker().checkBlock(b, Cache.votingBlock)) return; + unregisterVotingBooth(e.getPlayer(), b); + } + + @EventHandler(ignoreCancelled = true) + public void breakVotingFurniture(FurnitureBreakEvent e) { + if (!VotingBlock.matches(Cache.votingBlock, e.getNamespacedID())) return; + Entity entity = e.getBukkitEntity(); + if (entity == null) return; + unregisterVotingBooth(e.getPlayer(), entity.getLocation().getBlock()); + } + + private void unregisterVotingBooth(Player p, Block b) { Faction f = getByVotingBooth(b); if(f == null) return; Government gov = f.getGovernment(); diff --git a/src/main/java/net/tfminecraft/simplefactions/objects/Faction.java b/src/main/java/net/tfminecraft/simplefactions/objects/Faction.java index 8f871d5e..9bc84c4d 100644 --- a/src/main/java/net/tfminecraft/simplefactions/objects/Faction.java +++ b/src/main/java/net/tfminecraft/simplefactions/objects/Faction.java @@ -1074,6 +1074,9 @@ public void applyLaw(Law law, LawGroup group) { // --- 🔴 ELECTION CANCELLATION LOGIC --- cancelInvalidElections(); + if (enablesElections(effect)) { + government.ping(); + } // --- vassal logic --- if (effect.prohibitsVassals() && hasVassals()) { @@ -1133,6 +1136,15 @@ public void applyPoliticalAction(Cause cause, Proposal proposal) { } } + static boolean enablesElections(LawEffect effect) { + if (effect == null || !effect.hasRules()) { + return false; + } + Map rules = effect.getRules(); + return Boolean.TRUE.equals(rules.get(Rules.LEADER_ELECTIONS)) + || Boolean.TRUE.equals(rules.get(Rules.ELECTED_COUNCIL)); + } + private void cancelInvalidElections() { Government gov = getGovernment(); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 42c26a0d..138e6312 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -56,7 +56,7 @@ mercenary-default-breach-refund: 500.0 # smaller refund would make no-showing more profitable per head than fighting. bank-block: iaf(tfmc:bank) -voting-block: v(chiseled_bookshelf) +voting-block: iaf(tfmc:voting_booth) starting-year: "372 AE" max-extra-node-capacity: 0 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3c4133b8..b8395129 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,7 +5,7 @@ version: ${project.version} author: Drefvelin depend: [DenarEconomy, TLibs] -softdepend: [MMOItems, MythicLib, MMOCore, TFMCWeb, VehicleFramework, VFBuilders, ConditionalEvents, RPCharacters] +softdepend: [MMOItems, MythicLib, MMOCore, TFMCWeb, VehicleFramework, VFBuilders, ConditionalEvents, RPCharacters, ItemsAdder] commands: faction: diff --git a/src/test/java/net/tfminecraft/simplefactions/government/ElectionCountdownTest.java b/src/test/java/net/tfminecraft/simplefactions/government/ElectionCountdownTest.java new file mode 100644 index 00000000..9191d54b --- /dev/null +++ b/src/test/java/net/tfminecraft/simplefactions/government/ElectionCountdownTest.java @@ -0,0 +1,25 @@ +package net.tfminecraft.simplefactions.government; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.time.Instant; + +import org.junit.jupiter.api.Test; + +class ElectionCountdownTest { + + @Test + void formatTimeUntil_countsWholeDaysAndHours() { + Instant now = Instant.parse("2026-09-21T08:15:00Z"); + Instant next = Instant.parse("2026-09-28T00:00:00Z"); + assertEquals("6d 15h", Government.formatTimeUntil(now, next)); + } + + @Test + void formatTimeUntil_pastTargetIsZero() { + Instant now = Instant.parse("2026-09-28T08:15:00Z"); + Instant next = Instant.parse("2026-09-28T00:00:00Z"); + assertEquals("0d 0h", Government.formatTimeUntil(now, next)); + assertEquals("0d 0h", Government.formatTimeUntil(now, null)); + } +} diff --git a/src/test/java/net/tfminecraft/simplefactions/government/VotingBlockTest.java b/src/test/java/net/tfminecraft/simplefactions/government/VotingBlockTest.java new file mode 100644 index 00000000..6ae22434 --- /dev/null +++ b/src/test/java/net/tfminecraft/simplefactions/government/VotingBlockTest.java @@ -0,0 +1,27 @@ +package net.tfminecraft.simplefactions.government; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class VotingBlockTest { + + @Test + void furnitureId_readsItemsAdderFurniturePath() { + assertEquals("tfmc:voting_booth", VotingBlock.furnitureId("iaf(tfmc:voting_booth)")); + assertEquals("tfmc:voting_booth", VotingBlock.furnitureId("iaf.tfmc:voting_booth")); + assertNull(VotingBlock.furnitureId("v(chiseled_bookshelf)")); + assertNull(VotingBlock.furnitureId(null)); + } + + @Test + void matches_comparesNamespacedId() { + assertTrue(VotingBlock.matches("iaf(tfmc:voting_booth)", "tfmc:voting_booth")); + assertTrue(VotingBlock.matches("iaf(tfmc:voting_booth)", "TFMC:Voting_Booth")); + assertFalse(VotingBlock.matches("iaf(tfmc:voting_booth)", "tfmc:bank")); + assertFalse(VotingBlock.matches("v(chiseled_bookshelf)", "tfmc:voting_booth")); + } +} From 4239d10e03349399b890a2821d9277685cf37cb2 Mon Sep 17 00:00:00 2001 From: Drefvelin <54400154+Drefvelin@users.noreply.github.com> Date: Mon, 28 Sep 2026 08:43:13 +0000 Subject: [PATCH 2/2] Keep faction listeners working without ItemsAdder and create guilds before election laws. Co-authored-by: Cursor --- .../simplefactions/SimpleFactions.java | 4 ++ .../managers/FactionManager.java | 39 ++------------ .../managers/VotingBoothListener.java | 51 +++++++++++++++++++ .../simplefactions/objects/Faction.java | 2 +- 4 files changed, 59 insertions(+), 37 deletions(-) create mode 100644 src/main/java/net/tfminecraft/simplefactions/managers/VotingBoothListener.java diff --git a/src/main/java/net/tfminecraft/simplefactions/SimpleFactions.java b/src/main/java/net/tfminecraft/simplefactions/SimpleFactions.java index f6b43c83..c73efe3c 100644 --- a/src/main/java/net/tfminecraft/simplefactions/SimpleFactions.java +++ b/src/main/java/net/tfminecraft/simplefactions/SimpleFactions.java @@ -410,6 +410,10 @@ public void registerListeners() { getServer().getPluginManager().registerEvents(displayNameGate, this); getServer().getPluginManager().registerEvents(declareCodePrompt, this); getServer().getPluginManager().registerEvents(factionManager, this); + if (getServer().getPluginManager().getPlugin("ItemsAdder") != null) { + getServer().getPluginManager().registerEvents( + new net.tfminecraft.simplefactions.managers.VotingBoothListener(factionManager), this); + } getServer().getPluginManager().registerEvents(provincePresenceListener, this); getServer().getPluginManager().registerEvents(battleManager, this); getServer().getPluginManager().registerEvents(battleItemDurabilityListener, this); diff --git a/src/main/java/net/tfminecraft/simplefactions/managers/FactionManager.java b/src/main/java/net/tfminecraft/simplefactions/managers/FactionManager.java index 7fcf25a5..336a686a 100644 --- a/src/main/java/net/tfminecraft/simplefactions/managers/FactionManager.java +++ b/src/main/java/net/tfminecraft/simplefactions/managers/FactionManager.java @@ -10,7 +10,6 @@ import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.block.Block; -import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -20,10 +19,6 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.scheduler.BukkitRunnable; -import dev.lone.itemsadder.api.Events.FurnitureBreakEvent; -import dev.lone.itemsadder.api.Events.FurnitureInteractEvent; -import dev.lone.itemsadder.api.Events.FurniturePlaceSuccessEvent; - import net.tfminecraft.simplefactions.database.Database; import net.tfminecraft.simplefactions.database.LoanData; import net.tfminecraft.simplefactions.diplomacy.Attitude; @@ -1179,19 +1174,7 @@ public void openBooth(PlayerInteractEvent e) { } } - @EventHandler - public void openVotingFurniture(FurnitureInteractEvent e) { - Action action = e.getAction(); - if (action != null && action != Action.RIGHT_CLICK_AIR && action != Action.RIGHT_CLICK_BLOCK) return; - if (!VotingBlock.matches(Cache.votingBlock, e.getNamespacedID())) return; - Entity entity = e.getBukkitEntity(); - if (entity == null) return; - if (presentBooth(e.getPlayer(), entity.getLocation().getBlock())) { - e.setCancelled(true); - } - } - - private boolean presentBooth(Player p, Block b) { + boolean presentBooth(Player p, Block b) { Faction f = getByVotingBooth(b); if(f == null) return false; long now = System.currentTimeMillis(); @@ -1221,15 +1204,7 @@ public void placeVotingBooth(BlockPlaceEvent e) { registerVotingBooth(e.getPlayer(), b); } - @EventHandler - public void placeVotingFurniture(FurniturePlaceSuccessEvent e) { - if (!VotingBlock.matches(Cache.votingBlock, e.getNamespacedID())) return; - Entity entity = e.getBukkitEntity(); - if (entity == null) return; - registerVotingBooth(e.getPlayer(), entity.getLocation().getBlock()); - } - - private void registerVotingBooth(Player p, Block b) { + void registerVotingBooth(Player p, Block b) { Faction f = FactionManager.getByMember(p.getName()); if(f == null) return; Government gov = f.getGovernment(); @@ -1247,15 +1222,7 @@ public void breakVotingBooth(BlockBreakEvent e) { unregisterVotingBooth(e.getPlayer(), b); } - @EventHandler(ignoreCancelled = true) - public void breakVotingFurniture(FurnitureBreakEvent e) { - if (!VotingBlock.matches(Cache.votingBlock, e.getNamespacedID())) return; - Entity entity = e.getBukkitEntity(); - if (entity == null) return; - unregisterVotingBooth(e.getPlayer(), entity.getLocation().getBlock()); - } - - private void unregisterVotingBooth(Player p, Block b) { + void unregisterVotingBooth(Player p, Block b) { Faction f = getByVotingBooth(b); if(f == null) return; Government gov = f.getGovernment(); diff --git a/src/main/java/net/tfminecraft/simplefactions/managers/VotingBoothListener.java b/src/main/java/net/tfminecraft/simplefactions/managers/VotingBoothListener.java new file mode 100644 index 00000000..5a9c7449 --- /dev/null +++ b/src/main/java/net/tfminecraft/simplefactions/managers/VotingBoothListener.java @@ -0,0 +1,51 @@ +package net.tfminecraft.simplefactions.managers; + +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; + +import dev.lone.itemsadder.api.Events.FurnitureBreakEvent; +import dev.lone.itemsadder.api.Events.FurnitureInteractEvent; +import dev.lone.itemsadder.api.Events.FurniturePlaceSuccessEvent; +import net.tfminecraft.simplefactions.Cache; +import net.tfminecraft.simplefactions.government.VotingBlock; + +public class VotingBoothListener implements Listener { + private final FactionManager factions; + + public VotingBoothListener(FactionManager factions) { + this.factions = factions; + } + + @EventHandler + public void openVotingFurniture(FurnitureInteractEvent event) { + Action action = event.getAction(); + if (action != null && action != Action.RIGHT_CLICK_AIR && action != Action.RIGHT_CLICK_BLOCK) return; + if (!VotingBlock.matches(Cache.votingBlock, event.getNamespacedID())) return; + Entity entity = event.getBukkitEntity(); + if (entity == null) return; + if (factions.presentBooth(event.getPlayer(), entity.getLocation().getBlock())) { + event.setCancelled(true); + } + } + + @EventHandler + public void placeVotingFurniture(FurniturePlaceSuccessEvent event) { + if (!VotingBlock.matches(Cache.votingBlock, event.getNamespacedID())) return; + Entity entity = event.getBukkitEntity(); + if (entity == null) return; + factions.registerVotingBooth(event.getPlayer(), entity.getLocation().getBlock()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void breakVotingFurniture(FurnitureBreakEvent event) { + if (!VotingBlock.matches(Cache.votingBlock, event.getNamespacedID())) return; + Entity entity = event.getBukkitEntity(); + if (entity == null) return; + Block block = entity.getLocation().getBlock(); + factions.unregisterVotingBooth(event.getPlayer(), block); + } +} diff --git a/src/main/java/net/tfminecraft/simplefactions/objects/Faction.java b/src/main/java/net/tfminecraft/simplefactions/objects/Faction.java index 9bc84c4d..c5919583 100644 --- a/src/main/java/net/tfminecraft/simplefactions/objects/Faction.java +++ b/src/main/java/net/tfminecraft/simplefactions/objects/Faction.java @@ -165,9 +165,9 @@ public Faction(String id, String leader) { this.settlementHandler = new SettlementHandler(this); this.installationHandler = new InstallationHandler(this); this.taxHandler = new TaxHandler(this, 5, 5, 5, 5, 5); - lawHandler.apply(); this.guildHandler = new GuildHandler(this); guildHandler.addGuild(new Guild(this)); + lawHandler.apply(); createBanner(bannerPatterns); // Keyed per object: FactionCreateEvent can cancel this one, and the retry needs its own fetch. List placeholder = this.bannerPatterns;