From ddfebbc82c5a4a3fc7e6d44f7b7f0ebe2cc9a63c Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Tue, 24 Feb 2026 21:56:47 +0200 Subject: [PATCH 01/17] feat: mayors --- .../swofty/type/hub/npcs/NPCCurrentMayor.java | 58 ++++ .../type/hub/npcs/NPCCurrentMinister.java | 58 ++++ .../net/swofty/type/hub/npcs/NPCSalesman.java | 24 +- .../SkyBlockGenericLoader.java | 4 + .../calendar/CalendarEvent.java | 135 +++++--- .../elections/ElectionData.java | 289 ++++++++++++++++++ .../elections/ElectionManager.java | 134 ++++++++ .../elections/SkyBlockMayor.java | 182 +++++++++++ .../gui/inventories/election/GUIElection.java | 173 +++++++++++ .../election/GUIElectionViewStats.java | 168 ++++++++++ .../inventories/election/GUIMayorMenu.java | 91 ++++++ .../inventories/election/GUIMinisterMenu.java | 74 +++++ .../attribute/SkyBlockServerAttributes.java | 9 +- .../attribute/attributes/AttributeString.java | 16 + 14 files changed, 1349 insertions(+), 66 deletions(-) create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElection.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElectionViewStats.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMayorMenu.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMinisterMenu.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/attributes/AttributeString.java diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java new file mode 100644 index 000000000..72407f950 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java @@ -0,0 +1,58 @@ +package net.swofty.type.hub.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import net.swofty.type.skyblockgeneric.gui.inventories.election.GUIMayorMenu; + +public class NPCCurrentMayor extends HypixelNPC { + + public NPCCurrentMayor() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return new String[]{"Mayor ???", "§e§lCLICK"}; + return new String[]{"Mayor " + mayor.getDisplayName(), "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return ""; + return mayor.getSignature(); + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return ""; + return mayor.getTexture(); + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(6.5, 79, 19.5, 135, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) { + event.player().sendMessage("§cHello!!"); + return; + } + new GUIMayorMenu().open(event.player()); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java new file mode 100644 index 000000000..8c69c8908 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java @@ -0,0 +1,58 @@ +package net.swofty.type.hub.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import net.swofty.type.skyblockgeneric.gui.inventories.election.GUIMinisterMenu; + +public class NPCCurrentMinister extends HypixelNPC { + + public NPCCurrentMinister() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor minister = ElectionManager.getCurrentMinister(); + if (minister == null) return new String[]{"Minister ????", "§e§lCLICK"}; + return new String[]{"Minister " + minister.getDisplayName(), "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor minister = ElectionManager.getCurrentMinister(); + if (minister == null) return ""; + return minister.getSignature(); + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor minister = ElectionManager.getCurrentMinister(); + if (minister == null) return ""; + return minister.getTexture(); + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(8.5, 79, 17.5, 135, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor minister = ElectionManager.getCurrentMinister(); + if (minister == null) { + event.player().sendMessage("§cHello!!"); + return; + } + new GUIMinisterMenu().open(event.player()); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCSalesman.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCSalesman.java index 22d6e13dc..f68602c61 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCSalesman.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCSalesman.java @@ -1,41 +1,35 @@ package net.swofty.type.hub.npcs; import net.minestom.server.coordinate.Pos; -import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; import java.util.stream.Stream; -import net.swofty.type.generic.event.custom.NPCInteractEvent; - public class NPCSalesman extends HypixelNPC { public NPCSalesman() { - super(new HumanConfiguration() { //different name and skin for each season + super(new HumanConfiguration() { @Override public String[] holograms(HypixelPlayer player) { return new String[]{"§bSalesman", "§e§lCLICK"}; } @Override - public String signature(HypixelPlayer player) { //easter skin - return "w/C2jc1wq0NjyU8tkGeubVpSGHSqlkz3suFEiSzsjyGaob5OacAJENebvaWaLVVK9QJybvHhVmhInJ+kN0SUXQk8hr6+vnAlSpdCyDdgomn5SQtF9CUla/rfM9KXV06zwUBfa5Lm0U/GBO7u+SEFCLjXkj8gs3sHPd7/8nCQm/N0HJe6lLcVu07sTkH2rvRJn4pHB2oYCdwd8QTetKYtZD0BmE0dfp8IO0JspyuuQVl1AaIebAqPTpQqP8/z2TAPuEVL7dY65yX0jfziSxLLSXIFJTh+OXcJttmAoH09MojLYFnddH41WZMYEku0sqtUcZd3Vw9iyYW5vF79rGbUJ2Fcq3Iydy7Be0jY3yhrhY6r2Kz4wyiVkjL9+fCb9suf7lkUKL/yjfLMEOqh2wmCsDEU9r+pW0YDCBE0754hLdi6YB8hqKwBZ61m1G33bMYmPi+F7danTAPInL0q/bX7R5Vo4c/ajfc1TEfda5FBx4ec4MhjGMTzmJ8Z7I/P09aunOnRe2KNG3wnfGLmZgUj12pXQeaAeGoICNcYyeDjxAyugjDTvMRo673RMR5jR//g/hZZeFLpe1d6jLe5ZTnJFB5Qqj+1qHk56K4iVVyj3zkh4oR4IzWUplqQGNb5cGPEcIsT9qWIL2hoacnvwdE8HfiShc9CYrf/iu5UVVs5EDQ="; + public String signature(HypixelPlayer player) { + return "N1ypz7pBZlbwToXhi3vBN1naQCOPXQq9l3Ps2V5FEsLlIgXQTe9AUKGYsHxmxlu6rinMX2euQn1eyv3eS759C6LrqGoMdBYLJbLClyBy8VfaDOZjaCUG6f6wmRNaGcoce0Cf7wB9QC+tgutuy1QV6AtefdpgMQPYCDXLLzbjqwUyIJ/sLzViiecZXN8g13dd8f4LipRXCPV10xtO8Kq3eXLZeyOj6r4HE+R6UVQ+QIEvG857XmnH1o0ehmwRBg/0ftbgsVPgprfu8M0LgYb6VVswpMou++jXhUDzvHKzOICVNsKMC3BLouXzsVqSXhFP081kkw/cqVaHgtMXbRTxGIfIoPg+Q6sB53fqGe6U04M3YpjtlQO+SvmRAwpU2Zcqu39KhjBs0z58uawx1PNKo6dJkRgP1RpIkkPCJTQukNPrICxvy7o+s22DA5y7T5y8Hf4G5LbQ7q1stqiflttZ8RvHImVXL4biw9EACxGcqy04CdEXTh36lm2Il/r85cLTK2D94z18xFuQ4RYP1DVkmoDW1me5qOqNYhMy9hC9/ZW6QkhMJ9gmpDDqxpAeIDdFc3w1YNkS527smpLimdjY3gbxxl2AtGU8ZLo72yFCo8s3Ox8vi8TiU4s4HpMtGaL8bS3Sfr7z+aB4pJTmQwY/Ll4dLyzK7aLPWdCoiEQbQt0="; } @Override - public String texture(HypixelPlayer player) { //easter skin - return "ewogICJ0aW1lc3RhbXAiIDogMTYxODY1NTk1Mjg1NiwKICAicHJvZmlsZUlkIiA6ICJkMGI4MjE1OThmMTE0NzI1ODBmNmNiZTliOGUxYmU3MCIsCiAgInByb2ZpbGVOYW1lIiA6ICJqYmFydHl5IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzUyMGEzN2I1ZDA3OWViNzlkODdlZDVlZGEyY2Y5NWE1YWU3NjEwNjJlYjA5NDk5ZWYzMzA3ODQxMDg4M2NhNzIiCiAgICB9CiAgfQp9"; + public String texture(HypixelPlayer player) { + return "eyJ0aW1lc3RhbXAiOjE1NDUxNTQ2NzY3MjEsInByb2ZpbGVJZCI6ImRiYTJmMTE1NmNjMjQwMWJhOWU5YjRkMjdmN2M4OTdkIiwicHJvZmlsZU5hbWUiOiJjb2RlbmFtZV9CIiwic2lnbmF0dXJlUmVxdWlyZWQiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS85NTJiYjQ4YWYyZjU3ZDZhYzljOGU4NzVjMGM5ODc3YTM5NTNmMDQ4MDgxN2QyODQxZTU4NmU3NDdjODdjZTBjIn19fQ=="; } @Override public Pos position(HypixelPlayer player) { - return new Pos(7, 70, -85, 25, 0); - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; + return new Pos(-9.5, 71, -15.5, 0, 0); } }); } @@ -52,7 +46,7 @@ public DialogueSet[] dialogues(HypixelPlayer player) { DialogueSet.builder() .key("hello").lines(new String[]{ "Thank you for supporting the server and allowing us maintain SkyBlock!", - "If you want to support us, head over to the Hypixel Store§b store.hypixel.net" + "If you want to support us, head over to the Hypixel Store §bstore.hypixel.net§f!" }).build() ).toArray(DialogueSet[]::new); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/SkyBlockGenericLoader.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/SkyBlockGenericLoader.java index 9c1f868e7..044f64611 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/SkyBlockGenericLoader.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/SkyBlockGenericLoader.java @@ -56,6 +56,7 @@ import net.swofty.type.skyblockgeneric.data.monogdb.FairySoulDatabase; import net.swofty.type.skyblockgeneric.data.monogdb.IslandDatabase; import net.swofty.type.skyblockgeneric.data.monogdb.RegionDatabase; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.entity.ServerCrystalImpl; import net.swofty.type.skyblockgeneric.entity.mob.MobRegistry; import net.swofty.type.skyblockgeneric.entity.mob.SkyBlockMob; @@ -270,6 +271,9 @@ public void initialize(MinecraftServer server) { SkyBlockServerAttributes.loadAttributes(AttributeDatabase.getDocument("attributes")); SkyBlockServerAttributes.saveAttributeLoop(); + ElectionManager.checkElectionCycle(); + MinecraftServer.getSchedulerManager().buildTask(ElectionManager::checkElectionCycle).repeat(10, TimeUnit.SECOND).schedule(); + /** * Register Placement Rules */ diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/CalendarEvent.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/CalendarEvent.java index c03cbdf9b..8732f3935 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/CalendarEvent.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/CalendarEvent.java @@ -7,6 +7,7 @@ import net.swofty.commons.StringUtility; import net.swofty.commons.protocol.objects.darkauction.TriggerDarkAuctionProtocol; import net.swofty.proxyapi.ProxyService; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; import org.tinylog.Logger; import java.time.Duration; @@ -18,66 +19,67 @@ import java.util.function.Function; public record CalendarEvent( - String id, - ItemStack representation, - Function displayName, - List description, - List times, - Duration duration, - boolean tracksYear, - BiConsumer action + String id, + ItemStack representation, + Function displayName, + List description, + List times, + Duration duration, + boolean tracksYear, + BiConsumer action ) { private static final long THREE_DAYS = 3 * 20 * 60 * 24; // 3 SkyBlock days in ticks private static final long YEAR = 20 * 60 * 24 * 31 * 12; // Full SkyBlock year in ticks + private static final long MONTH = 744000L; private static final Map> eventCache = new HashMap<>(); private static final List allEvents = new ArrayList<>(); public static CalendarEvent NEW_YEAR = new CalendarEvent( - "new_year", - ItemStack.of(Material.CAKE).with(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, true), - year -> "§d" + StringUtility.ntify(year) + " New Year Celebration", - List.of( - "§7To celebrate the SkyBlock New Year,", - "§7the Baker is giving out free Cake!" - ), - List.of(10L), - Duration.ofHours(1), - true, - (time, year) -> { - // New Year's actions - } + "new_year", + ItemStack.of(Material.CAKE).with(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, true), + year -> "§d" + StringUtility.ntify(year) + " New Year Celebration", + List.of( + "§7To celebrate the SkyBlock New Year,", + "§7the Baker is giving out free Cake!" + ), + List.of(10L), + Duration.ofHours(1), + true, + (time, year) -> { + // New Year's actions + } ); // Dark Auction occurs every 3 SkyBlock days at midnight public static CalendarEvent DARK_AUCTION = new CalendarEvent( - "dark_auction", - ItemStack.of(Material.NETHER_STAR).with(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, true), - year -> "§5Dark Auction", - List.of( - "§7The Dark Auction is a secret", - "§7underground auction where", - "§7special items are sold." - ), - calculateDarkAuctionTimes(), - Duration.ofMinutes(5), - false, - (time, year) -> { - ProxyService darkAuctionService = new ProxyService(ServiceType.DARK_AUCTION); - darkAuctionService.handleRequest(new TriggerDarkAuctionProtocol.TriggerMessage(time)) - .thenAccept(response -> { - if (response instanceof TriggerDarkAuctionProtocol.TriggerResponse triggerResponse) { - if (triggerResponse.success()) { - Logger.info("Dark Auction started successfully"); - } else { - Logger.debug("Dark Auction trigger: {}", triggerResponse.message()); - } - } - }) - .exceptionally(throwable -> { - Logger.error(throwable, "Failed to trigger Dark Auction"); - return null; - }); - } + "dark_auction", + ItemStack.of(Material.NETHER_STAR).with(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, true), + year -> "§5Dark Auction", + List.of( + "§7The Dark Auction is a secret", + "§7underground auction where", + "§7special items are sold." + ), + calculateDarkAuctionTimes(), + Duration.ofMinutes(5), + false, + (time, year) -> { + ProxyService darkAuctionService = new ProxyService(ServiceType.DARK_AUCTION); + darkAuctionService.handleRequest(new TriggerDarkAuctionProtocol.TriggerMessage(time)) + .thenAccept(response -> { + if (response instanceof TriggerDarkAuctionProtocol.TriggerResponse triggerResponse) { + if (triggerResponse.success()) { + Logger.info("Dark Auction started successfully"); + } else { + Logger.debug("Dark Auction trigger: {}", triggerResponse.message()); + } + } + }) + .exceptionally(throwable -> { + Logger.error(throwable, "Failed to trigger Dark Auction"); + return null; + }); + } ); private static List calculateDarkAuctionTimes() { @@ -89,9 +91,44 @@ private static List calculateDarkAuctionTimes() { return times; } + public static CalendarEvent ELECTION_OPEN = new CalendarEvent( + "election_open", + ItemStack.of(Material.JUKEBOX), + year -> "§b" + StringUtility.ntify(year) + " Election Booth Opens", + List.of( + "§7The Mayor Election voting booth", + "§7is now open! Cast your vote for", + "§7your favorite candidate." + ), + List.of(5 * MONTH), + Duration.ofHours(0), + true, + (_, _) -> { + ElectionManager.onElectionStart(); + } + ); + + public static CalendarEvent ELECTION_CLOSE = new CalendarEvent( + "election_close", + ItemStack.of(Material.JUKEBOX), + year -> "§b" + StringUtility.ntify(year) + " Election Over!", + List.of( + "§7The Mayor Election has concluded!", + "§7A new Mayor has been elected." + ), + List.of(8 * MONTH), + Duration.ofHours(0), + true, + (_, _) -> { + ElectionManager.onElectionEnd(); + } + ); + static { registerEvent(NEW_YEAR); registerEvent(DARK_AUCTION); + registerEvent(ELECTION_OPEN); + registerEvent(ELECTION_CLOSE); } public String getDisplayName(int year) { diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java new file mode 100644 index 000000000..03252cb0e --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java @@ -0,0 +1,289 @@ +package net.swofty.type.skyblockgeneric.elections; + +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +@Getter +@Setter +public class ElectionData { + private int electionYear; + + private String currentMayor; + private List currentMayorPerks = new ArrayList<>(); + private int mayorElectedYear; + + private String currentMinister; + private String ministerPerk; + + private List candidates = new ArrayList<>(); + private Map votes = new HashMap<>(); + private boolean electionOpen; + + private Map lastElectedYear = new HashMap<>(); + private Map> candidateActivePerks = new HashMap<>(); + private Map failedPerkGainLastTime = new HashMap<>(); + private int specialCandidateIndex; + + public ElectionData() {} + + public SkyBlockMayor getMayorEnum() { + if (currentMayor == null) return null; + try { + return SkyBlockMayor.valueOf(currentMayor); + } catch (IllegalArgumentException e) { + return null; + } + } + + public SkyBlockMayor getMinisterEnum() { + if (currentMinister == null) return null; + try { + return SkyBlockMayor.valueOf(currentMinister); + } catch (IllegalArgumentException e) { + return null; + } + } + + public SkyBlockMayor.Perk getMinisterPerkEnum() { + if (ministerPerk == null) return null; + try { + return SkyBlockMayor.Perk.valueOf(ministerPerk); + } catch (IllegalArgumentException e) { + return null; + } + } + + public List getCurrentMayorPerkEnums() { + List result = new ArrayList<>(); + for (String perkName : currentMayorPerks) { + try { + result.add(SkyBlockMayor.Perk.valueOf(perkName)); + } catch (IllegalArgumentException ignored) {} + } + return result; + } + + public void castVote(UUID accountId, String candidateName) { + votes.put(accountId.toString(), candidateName); + } + + public String getVote(UUID accountId) { + return votes.get(accountId.toString()); + } + + public Map tallyVotes() { + Map tally = new HashMap<>(); + for (CandidateData candidate : candidates) { + tally.put(candidate.getMayorName(), 0L); + } + for (String candidateName : votes.values()) { + tally.merge(candidateName, 1L, Long::sum); + } + return tally; + } + + public void resolveElection(int currentYear) { + Map tally = tallyVotes(); + List> sorted = new ArrayList<>(tally.entrySet()); + sorted.sort((a, b) -> Long.compare(b.getValue(), a.getValue())); + + if (sorted.isEmpty()) return; + + long topVotes = sorted.getFirst().getValue(); + List> tied = sorted.stream() + .filter(e -> e.getValue() == topVotes).toList(); + + String winnerName; + if (tied.size() > 1) { + winnerName = tied.get(ThreadLocalRandom.current().nextInt(tied.size())).getKey(); + } else { + winnerName = sorted.getFirst().getKey(); + } + + SkyBlockMayor winner = SkyBlockMayor.valueOf(winnerName); + + CandidateData winnerCandidate = candidates.stream() + .filter(c -> c.getMayorName().equals(winnerName)) + .findFirst().orElse(null); + + currentMayor = winnerName; + currentMayorPerks = winnerCandidate != null + ? new ArrayList<>(winnerCandidate.getActivePerks()) + : Arrays.stream(winner.getAllPerks()).map(Enum::name).toList(); + mayorElectedYear = currentYear; + lastElectedYear.put(winnerName, currentYear); + + if (winner.isSpecial()) { + currentMinister = null; + ministerPerk = null; + } else { + String secondPlace = sorted.stream().filter(entry -> !entry.getKey().equals(winnerName)).findFirst().map(Map.Entry::getKey).orElse(null); + if (secondPlace != null) { + SkyBlockMayor ministerMayor = SkyBlockMayor.valueOf(secondPlace); + currentMinister = secondPlace; + + CandidateData ministerCandidate = candidates.stream() + .filter(c -> c.getMayorName().equals(secondPlace)) + .findFirst().orElse(null); + + if (ministerCandidate != null && !ministerCandidate.getActivePerks().isEmpty()) { + List perks = ministerCandidate.getActivePerks(); + ministerPerk = perks.get(ThreadLocalRandom.current().nextInt(perks.size())); + } else { + SkyBlockMayor.Perk[] allPerks = ministerMayor.getAllPerks(); + ministerPerk = allPerks[ThreadLocalRandom.current().nextInt(allPerks.length)].name(); + } + } + } + + for (CandidateData candidate : candidates) { + if (candidate.getMayorName().equals(winnerName)) { + candidateActivePerks.remove(winnerName); + failedPerkGainLastTime.remove(winnerName); + continue; + } + + SkyBlockMayor mayor = SkyBlockMayor.valueOf(candidate.getMayorName()); + if (mayor.isSpecial()) continue; + + List currentPerks = new ArrayList<>(candidate.getActivePerks()); + if (currentPerks.size() < mayor.getAllPerks().length) { + boolean failedLast = Boolean.TRUE.equals(failedPerkGainLastTime.get(candidate.getMayorName())); + boolean gainPerk = failedLast || ThreadLocalRandom.current().nextBoolean(); + + if (gainPerk) { + List available = new ArrayList<>(); + for (SkyBlockMayor.Perk perk : mayor.getAllPerks()) { + if (!currentPerks.contains(perk.name())) { + available.add(perk.name()); + } + } + if (!available.isEmpty()) { + currentPerks.add(available.get(ThreadLocalRandom.current().nextInt(available.size()))); + } + failedPerkGainLastTime.put(candidate.getMayorName(), false); + } else { + failedPerkGainLastTime.put(candidate.getMayorName(), true); + } + } + candidateActivePerks.put(candidate.getMayorName(), currentPerks); + } + + SkyBlockMayor winnerEnum = SkyBlockMayor.valueOf(winnerName); + if (!winnerEnum.isSpecial()) { + SkyBlockMayor.Perk[] allPerks = winnerEnum.getAllPerks(); + SkyBlockMayor.Perk randomPerk = allPerks[ThreadLocalRandom.current().nextInt(allPerks.length)]; + candidateActivePerks.put(winnerName, List.of(randomPerk.name())); + } + + candidates.clear(); + votes.clear(); + electionOpen = false; + } + + public void startNewElection(int year) { + this.electionYear = year; + this.electionOpen = true; + this.votes.clear(); + this.candidates.clear(); + + boolean isSpecialYear = (year % 8 == 0); + + List regularPool = new ArrayList<>(SkyBlockMayor.getRegularMayors()); + if (currentMayor != null) { + regularPool.removeIf(m -> m.name().equals(currentMayor)); + } + + Collections.shuffle(regularPool); + + int regularCount = isSpecialYear ? 4 : 5; + List selected = new ArrayList<>(regularPool.subList(0, Math.min(regularCount, regularPool.size()))); + + for (SkyBlockMayor mayor : selected) { + CandidateData candidate = new CandidateData(); + candidate.setMayorName(mayor.name()); + + List perks = candidateActivePerks.get(mayor.name()); + if (perks == null || perks.isEmpty()) { + SkyBlockMayor.Perk[] allPerks = mayor.getAllPerks(); + candidate.setActivePerks(List.of(allPerks[ThreadLocalRandom.current().nextInt(allPerks.length)].name())); + } else { + candidate.setActivePerks(new ArrayList<>(perks)); + } + candidates.add(candidate); + } + + if (isSpecialYear) { + List specials = SkyBlockMayor.getSpecialMayors(); + SkyBlockMayor specialCandidate = specials.get(specialCandidateIndex % specials.size()); + specialCandidateIndex++; + + CandidateData candidate = new CandidateData(); + candidate.setMayorName(specialCandidate.name()); + candidate.setActivePerks(Arrays.stream(specialCandidate.getAllPerks()).map(Enum::name).toList()); + candidates.add(candidate); + } + + boolean diazLongTerm = currentMinister != null + && currentMinister.equals(SkyBlockMayor.DIAZ.name()) + && ministerPerk != null + && ministerPerk.equals(SkyBlockMayor.Perk.LONG_TERM_INVESTMENT.name()); + + if (diazLongTerm) { + boolean alreadyInElection = candidates.stream() + .anyMatch(c -> c.getMayorName().equals(SkyBlockMayor.DIAZ.name())); + if (!alreadyInElection) { + CandidateData diazCandidate = new CandidateData(); + diazCandidate.setMayorName(SkyBlockMayor.DIAZ.name()); + diazCandidate.setActivePerks(Arrays.stream(SkyBlockMayor.DIAZ.getAllPerks()).map(Enum::name).toList()); + candidates.add(diazCandidate); + } + } + } + + public int getYearsSinceLastElected(String mayorName, int currentYear) { + Integer lastYear = lastElectedYear.get(mayorName); + if (lastYear == null) return -1; + return currentYear - lastYear; + } + + @Getter + @Setter + public static class CandidateData { + private String mayorName; + private List activePerks = new ArrayList<>(); + + public CandidateData() {} + + public SkyBlockMayor getMayorEnum() { + try { + return SkyBlockMayor.valueOf(mayorName); + } catch (IllegalArgumentException e) { + return null; + } + } + + public List getActivePerkEnums() { + List result = new ArrayList<>(); + for (String perkName : activePerks) { + try { + result.add(SkyBlockMayor.Perk.valueOf(perkName)); + } catch (IllegalArgumentException ignored) {} + } + return result; + } + + public boolean hasMinisterPerkMarker(SkyBlockMayor.Perk perk) { + return activePerks.contains(perk.name()); + } + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java new file mode 100644 index 000000000..e42eea92b --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java @@ -0,0 +1,134 @@ +package net.swofty.type.skyblockgeneric.elections; + +import lombok.Getter; +import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; +import net.swofty.type.skyblockgeneric.server.attribute.SkyBlockServerAttributes; +import net.swofty.type.skyblockgeneric.server.attribute.attributes.AttributeString; +import org.tinylog.Logger; +import tools.jackson.databind.DeserializationFeature; +import tools.jackson.databind.SerializationFeature; +import tools.jackson.databind.json.JsonMapper; + +import java.util.Arrays; +import java.util.UUID; + +public class ElectionManager { + private static final JsonMapper MAPPER = JsonMapper.builder() + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .build(); + + @Getter + private static ElectionData electionData = new ElectionData(); + + public static void loadFromAttribute() { + try { + SkyBlockServerAttributes attributes = new SkyBlockServerAttributes(); + AttributeString attr = attributes.get( + SkyBlockServerAttributes.Attributes.ELECTION_DATA, AttributeString.class); + String json = attr.getValue(); + if (json != null && !json.isEmpty() && !json.equals("\"\"")) { + electionData = MAPPER.readValue(json, ElectionData.class); + if (electionData.getCurrentMayor() == null || electionData.getCurrentMinister() == null) { + Logger.warn("Election data is missing mayor or minister. Reinitializing."); + electionData = new ElectionData(); + initializeFirstElection(); + } + } else { + electionData = new ElectionData(); + initializeFirstElection(); + } + } catch (Exception e) { + Logger.error(e, "Failed to load election data"); + electionData = new ElectionData(); + initializeFirstElection(); + } + } + + public static String serializeData() { + try { + return MAPPER.writeValueAsString(electionData); + } catch (Exception e) { + Logger.error(e, "Failed to serialize election data"); + return "{}"; + } + } + + private static void initializeFirstElection() { + int currentYear = SkyBlockCalendar.getYear(); + electionData.setCurrentMayor(SkyBlockMayor.COLE.name()); + electionData.setCurrentMayorPerks( + Arrays.stream(SkyBlockMayor.COLE.getAllPerks()) + .map(Enum::name).toList() + ); + electionData.setMayorElectedYear(currentYear); + electionData.setCurrentMinister(SkyBlockMayor.DIAZ.name()); + electionData.setMinisterPerk(SkyBlockMayor.Perk.STOCK_EXCHANGE.name()); + } + + public static void onElectionStart() { + int currentYear = SkyBlockCalendar.getYear(); + if (electionData.isElectionOpen()) return; + + electionData.startNewElection(currentYear); + Logger.info("Election started for Year {}", currentYear); + } + + public static void onElectionEnd() { + if (!electionData.isElectionOpen()) return; + + int currentYear = SkyBlockCalendar.getYear(); + electionData.resolveElection(currentYear); + Logger.info("Election resolved for Year {}. New Mayor: {}", currentYear, electionData.getCurrentMayor()); + } + + public static void castVote(UUID accountId, String candidateName) { + if (!electionData.isElectionOpen()) return; + + boolean validCandidate = electionData.getCandidates().stream() + .anyMatch(c -> c.getMayorName().equals(candidateName)); + if (!validCandidate) return; + + electionData.castVote(accountId, candidateName); + } + + public static String getPlayerVote(UUID accountId) { + return electionData.getVote(accountId); + } + + public static SkyBlockMayor getCurrentMayor() { + return electionData.getMayorEnum(); + } + + public static SkyBlockMayor getCurrentMinister() { + return electionData.getMinisterEnum(); + } + + public static boolean isMayorPerkActive(SkyBlockMayor.Perk perk) { + return electionData.getCurrentMayorPerkEnums().contains(perk); + } + + public static boolean isMinisterPerkActive(SkyBlockMayor.Perk perk) { + SkyBlockMayor.Perk activePerk = electionData.getMinisterPerkEnum(); + return activePerk != null && activePerk == perk; + } + + public static boolean isPerkActive(SkyBlockMayor.Perk perk) { + return isMayorPerkActive(perk) || isMinisterPerkActive(perk); + } + + public static void checkElectionCycle() { + int currentYear = SkyBlockCalendar.getYear(); + int currentMonth = SkyBlockCalendar.getMonth(); + + if (currentMonth >= 6 && currentMonth <= 8 && !electionData.isElectionOpen()) { + if (electionData.getElectionYear() != currentYear) { + onElectionStart(); + } + } + + if (currentMonth >= 9 && electionData.isElectionOpen()) { + onElectionEnd(); + } + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java new file mode 100644 index 000000000..b85b17e2e --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java @@ -0,0 +1,182 @@ +package net.swofty.type.skyblockgeneric.elections; + +import lombok.Getter; + +import java.util.Arrays; +import java.util.List; + +@Getter +public enum SkyBlockMayor { + AATROX( + "Aatrox", "§a", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTIyNjczMywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzFiZGY1MDViYjhjMGYxZjMzNjVhMDMwMzJkZTE5MzE2NjNmZjcxYzU3ZTAyMjU1OGRlMzEyYjhmMWI1YzQ0NSIKICAgIH0KICB9Cn0=", + "fuSuJuBDgFDBV9878jr/Sgvg5w+DJ1YaXBmgAPurDoScZtarz1pwQ0Tsw+kBPzNYBhD2hOaGHna32ttqlKKufdXFJG09uPlv8nSCHNA7rwl74L0KO7wOn4Bxsa6cS0UsGj3AJYzJ0tnTcF3ILpHUF+C2aYgRvTjm0UXWo1Ai0+bjN67ecb3MlcsuCBDpTQQl8ujvW3xp2krxyJeeKeERMAGTW0QgsuJCrkN3iXrIiv4VWn1TBslutuu8vsltkYcRZcsUljWNtCHYQ/eBt6B8qdoEhierPCepdpdJzwYmcWMaxLWHO336g2Sp541hJDVtS5yCN48rY6UREJfcISJS0HjmVo0862h0JMKNT6ceIAbF/CzLkL+uAnaOCUNdPedrRjevWrKAXAGfd9JXK073ge3X/qDr0HahNFManGA030qHSTz3C7rqTrCVPOLg7QSipFZH0HKGrEyhCPnpZ10zC4UHeFL9zwCEi5L7O+qIrPraJmdJ2lU7QA33mLstL6AEabLZ2LluRRpki+9GIJ/gfjlB50fIHYOJPTykZymPIp1R6fAXyNn32m15WP38c5c4akYTfTq+1+zBupfxYOD2BZTd3x2Ce2klEMnn4Wo4CwkENI/37/kaure7CB0TpM9VCMJaNQZbIc10ehr93qJGCROSxpvT/+KqN6nRhfs7hVk=", + new Perk[]{Perk.SLASHED_PRICING, Perk.SLAYER_XP_BUFF, Perk.PATHFINDER} + ), + COLE( + "Cole", "§e", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MDkwNjkxMiwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTY0MjJkZTA4ODQ4OTUyZDFjYmVhZDY2YmJiYWQ2ZjA3MTkxYmRjYzk1MmYzZDEwMzZhZWIwYzIyOTM4ZjM5YiIKICAgIH0KICB9Cn0=", + "FWvg7q7AORwUPOYVUNH4xjgwxOhzLm2rnBJH4mHkVA/BTYnaLD/hkJkUeMxYFgjArbrw8EvjUmhix7UgptWx0mHWmqssceBuXFHlq1JkzpPubfXpGRpvT+2AUqGSgHGHW9Gxeo0jtGr+mOvIABP+FPHs72dmYWZYW5TJCfw+8e8KhayferdStTKaDanpFi2RGxe3uZjMh3ZoKSxGugCxiAR/7cwIAAW1px4Z9ZmxhzFtQIp+Deyh871IVEjhOyYjs8QZtZCPGr6QAuH4wd1srXU1FJqU2lDGa/DYj4tBFl0bfO2oczJUuy5UJQWFZFbS7uBVAP5P5en2pvg04eqghlksCEQ/npzZolGSjSmobxlOf/8CXy9vYBNp12W1DlzC8RkQnNhC/3Mm8JWciSechunP4NfAig9QG5UJiy2WjeiwWnLyk4OpDaYA09hVjuxJ12xuScggkYwbPDdsyU1SftLynjoB6ktHamiFtg1DvuIqdfl8T4Qd8iGBTk00b49NoI9+LB9Yu6fNiGbYgMKzsr5LAStaAtvFApQolsreGjCUX6K62qr+0HmKX10esO+yi3cFvj20Yy/BS8xfLrakx4Z3f3wzk/0ONSHtoHLO/PbZTlLxtRypjenTnqV95dMRmBhjdS0RG9vUmvtEISN4CiFMTsMJU6QJg77Lmp5Tz7A=", + new Perk[]{Perk.PROSPECTION, Perk.MINING_XP_BUFF, Perk.MINING_FIESTA, Perk.MOLTEN_FORGE} + ), + DIANA( + "Diana", "§d", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzk0MjU3NDIzMCwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODNjYzFjZjY3MmE0YjI1NDBiZTM0NmVhZDc5YWMyZDllZDE5ZDk1YjYwNzViZjk1YmUwYjZkMGRhNjEzNzdiZSIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9", + "FepPcmM5MycgGDcxdEFXgQ0ncPuOWemDQRpJguSUc2Xfyz0Dub5OKDAiBOPkWDt7gR/UUOfenDW8XGg0gRFSvw4VR6maV1twwL3S+sn6rgIYfBZ4A5khrVpKNTvXQFDyMPB4780dsvIrM34CAcLzadxdoldT1Z8iibunDXVmLKiJwj9RctTRwdc3nbk/7a1P2pkpUs9JRUwbLwidZJRFbhSMr87jyNiUJzYKAaQ1vXpsWvkRD860PuLrbi8Nf1GInHuxRaIkeMRP6tQKDY7XubW2wIYrDn5MzZf9htnOBKWRx50s3e2qy3PiBgI7iJNbEo9X1qNHBQe6FkHS6zsZLX63kJDSyzq4+xgKZmSvVnPYFKeJLor/gKf+xX9RkVKzZqlU97jNHV+9vXUWfrVoUfCNpNwmK2YR+HT86Q5g0vQyD3gwq1W/QvvFkmgU7sOHRINVNxH6R6QOx3cKKDVaEqPjRKkEMsJOBLsJjNXDRMKg21oh+mhxzSRyjDy6LBBIPLM6m25GUtBhAuMs65gwWeyUAOml1hNLN9knzPVPigv0iAx8BJxvSIhXWkudA0UDDjnNGFGpxinykftWr1FAKo40M+SSnOG58mpOwGJEPxsWQm4k8IY73c1fiAdugh/LbkD2WBS0nc3qHQhZAW8xM7sZaBLhq7Et+9hrQx8qse8=", + new Perk[]{Perk.HUNTRESS_INTUITION, Perk.SHARING_IS_CARING, Perk.LUCKY_PAWS, Perk.PET_XP_BUFF} + ), + // TODO: proper skin for Diaz + DIAZ( + "Diaz", "§d", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", + "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + new Perk[]{Perk.STOCK_EXCHANGE, Perk.LONG_TERM_INVESTMENT, Perk.SHOPPING_SPREE, Perk.VOLUME_TRADING} + ), + FINNEGAN( + "Finnegan", "§e", false, + "ewogICJ0aW1lc3RhbXAiIDogMTY1NDIwMzAxNDc3MiwKICAicHJvZmlsZUlkIiA6ICI0NGNlMmMwZTFjNTM0ZDhmYmExNmNkNDhlYjkyYTUxZSIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4WGlyYW56dThYeCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9lNzc0N2ZiZWU5ZmIzOWJlMzliMDBkM2Q0ODNlYjJmODhiNGJhZTgyNDE3YWI1Y2IxYjFhYTkzMGRkN2I2Njg5IiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=", + "W1VnWYThZuihE6z8wX4XqfYwXIMxSHeXpWabQYntXkBeL+G4tA7Vu5p/IbBIco2w2uVeJZ1HC5HnHFQMgcBSXImHyomGjn4T2NQD9zg4sAAXevh8T9oeAC92qzCCa5wyyzm0hhxFhJ2RHr+JOii0cfaPn+7P6gLxZgVfaRLPJA4d5J+SwaUdTcHBVZm6A0Tzn54T4Acj4tUcWFZNrsqOck9VdJy9gLPvE3xDKDOVk4MTvXUJFRxOEjwWiIKmdP8ccDqy/C3F/zB0fulCXc0e8LWN9RKUQc0NSiz+TFetzZbNhi6PApA7DaicNKbZcj9DCDiGFvZUi2YMiadI25h7yhkF98uUc06Bg1soe8UTKok4LAFpt93CHr9ISFGXF34SnMSphbIWvsp34KgmdDOxAbSCogHDFfbozzljS2t07DHD0TiWfA+6WbzL6WB94774A/c8iPOFcPnmdBHodeYjp5bn8GBn+Bzu4dbOJxFmEj4940ZrYgYG1USwaw69hApXxmDJbzeD6oojiceT2CARGrFAxwpI9TvMU2ZtLATnS01vXxlX8NVcR+ovR1awuPOB/NiCY0kCxs/2pi65Glm09NqAK8AurFJXK/ueHYnV+FzuutSybvc78Mn2+iwgzOoxD0GM9fqw9eC70tI+10daitNyIi9QK0R6yfi3WpzxEzs=", + new Perk[]{Perk.PEST_ERADICATOR, Perk.GOATED, Perk.PELT_POCALYPSE, Perk.BLOOMING_BUSINESS} + ), + FOXY( + "Foxy", "§b", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", + "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + new Perk[]{Perk.SWEET_BENEVOLENCE, Perk.A_TIME_FOR_GIVING, Perk.CHIVALROUS_CARNIVAL, Perk.EXTRA_EVENT} + ), + // TODO: proper skin for Marina + MARINA( + "Marina", "§b", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", + "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + new Perk[]{Perk.FISHING_XP_BUFF, Perk.LUCK_OF_THE_SEA, Perk.FISHING_FESTIVAL, Perk.DOUBLE_TROUBLE} + ), + PAUL( + "Paul", "§c", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MDk0OTYzOCwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWI1OWM0M2Q4ZGJjY2ZkN2VjNmU2Mzk0YjYzMDRiNzBkNGVkMzE1YWRkMDQ5NGVlNzdjNzMzZjQxODE4YzczYSIKICAgIH0KICB9Cn0=", + "UeEf0Ir81BLTBE0PfVeEtU/6mHUw3xSP7XGcQYN18qlYS6J7qd+bQskaSJQbEHXr+axq2+5aPm/AfGrjNnl9zQn1EucBIwhdRBHnjuJeRY6x9VKEHAtX2gnpnNelU/oP6MKPZ1dUad4iAHQg8BmJR/oQpedvOJDuqdUZowe8WTVFC5qctJQWRIZCX0BWYK1O1xxJx4FZ9LzF++7qWZsVqO+qmOR8R7Xr4jFkF8cdNIRyezgcfhmw3BCqiDDheOzuJzo0l7y9kHR82reHus/JBLGyTy/iqMqlZFgNePEoaOGRgIvROw9oIS4R/19+UABIe0MDD6CSGgsE7VfgWeyCVw3qxmCSAZDHnYuYyH0zpnGQRsmQrx9aTjFXHf6g551MEpx7KGGTMaOm9b7ygOGuVGB/52UXR2W9UU+YtBZoUzDPMeVcM1NQno/fY3rLoSf5PfuaaEpZMlczYpH0DBvApEQ6FBm/XTOPeS5w3a+7UXh/wrjXu5b62rXG4SNZaBZRT76eseX3wZoCGiLYEh+IXfAJxXSKOqmlHmRmv6FGRzMcZpHzr63GqD0jJwpLuUZ54uuMgUtjx/liEZG1pesdUuf0ObRVf+xDxk/iLAiNKRvd6BoP7wVm0CkebDlyPObdKW0Ss+tAhB0y1o4das+n+UjpHUuPM2D/eLZFA01umyw=", + new Perk[]{Perk.MARAUDER, Perk.BENEDICTION, Perk.EZPZ} + ), + // TODO: proper skin for Barry + BARRY( + "Barry", "§d", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", + "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + new Perk[]{Perk.SEAL_OF_APPROVAL, Perk.HOT_STUFF, Perk.ARCANE_CATALYST, Perk.GOVERNMENT_REFORM} + ), + // TODO: proper skin for Scorpius + SCORPIUS( + "Scorpius", "§5", true, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", + "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + new Perk[]{Perk.BRIBE, Perk.DARKER_AUCTIONS} + ), + // TODO: proper skin for Derpy + DERPY( + "Derpy", "§6", true, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", + "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + new Perk[]{Perk.TURBO_MINIONS, Perk.AH_CLOSED, Perk.DOUBLE_MOBS_HP, Perk.MOAR_SKILLZ} + ), + // TODO: proper skin for Jerry + JERRY( + "Jerry", "§d", true, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", + "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + new Perk[]{Perk.PERKPOCALYPSE, Perk.STATSPOCALYPSE, Perk.JERRYPOCALYPSE} + ); + + private final String displayName; + private final String color; + private final boolean special; + private final String texture; + private final String signature; + private final Perk[] allPerks; + + SkyBlockMayor(String displayName, String color, boolean special, String texture, String signature, Perk[] allPerks) { + this.displayName = displayName; + this.color = color; + this.special = special; + this.texture = texture; + this.signature = signature; + this.allPerks = allPerks; + } + + public String getColoredName() { + return color + displayName; + } + + public static List getRegularMayors() { + return Arrays.stream(values()).filter(m -> !m.special).toList(); + } + + public static List getSpecialMayors() { + return Arrays.stream(values()).filter(m -> m.special).toList(); + } + + @Getter + public enum Perk { + SLASHED_PRICING("SLASHED Pricing", "§7Starting slayer quests is §ehalf price§7."), + SLAYER_XP_BUFF("Slayer XP Buff", "§7Earn §d25% §7more Slayer XP."), + PATHFINDER("Pathfinder", "§7Gain rare drops §d20% §7more often."), + + PROSPECTION("Prospection", "§7Mining minions work §a25% §7faster."), + MINING_XP_BUFF("Mining XP Buff", "§7Get §3+60☯ Mining Wisdom §7on public islands."), + MINING_FIESTA("Mining Fiesta", "§7Schedules 5 §6Mining Fiestas §7throughout the year!"), + MOLTEN_FORGE("Molten Forge", "§7Decrease the time it takes to §6forge §7items by §d25%§7."), + + HUNTRESS_INTUITION("Huntress' Intuition", "§7Gain §d+10❃ Tracking§7."), + SHARING_IS_CARING("Sharing is Caring", "§7Unlocks §a2 §7more §6Exp Share §7slots in your pets menu and increases the §6Exp Share §7rate by §a+10%§7!"), + LUCKY_PAWS("Lucky Paws", "§7Increases chance of finding rare Mythological creatures by §a+15%§7."), + PET_XP_BUFF("Pet XP Buff", "§7Gain §a+35% §7more pet experience from all sources."), + + STOCK_EXCHANGE("Stock Exchange", "§7Participate in the §dStonks Auction §7for a chance to win §5Stock of Stonks§7! Trade them for §6extravagant items §7at the §bTrade Center§7."), + LONG_TERM_INVESTMENT("Long Term Investment", "§7The §dMinister §7reappears in the next election with §aall §7of their perks."), + SHOPPING_SPREE("Shopping Spree", "§7Reduces NPC shop prices by §a20%§7."), + VOLUME_TRADING("Volume Trading", "§7Bazaar sell/buy orders are §a10% §7cheaper."), + + PEST_ERADICATOR("Pest Eradicator", "§7The duration of Pesthunter Phillip's §6☘ Farming Fortune §7bonus is now §a60m§7. Decreases the spawn cooldown of §2Pests §7by §a20%§7."), + GOATED("GOATed", "§eJacob's Farming Contest §7brackets include up to §a10% §7more players each."), + PELT_POCALYPSE("Pelt-pocalypse", "§7Obtain §a1.5x §7more §5pelts §7from §aTrevor §7in the §eMushroom Desert§7."), + BLOOMING_BUSINESS("Blooming Business", "§7All Garden Visitors reward §aFine Flour§7 and §c+10% Copper §7for accepting offers."), + + SWEET_BENEVOLENCE("Sweet Benevolence", "§7Earn §a+30% §7more §dCandy§7, §cGifts §7and §6Chocolate §7from duplicate rabbits during their respective events."), + A_TIME_FOR_GIVING("A Time for Giving", "§7Spawn §dParty Chests §7by killing mobs during the §6Spooky Festival §7and collect §bParty Gifts §7from §cJerry's Workshop§7."), + CHIVALROUS_CARNIVAL("Chivalrous Carnival", "§7Schedules a §eCarnival §7in the hub, active throughout the §bentire year§7."), + EXTRA_EVENT("Extra Event", "§7Schedules an extra §6Spooky Festival §7event during the year."), + + FISHING_XP_BUFF("Fishing XP Buff", "§7Get §3+50☯ Fishing Wisdom §7on public islands."), + LUCK_OF_THE_SEA("Luck of the Sea 2.0", "§7Gain §a+15 ☂ Sea Creature Chance§7."), + FISHING_FESTIVAL("Fishing Festival", "§7Schedules 5 §6Fishing Festivals §7throughout the year!"), + DOUBLE_TROUBLE("Double Trouble", "§7Fishing minions work §a50% §7faster."), + + MARAUDER("Marauder", "§7Dungeon reward chests are §e20% §7cheaper."), + BENEDICTION("Benediction", "§7Blessings are §d25% §7stronger."), + EZPZ("EZPZ", "§7Gain §e+25% §7more class experience."), + + SEAL_OF_APPROVAL("Seal of Approval", "§7Rare items from the §dWizard Tower §7are §a5% §7more common."), + HOT_STUFF("Hot Stuff", "§7Get §d+10% §7bonus stats from Hot Potato Books on weapons and armor."), + ARCANE_CATALYST("Arcane Catalyst", "§7Enchanting pet XP is boosted §a50%§7."), + GOVERNMENT_REFORM("Government Reform", "§7Influence the perks of the current Mayor by selecting §a1 §7of §a3 §7options from a special menu."), + + BRIBE("Bribe", "§7If Scorpius wins, all players receive a §6gift §7at the §aElection Room §7based on their rank."), + DARKER_AUCTIONS("Darker Auctions", "§7During Scorpius's term, the §5Dark Auction §7sells extra rare items."), + + TURBO_MINIONS("TURBO MINIONS!!!", "§7All minions work §a2x §7faster!"), + AH_CLOSED("AH CLOSED!!!", "§7Auction House is closed for the duration."), + DOUBLE_MOBS_HP("DOUBLE MOBS HP!!!", "§7All mobs have §c2x §7more health."), + MOAR_SKILLZ("MOAR SKILLZ!!!", "§7Earn §d+50% §7more skill experience."), + + PERKPOCALYPSE("Perkpocalypse", "§7All previously elected Mayor §aperks §7are activated!"), + STATSPOCALYPSE("Statspocalypse", "§7Gain §a+10% §7to all stats."), + JERRYPOCALYPSE("Jerrypocalypse", "§5Perk unknown until elected..."); + + private final String displayName; + private final String description; + + Perk(String displayName, String description) { + this.displayName = displayName; + this.description = description; + } + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElection.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElection.java new file mode 100644 index 000000000..efc77a75e --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElection.java @@ -0,0 +1,173 @@ +package net.swofty.type.skyblockgeneric.gui.inventories.election; + +import net.minestom.server.entity.PlayerSkin; +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; +import net.swofty.type.generic.gui.inventory.item.GUIItem; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class GUIElection extends HypixelInventoryGUI { + + public GUIElection() { + super("Election", InventoryType.CHEST_3_ROW); + } + + @Override + public void onOpen(InventoryGUIOpenEvent e) { + ElectionData data = ElectionManager.getElectionData(); + + if (!data.isElectionOpen() || data.getCandidates().isEmpty()) { + set(new GUIItem(13) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return ItemStackCreator.getStack( + "§cNo Active Election", + Material.BARRIER, + 1, + "§7There is no active election", + "§7at this time." + ); + } + }); + updateItemStacks(getInventory(), getPlayer()); + return; + } + + int currentYear = SkyBlockCalendar.getYear(); + String playerVote = ElectionManager.getPlayerVote(getPlayer().getUuid()); + Map tally = data.tallyVotes(); + long totalVotes = tally.values().stream().mapToLong(Long::longValue).sum(); + + List candidates = data.getCandidates(); + int[] slots = getCandidateSlots(candidates.size()); + + for (int i = 0; i < candidates.size(); i++) { + ElectionData.CandidateData candidate = candidates.get(i); + SkyBlockMayor mayor = candidate.getMayorEnum(); + if (mayor == null) continue; + + int slot = slots[i]; + boolean isVotedFor = candidate.getMayorName().equals(playerVote); + long votes = tally.getOrDefault(candidate.getMayorName(), 0L); + String voteStr = formatVotes(votes); + String pctStr = totalVotes > 0 + ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; + + int yearsSince = data.getYearsSinceLastElected(candidate.getMayorName(), currentYear); + + set(new GUIClickableItem(slot) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + List lore = buildCandidateLore( + mayor, candidate, data.getElectionYear(), + yearsSince, voteStr, pctStr, isVotedFor + ); + return ItemStackCreator.getStackHead( + mayor.getColoredName(), + new PlayerSkin(mayor.getTexture(), mayor.getSignature()), + 1, + lore.toArray(new String[0]) + ); + } + + @Override + public void run(InventoryPreClickEvent event, HypixelPlayer player) { + ElectionManager.castVote(player.getUuid(), candidate.getMayorName()); + player.sendMessage("§aYou voted for " + mayor.getColoredName() + "§a!"); + new GUIElection().open(player); + } + }); + } + + updateItemStacks(getInventory(), getPlayer()); + } + + private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.CandidateData candidate, + int electionYear, int yearsSince, + String voteStr, String pctStr, boolean votedFor) { + List lore = new ArrayList<>(); + lore.add("§8Year " + electionYear + " Candidate"); + lore.add(""); + lore.add("§7Votes: " + mayor.getColor() + voteStr + " §7(" + mayor.getColor() + pctStr + "§7)"); + if (yearsSince >= 0) { + lore.add("§7Last elected: " + mayor.getColor() + yearsSince + "y ago"); + } else { + lore.add("§7Last elected: " + mayor.getColor() + "Never"); + } + lore.add(""); + lore.add("§8§m--------------------------"); + + List activePerks = candidate.getActivePerkEnums(); + for (int j = 0; j < activePerks.size(); j++) { + SkyBlockMayor.Perk perk = activePerks.get(j); + if (j == 0) { + lore.add("§6✯ " + mayor.getColor() + perk.getDisplayName()); + } else { + lore.add(mayor.getColor() + perk.getDisplayName()); + } + lore.add(perk.getDescription()); + if (j < activePerks.size() - 1) lore.add(""); + } + + lore.add("§8§m--------------------------"); + + if (!mayor.isSpecial()) { + lore.add(""); + lore.add("§6✯ " + mayor.getColor() + "Minister Perks §7are also granted if"); + lore.add("§7this mayor wins second place!"); + } + + lore.add(""); + if (votedFor) { + lore.add("§aYou voted for this candidate!"); + } else { + lore.add("§8You may change your vote at any"); + lore.add("§8time until the election ends!"); + lore.add(""); + lore.add("§eClick to vote for " + mayor.getDisplayName() + "!"); + } + + return lore; + } + + private int[] getCandidateSlots(int count) { + return switch (count) { + case 1 -> new int[]{13}; + case 2 -> new int[]{11, 15}; + case 3 -> new int[]{11, 13, 15}; + case 4 -> new int[]{10, 12, 14, 16}; + case 5 -> new int[]{9, 11, 13, 15, 17}; + case 6 -> new int[]{9, 11, 13, 15, 17, 18}; + default -> new int[]{9, 11, 13, 15, 17}; + }; + } + + private String formatVotes(long votes) { + if (votes >= 1_000_000) return String.format("%.1fM", votes / 1_000_000.0); + if (votes >= 1_000) return String.format("%.1fk", votes / 1_000.0); + return String.valueOf(votes); + } + + @Override + public boolean allowHotkeying() { + return false; + } + + @Override + public void onBottomClick(InventoryPreClickEvent e) { + e.setCancelled(true); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElectionViewStats.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElectionViewStats.java new file mode 100644 index 000000000..b43870f55 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElectionViewStats.java @@ -0,0 +1,168 @@ +package net.swofty.type.skyblockgeneric.gui.inventories.election; + +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.item.GUIItem; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class GUIElectionViewStats extends HypixelInventoryGUI { + + public GUIElectionViewStats() { + super("Election Stats", InventoryType.CHEST_6_ROW); + } + + @Override + public void onOpen(InventoryGUIOpenEvent e) { + ElectionData data = ElectionManager.getElectionData(); + + if (!data.isElectionOpen() || data.getCandidates().isEmpty()) { + set(new GUIItem(22) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return ItemStackCreator.getStack( + "§cNo Active Election", + Material.BARRIER, + 1, + "§7There is no active election", + "§7at this time." + ); + } + }); + updateItemStacks(getInventory(), getPlayer()); + return; + } + + int currentYear = SkyBlockCalendar.getYear(); + String playerVote = ElectionManager.getPlayerVote(getPlayer().getUuid()); + Map tally = data.tallyVotes(); + long totalVotes = tally.values().stream().mapToLong(Long::longValue).sum(); + + List candidates = data.getCandidates(); + + for (int i = 0; i < candidates.size() && i < 5; i++) { + ElectionData.CandidateData candidate = candidates.get(i); + SkyBlockMayor mayor = candidate.getMayorEnum(); + if (mayor == null) continue; + + boolean isVotedFor = candidate.getMayorName().equals(playerVote); + long votes = tally.getOrDefault(candidate.getMayorName(), 0L); + String voteStr = formatVotes(votes); + String pctStr = totalVotes > 0 + ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; + int yearsSince = data.getYearsSinceLastElected(candidate.getMayorName(), currentYear); + + int col = i * 2; + + for (int row = 0; row < 6; row++) { + int slot = row * 9 + col; + int finalRow = row; + + set(new GUIItem(slot) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + if (finalRow == 0) { + List lore = buildCandidateLore( + mayor, candidate, data.getElectionYear(), + yearsSince, voteStr, pctStr, isVotedFor + ); + return ItemStackCreator.getStack( + mayor.getColoredName(), + Material.GRAY_STAINED_GLASS_PANE, + 1, + lore.toArray(new String[0]) + ); + } + + int barHeight = totalVotes > 0 ? (int) Math.ceil((votes * 5.0) / totalVotes) : 0; + int barRow = 6 - finalRow; + if (barRow <= barHeight) { + return ItemStackCreator.getStack( + mayor.getColor() + voteStr + " votes", + Material.LIME_STAINED_GLASS_PANE, + 1, + mayor.getColor() + pctStr + ); + } + return ItemStackCreator.getStack(" ", + Material.BLACK_STAINED_GLASS_PANE, 1); + } + }); + } + } + + updateItemStacks(getInventory(), getPlayer()); + } + + private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.CandidateData candidate, + int electionYear, int yearsSince, + String voteStr, String pctStr, boolean votedFor) { + List lore = new ArrayList<>(); + lore.add("§8Year " + electionYear + " Candidate"); + lore.add(""); + lore.add("§7Votes: " + mayor.getColor() + voteStr + " §7(" + mayor.getColor() + pctStr + "§7)"); + if (yearsSince >= 0) { + lore.add("§7Last elected: " + mayor.getColor() + yearsSince + "y ago"); + } else { + lore.add("§7Last elected: " + mayor.getColor() + "Never"); + } + lore.add(""); + lore.add("§8§m--------------------------"); + + List activePerks = candidate.getActivePerkEnums(); + for (int j = 0; j < activePerks.size(); j++) { + SkyBlockMayor.Perk perk = activePerks.get(j); + if (j == 0) { + lore.add("§6✯ " + mayor.getColor() + perk.getDisplayName()); + } else { + lore.add(mayor.getColor() + perk.getDisplayName()); + } + lore.add(perk.getDescription()); + if (j < activePerks.size() - 1) lore.add(""); + } + + lore.add("§8§m--------------------------"); + + if (!mayor.isSpecial()) { + lore.add(""); + lore.add("§6✯ " + mayor.getColor() + "Minister Perks §7are also granted if"); + lore.add("§7this mayor wins second place!"); + } + + lore.add(""); + if (votedFor) { + lore.add("§aYou voted for this candidate!"); + } else { + lore.add("§eClick to vote for " + mayor.getDisplayName() + "!"); + } + + return lore; + } + + private String formatVotes(long votes) { + if (votes >= 1_000_000) return String.format("%.1fM", votes / 1_000_000.0); + if (votes >= 1_000) return String.format("%.1fk", votes / 1_000.0); + return String.valueOf(votes); + } + + @Override + public boolean allowHotkeying() { + return false; + } + + @Override + public void onBottomClick(InventoryPreClickEvent e) { + e.setCancelled(true); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMayorMenu.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMayorMenu.java new file mode 100644 index 000000000..2a13de1d4 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMayorMenu.java @@ -0,0 +1,91 @@ +package net.swofty.type.skyblockgeneric.gui.inventories.election; + +import net.minestom.server.entity.PlayerSkin; +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; +import net.swofty.type.generic.gui.inventory.item.GUIItem; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; + +import java.util.ArrayList; +import java.util.List; + +public class GUIMayorMenu extends HypixelInventoryGUI { + + public GUIMayorMenu() { + super("Mayor", InventoryType.CHEST_4_ROW); + } + + @Override + public void onOpen(InventoryGUIOpenEvent e) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return; + + ElectionData data = ElectionManager.getElectionData(); + List activePerks = data.getCurrentMayorPerkEnums(); + + set(new GUIItem(11) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + List lore = new ArrayList<>(); + lore.add("§8Perks List"); + lore.add(""); + lore.add("§8§m--------------------------"); + + for (SkyBlockMayor.Perk perk : activePerks) { + lore.add(mayor.getColor() + perk.getDisplayName()); + lore.add(perk.getDescription()); + lore.add(""); + } + + lore.add("§8§m--------------------------"); + lore.add(""); + lore.add("§7The listed perks are available to"); + lore.add("§7all players until the closing of"); + lore.add("§7the next elections."); + + return ItemStackCreator.getStackHead( + mayor.getColor() + "Mayor " + mayor.getDisplayName(), + new PlayerSkin(mayor.getTexture(), mayor.getSignature()), + 1, + lore.toArray(new String[0]) + ); + } + }); + + set(new GUIItem(15) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return ItemStackCreator.getStack( + "§bElection & Voting", + Material.JUKEBOX, + 1, + "§7View the current election", + "§7candidates and cast your vote.", + "", + "§eClick to view!" + ); + } + }); + + set(GUIClickableItem.getCloseItem(31)); + updateItemStacks(getInventory(), getPlayer()); + } + + @Override + public boolean allowHotkeying() { + return false; + } + + @Override + public void onBottomClick(InventoryPreClickEvent e) { + e.setCancelled(true); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMinisterMenu.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMinisterMenu.java new file mode 100644 index 000000000..6f05c7d7d --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMinisterMenu.java @@ -0,0 +1,74 @@ +package net.swofty.type.skyblockgeneric.gui.inventories.election; + +import net.minestom.server.entity.PlayerSkin; +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; +import net.swofty.type.generic.gui.inventory.item.GUIItem; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; + +import java.util.ArrayList; +import java.util.List; + +public class GUIMinisterMenu extends HypixelInventoryGUI { + + public GUIMinisterMenu() { + super("Minister", InventoryType.CHEST_4_ROW); + } + + @Override + public void onOpen(InventoryGUIOpenEvent e) { + SkyBlockMayor minister = ElectionManager.getCurrentMinister(); + if (minister == null) return; + + ElectionData data = ElectionManager.getElectionData(); + SkyBlockMayor.Perk activePerk = data.getMinisterPerkEnum(); + + set(new GUIItem(11) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + List lore = new ArrayList<>(); + lore.add("§8Active Perk"); + lore.add(""); + lore.add("§8§m--------------------------"); + + if (activePerk != null) { + lore.add(minister.getColor() + activePerk.getDisplayName()); + lore.add(activePerk.getDescription()); + } + + lore.add("§8§m--------------------------"); + lore.add(""); + lore.add("§7The Minister is who came in 2nd Place"); + lore.add("§7during the election. They have one"); + lore.add("§7of their perks active."); + + return ItemStackCreator.getStackHead( + minister.getColor() + "Minister " + minister.getDisplayName(), + new PlayerSkin(minister.getTexture(), minister.getSignature()), + 1, + lore.toArray(new String[0]) + ); + } + }); + + set(GUIClickableItem.getCloseItem(31)); + updateItemStacks(getInventory(), getPlayer()); + } + + @Override + public boolean allowHotkeying() { + return false; + } + + @Override + public void onBottomClick(InventoryPreClickEvent e) { + e.setCancelled(true); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/SkyBlockServerAttributes.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/SkyBlockServerAttributes.java index fea831334..6ebaff7ae 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/SkyBlockServerAttributes.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/SkyBlockServerAttributes.java @@ -1,6 +1,5 @@ package net.swofty.type.skyblockgeneric.server.attribute; -import org.tinylog.Logger; import lombok.Getter; import net.minestom.server.MinecraftServer; import net.minestom.server.timer.ExecutionType; @@ -9,8 +8,11 @@ import net.swofty.type.generic.HypixelTypeLoader; import net.swofty.type.generic.data.mongodb.AttributeDatabase; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.server.attribute.attributes.AttributeLong; +import net.swofty.type.skyblockgeneric.server.attribute.attributes.AttributeString; import org.bson.Document; +import org.tinylog.Logger; import tools.jackson.core.JacksonException; import java.util.Arrays; @@ -73,7 +75,10 @@ public static void saveAttributeLoop() { public enum Attributes { CALENDER_ELAPSED_TIME("elapsed", AttributeLong.class, new AttributeLong("elapsed", 0L), (attribute) -> { SkyBlockCalendar.setElapsed((Long) attribute.getValue()); - }, (server) -> new AttributeLong("elapsed", SkyBlockCalendar.getElapsed())); + }, (server) -> new AttributeLong("elapsed", SkyBlockCalendar.getElapsed())), + ELECTION_DATA("election_data", AttributeString.class, new AttributeString("election_data", ""), (attribute) -> { + ElectionManager.loadFromAttribute(); + }, (server) -> new AttributeString("election_data", ElectionManager.serializeData())); @Getter private final String key; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/attributes/AttributeString.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/attributes/AttributeString.java new file mode 100644 index 000000000..de2081c8e --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/attributes/AttributeString.java @@ -0,0 +1,16 @@ +package net.swofty.type.skyblockgeneric.server.attribute.attributes; + +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.type.skyblockgeneric.server.attribute.ServerAttribute; + +public class AttributeString extends ServerAttribute { + private static final JacksonSerializer serializer = new JacksonSerializer<>(String.class); + + public AttributeString(String key, String value) { + super(key, value, serializer); + } + + public AttributeString(String key) { + super(key, null, serializer); + } +} From 26ba41a5689bb904198ae83b103beb9c588e0b39 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:46:05 +0200 Subject: [PATCH 02/17] feat: election service --- .../java/net/swofty/commons/ServiceType.java | 1 + .../election/CastVoteProtocolObject.java | 70 +++++++++++ .../election/GetCandidatesProtocolObject.java | 82 +++++++++++++ .../GetElectionDataProtocolObject.java | 64 ++++++++++ .../SaveElectionDataProtocolObject.java | 58 +++++++++ .../main/java/net/swofty/loader/Hypixel.java | 8 +- .../net/swofty/proxyapi/ProxyService.java | 35 +++--- service.elections/build.gradle.kts | 47 ++++++++ .../service/election/ElectionDatabase.java | 93 ++++++++++++++ .../service/election/ElectionService.java | 27 +++++ .../election/endpoints/CastVoteEndpoint.java | 68 +++++++++++ .../endpoints/GetCandidatesEndpoint.java | 75 ++++++++++++ .../endpoints/GetElectionDataEndpoint.java | 29 +++++ .../endpoints/SaveElectionDataEndpoint.java | 30 +++++ settings.gradle.kts | 1 + .../data/datapoints/DatapointToggles.java | 1 + .../net/swofty/type/hub/TypeHubLoader.java | 2 +- .../swofty/type/hub/npcs/NPCCurrentMayor.java | 4 +- .../type/hub/npcs/NPCCurrentMinister.java | 4 +- .../type/hub/npcs/NPCMuseumDisplay.java | 2 +- .../SkyBlockGenericLoader.java | 11 +- .../calendar/SkyBlockCalendar.java | 45 ++++++- .../darkauction/DarkAuctionHandler.java | 4 +- .../elections/ElectionCandidate.java | 42 +++++++ .../elections/ElectionManager.java | 80 ++++++++---- .../{GUIElection.java => ElectionView.java} | 101 +++++++--------- ...wStats.java => ElectionViewStatsView.java} | 114 ++++++++---------- .../inventories/election/GUIMayorMenu.java | 91 -------------- .../inventories/election/GUIMinisterMenu.java | 74 ------------ .../inventories/election/MayorMenuView.java | 74 ++++++++++++ .../election/MinisterMenuView.java | 62 ++++++++++ .../sbmenu/calendar/GUICalendar.java | 41 ++++--- .../attribute/SkyBlockServerAttributes.java | 8 +- 33 files changed, 1081 insertions(+), 367 deletions(-) create mode 100644 commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java create mode 100644 commons/src/main/java/net/swofty/commons/protocol/objects/election/GetCandidatesProtocolObject.java create mode 100644 commons/src/main/java/net/swofty/commons/protocol/objects/election/GetElectionDataProtocolObject.java create mode 100644 commons/src/main/java/net/swofty/commons/protocol/objects/election/SaveElectionDataProtocolObject.java create mode 100644 service.elections/build.gradle.kts create mode 100644 service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java create mode 100644 service.elections/src/main/java/net/swofty/service/election/ElectionService.java create mode 100644 service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java create mode 100644 service.elections/src/main/java/net/swofty/service/election/endpoints/GetCandidatesEndpoint.java create mode 100644 service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java create mode 100644 service.elections/src/main/java/net/swofty/service/election/endpoints/SaveElectionDataEndpoint.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionCandidate.java rename type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/{GUIElection.java => ElectionView.java} (64%) rename type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/{GUIElectionViewStats.java => ElectionViewStatsView.java} (57%) delete mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMayorMenu.java delete mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMinisterMenu.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java diff --git a/commons/src/main/java/net/swofty/commons/ServiceType.java b/commons/src/main/java/net/swofty/commons/ServiceType.java index b72b4a97e..8dfd259b0 100644 --- a/commons/src/main/java/net/swofty/commons/ServiceType.java +++ b/commons/src/main/java/net/swofty/commons/ServiceType.java @@ -11,5 +11,6 @@ public enum ServiceType { ORCHESTRATOR, FRIEND, PUNISHMENT, + ELECTION, ; } diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java new file mode 100644 index 000000000..c2f8b0c36 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java @@ -0,0 +1,70 @@ +package net.swofty.commons.protocol.objects.election; + +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; +import org.json.JSONObject; + +import java.util.UUID; + +public class CastVoteProtocolObject + extends ProtocolObject { + + @Override + public Serializer getSerializer() { + return new Serializer<>() { + @Override + public String serialize(CastVoteMessage value) { + JSONObject json = new JSONObject(); + json.put("accountId", value.accountId().toString()); + json.put("candidateName", value.candidateName()); + return json.toString(); + } + + @Override + public CastVoteMessage deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new CastVoteMessage( + UUID.fromString(obj.getString("accountId")), + obj.getString("candidateName") + ); + } + + @Override + public CastVoteMessage clone(CastVoteMessage value) { + return value; + } + }; + } + + @Override + public Serializer getReturnSerializer() { + return new Serializer<>() { + @Override + public String serialize(CastVoteResponse value) { + JSONObject json = new JSONObject(); + json.put("success", value.success()); + json.put("serializedData", value.serializedData()); + return json.toString(); + } + + @Override + public CastVoteResponse deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new CastVoteResponse( + obj.getBoolean("success"), + obj.optString("serializedData", null) + ); + } + + @Override + public CastVoteResponse clone(CastVoteResponse value) { + return value; + } + }; + } + + public record CastVoteMessage(UUID accountId, String candidateName) {} + + public record CastVoteResponse(boolean success, String serializedData) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetCandidatesProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetCandidatesProtocolObject.java new file mode 100644 index 000000000..ed1a13ef3 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetCandidatesProtocolObject.java @@ -0,0 +1,82 @@ +package net.swofty.commons.protocol.objects.election; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; +import org.json.JSONObject; + +import java.util.List; + +public class GetCandidatesProtocolObject + extends ProtocolObject { + + @Override + public Serializer getSerializer() { + return new Serializer<>() { + @Override + public String serialize(GetCandidatesMessage value) { + return new JSONObject().put("_", true).toString(); + } + + @Override + public GetCandidatesMessage deserialize(String json) { + return new GetCandidatesMessage(); + } + + @Override + public GetCandidatesMessage clone(GetCandidatesMessage value) { + return value; + } + }; + } + + @Override + public Serializer getReturnSerializer() { + return new Serializer<>() { + private final Gson gson = new Gson(); + + @Override + public String serialize(GetCandidatesResponse value) { + JSONObject json = new JSONObject(); + json.put("electionOpen", value.electionOpen()); + json.put("candidates", gson.toJson(value.candidates())); + return json.toString(); + } + + @Override + public GetCandidatesResponse deserialize(String json) { + JSONObject obj = new JSONObject(json); + boolean open = obj.getBoolean("electionOpen"); + List candidates = List.of(); + if (!obj.isNull("candidates")) { + candidates = gson.fromJson( + obj.getString("candidates"), + new TypeToken>() {}.getType() + ); + } + return new GetCandidatesResponse(open, candidates); + } + + @Override + public GetCandidatesResponse clone(GetCandidatesResponse value) { + return value; + } + }; + } + + public record GetCandidatesMessage() {} + + public record GetCandidatesResponse( + boolean electionOpen, + List candidates + ) {} + + public record CandidateInfo( + String mayorName, + List activePerks, + long votes, + double votePercentage + ) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetElectionDataProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetElectionDataProtocolObject.java new file mode 100644 index 000000000..4e604498b --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetElectionDataProtocolObject.java @@ -0,0 +1,64 @@ +package net.swofty.commons.protocol.objects.election; + +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; +import org.json.JSONObject; + +public class GetElectionDataProtocolObject + extends ProtocolObject { + + @Override + public Serializer getSerializer() { + return new Serializer<>() { + @Override + public String serialize(GetElectionDataMessage value) { + return new JSONObject().put("_", true).toString(); + } + + @Override + public GetElectionDataMessage deserialize(String json) { + return new GetElectionDataMessage(); + } + + @Override + public GetElectionDataMessage clone(GetElectionDataMessage value) { + return value; + } + }; + } + + @Override + public Serializer getReturnSerializer() { + return new Serializer<>() { + @Override + public String serialize(GetElectionDataResponse value) { + JSONObject json = new JSONObject(); + json.put("found", value.found()); + json.put("data", value.serializedData()); + return json.toString(); + } + + @Override + public GetElectionDataResponse deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new GetElectionDataResponse( + obj.getBoolean("found"), + obj.optString("data", null) + ); + } + + @Override + public GetElectionDataResponse clone(GetElectionDataResponse value) { + return value; + } + }; + } + + public record GetElectionDataMessage() {} + + public record GetElectionDataResponse( + boolean found, + String serializedData + ) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/SaveElectionDataProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/SaveElectionDataProtocolObject.java new file mode 100644 index 000000000..a6e59d65e --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/SaveElectionDataProtocolObject.java @@ -0,0 +1,58 @@ +package net.swofty.commons.protocol.objects.election; + +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; +import org.json.JSONObject; + +public class SaveElectionDataProtocolObject + extends ProtocolObject { + + @Override + public Serializer getSerializer() { + return new Serializer<>() { + @Override + public String serialize(SaveElectionDataMessage value) { + JSONObject json = new JSONObject(); + json.put("data", value.serializedData()); + return json.toString(); + } + + @Override + public SaveElectionDataMessage deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new SaveElectionDataMessage(obj.getString("data")); + } + + @Override + public SaveElectionDataMessage clone(SaveElectionDataMessage value) { + return value; + } + }; + } + + @Override + public Serializer getReturnSerializer() { + return new Serializer<>() { + @Override + public String serialize(SaveElectionDataResponse value) { + return new JSONObject().put("success", value.success()).toString(); + } + + @Override + public SaveElectionDataResponse deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new SaveElectionDataResponse(obj.getBoolean("success")); + } + + @Override + public SaveElectionDataResponse clone(SaveElectionDataResponse value) { + return value; + } + }; + } + + public record SaveElectionDataMessage(String serializedData) {} + + public record SaveElectionDataResponse(boolean success) {} +} diff --git a/loader/src/main/java/net/swofty/loader/Hypixel.java b/loader/src/main/java/net/swofty/loader/Hypixel.java index 94365de2b..efcd5fd8d 100644 --- a/loader/src/main/java/net/swofty/loader/Hypixel.java +++ b/loader/src/main/java/net/swofty/loader/Hypixel.java @@ -133,8 +133,10 @@ static void main(String[] args) { new HypixelGenericLoader(typeLoader).initialize(minecraftServer); // Initialize TypeLoader + SkyBlockGenericLoader skyblockLoader = null; if (typeLoader instanceof SkyBlockTypeLoader) { - new SkyBlockGenericLoader(typeLoader).initialize(minecraftServer); + skyblockLoader = new SkyBlockGenericLoader(typeLoader); + skyblockLoader.initialize(minecraftServer); } if (typeLoader instanceof RavengardTypeLoader) { new RavengardGenericLoader(typeLoader).initialize(minecraftServer); @@ -183,7 +185,11 @@ static void main(String[] args) { } }); }); + typeLoader.afterInitialize(minecraftServer); + if (skyblockLoader != null) { + skyblockLoader.afterInitialize(); + } // Start the server MinecraftServer.setBrandName("Hypixel"); diff --git a/proxy.api/src/main/java/net/swofty/proxyapi/ProxyService.java b/proxy.api/src/main/java/net/swofty/proxyapi/ProxyService.java index 57ccf99b4..4ab62136a 100644 --- a/proxy.api/src/main/java/net/swofty/proxyapi/ProxyService.java +++ b/proxy.api/src/main/java/net/swofty/proxyapi/ProxyService.java @@ -4,7 +4,6 @@ import net.swofty.commons.protocol.ProtocolObject; import net.swofty.commons.protocol.objects.PingProtocolObject; import net.swofty.proxyapi.redis.ServerOutboundMessage; -import org.tinylog.Logger; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -16,17 +15,17 @@ public CompletableFuture isOnline() { AtomicBoolean hasReceivedResponse = new AtomicBoolean(false); ServerOutboundMessage.sendMessageToService(type, new PingProtocolObject(), - new PingProtocolObject.EmptyMessage(), (s) -> { - future.complete(true); - hasReceivedResponse.set(true); - }); + new PingProtocolObject.EmptyMessage(), (s) -> { + future.complete(true); + hasReceivedResponse.set(true); + }); CompletableFuture.delayedExecutor(150, TimeUnit.MILLISECONDS) - .execute(() -> { - if (!hasReceivedResponse.get()) { - future.complete(false); - } - }); + .execute(() -> { + if (!hasReceivedResponse.get()) { + future.complete(false); + } + }); return future; } @@ -35,13 +34,15 @@ public CompletableFuture handleRequest(T request) { ProtocolObject protocolObject = ServerOutboundMessage.protocolObjects.get(request.getClass().getSimpleName()); CompletableFuture future = new CompletableFuture<>(); - Thread.startVirtualThread(() -> { - ServerOutboundMessage.sendMessageToService(type, protocolObject, request, (s) -> { - Thread.startVirtualThread(() -> { - future.complete(protocolObject.translateReturnFromString(s)); - }); - }); - }); + Thread.startVirtualThread(() -> + ServerOutboundMessage.sendMessageToService( + type, + protocolObject, + request, + (s) -> Thread.startVirtualThread( + () -> future.complete(protocolObject.translateReturnFromString(s)) + ) + )); return future; } } diff --git a/service.elections/build.gradle.kts b/service.elections/build.gradle.kts new file mode 100644 index 000000000..4ec8e0379 --- /dev/null +++ b/service.elections/build.gradle.kts @@ -0,0 +1,47 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + java + application + id("com.gradleup.shadow") version "9.3.1" +} + +group = "net.swofty" +version = "3.0" + +java { + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 + toolchain { + languageVersion.set(JavaLanguageVersion.of(25)) + } +} + +repositories { + maven("https://jitpack.io") + mavenCentral() +} + +dependencies { + implementation(project(":service.generic")) + implementation(project(":commons")) + implementation("com.github.ben-manes.caffeine:caffeine:3.2.3") + implementation("org.tinylog:tinylog-api:2.7.0") + implementation("org.tinylog:tinylog-impl:2.7.0") + implementation("com.google.code.gson:gson:2.11.0") + implementation("org.mongodb:bson:5.6.2") + implementation("org.mongodb:mongodb-driver-sync:5.6.2") + implementation("redis.clients:jedis:7.2.0") +} + +application { + mainClass.set("net.swofty.service.election.ElectionService") +} + +tasks { + named("shadowJar") { + archiveBaseName.set("ServiceElection") + archiveClassifier.set("") + archiveVersion.set("") + } +} diff --git a/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java b/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java new file mode 100644 index 000000000..40d63bc31 --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java @@ -0,0 +1,93 @@ +package net.swofty.service.election; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Updates; +import net.swofty.service.generic.MongoDB; +import org.bson.Document; + +public record ElectionDatabase(String key) implements MongoDB { + public static MongoClient client; + public static MongoDatabase database; + public static MongoCollection electionCollection; + + @Override + public MongoDB connect(String connectionString) { + ConnectionString cs = new ConnectionString(connectionString); + MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build(); + client = MongoClients.create(settings); + + database = client.getDatabase("Minestom"); + electionCollection = database.getCollection("elections"); + return this; + } + + @Override + public void set(String key, Object value) { + insertOrUpdate(key, value); + } + + @Override + public boolean exists() { + Document query = new Document("_id", key); + Document found = electionCollection.find(query).first(); + return found != null; + } + + @Override + public Object get(String key, Object def) { + Document doc = electionCollection.find(Filters.eq("_id", this.key)).first(); + if (doc == null) { + return def; + } + return doc.get(key); + } + + @Override + public void insertOrUpdate(String key, Object value) { + if (exists()) { + Document query = new Document("_id", this.key); + Document found = electionCollection.find(query).first(); + assert found != null; + electionCollection.updateOne(found, Updates.set(key, value)); + return; + } + Document newDoc = new Document("_id", this.key); + newDoc.append(key, value); + electionCollection.insertOne(newDoc); + } + + @Override + public boolean remove(String id) { + Document query = new Document("_id", id); + Document found = electionCollection.find(query).first(); + if (found == null) { + return false; + } + electionCollection.deleteOne(query); + return true; + } + + public static String loadElectionData() { + Document doc = electionCollection.find(Filters.eq("_id", "election_data")).first(); + if (doc == null) return null; + return doc.getString("data"); + } + + public static void saveElectionData(String serializedData) { + Document query = new Document("_id", "election_data"); + Document existing = electionCollection.find(query).first(); + if (existing != null) { + electionCollection.updateOne(query, Updates.set("data", serializedData)); + } else { + Document newDoc = new Document("_id", "election_data"); + newDoc.append("data", serializedData); + electionCollection.insertOne(newDoc); + } + } +} diff --git a/service.elections/src/main/java/net/swofty/service/election/ElectionService.java b/service.elections/src/main/java/net/swofty/service/election/ElectionService.java new file mode 100644 index 000000000..79396fe4b --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/ElectionService.java @@ -0,0 +1,27 @@ +package net.swofty.service.election; + +import net.swofty.commons.ServiceType; +import net.swofty.commons.config.ConfigProvider; +import net.swofty.service.generic.SkyBlockService; +import net.swofty.service.generic.redis.ServiceEndpoint; + +import java.util.List; + +public class ElectionService implements SkyBlockService { + + static void main(String[] args) { + String mongoUri = ConfigProvider.settings().getMongodb(); + new ElectionDatabase(null).connect(mongoUri); + SkyBlockService.init(new ElectionService()); + } + + @Override + public ServiceType getType() { + return ServiceType.ELECTION; + } + + @Override + public List getEndpoints() { + return loopThroughPackage("net.swofty.service.election.endpoints", ServiceEndpoint.class).toList(); + } +} diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java new file mode 100644 index 000000000..9eacd1a30 --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java @@ -0,0 +1,68 @@ +package net.swofty.service.election.endpoints; + +import com.google.gson.Gson; +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.objects.election.CastVoteProtocolObject; +import net.swofty.service.election.ElectionDatabase; +import net.swofty.service.generic.redis.ServiceEndpoint; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CastVoteEndpoint implements ServiceEndpoint + { + + private static final Gson GSON = new Gson(); + + @Override + public ProtocolObject associatedProtocolObject() { + return new CastVoteProtocolObject(); + } + + @Override + @SuppressWarnings("unchecked") + public CastVoteProtocolObject.CastVoteResponse onMessage( + ServiceProxyRequest message, + CastVoteProtocolObject.CastVoteMessage messageObject) { + try { + String rawData = ElectionDatabase.loadElectionData(); + if (rawData == null) { + return new CastVoteProtocolObject.CastVoteResponse(false, null); + } + + Map data = GSON.fromJson(rawData, Map.class); + Boolean electionOpen = (Boolean) data.get("electionOpen"); + if (electionOpen == null || !electionOpen) { + return new CastVoteProtocolObject.CastVoteResponse(false, null); + } + + List> candidates = (List>) data.get("candidates"); + if (candidates == null) candidates = new ArrayList<>(); + + boolean validCandidate = candidates.stream() + .anyMatch(c -> messageObject.candidateName().equals(c.get("mayorName"))); + if (!validCandidate) { + return new CastVoteProtocolObject.CastVoteResponse(false, null); + } + + Map votes = (Map) data.get("votes"); + if (votes == null) { + votes = new HashMap<>(); + data.put("votes", votes); + } + votes.put(messageObject.accountId().toString(), messageObject.candidateName()); + + String updatedData = GSON.toJson(data); + ElectionDatabase.saveElectionData(updatedData); + + return new CastVoteProtocolObject.CastVoteResponse(true, updatedData); + } catch (Exception e) { + return new CastVoteProtocolObject.CastVoteResponse(false, null); + } + } +} diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetCandidatesEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetCandidatesEndpoint.java new file mode 100644 index 000000000..d5ae2d8d3 --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetCandidatesEndpoint.java @@ -0,0 +1,75 @@ +package net.swofty.service.election.endpoints; + +import com.google.gson.Gson; +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.objects.election.GetCandidatesProtocolObject; +import net.swofty.service.election.ElectionDatabase; +import net.swofty.service.generic.redis.ServiceEndpoint; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class GetCandidatesEndpoint implements ServiceEndpoint + { + + private static final Gson GSON = new Gson(); + + @Override + public ProtocolObject associatedProtocolObject() { + return new GetCandidatesProtocolObject(); + } + + @Override + @SuppressWarnings("unchecked") + public GetCandidatesProtocolObject.GetCandidatesResponse onMessage( + ServiceProxyRequest message, + GetCandidatesProtocolObject.GetCandidatesMessage messageObject) { + try { + String rawData = ElectionDatabase.loadElectionData(); + if (rawData == null) { + return new GetCandidatesProtocolObject.GetCandidatesResponse(false, List.of()); + } + + Map data = GSON.fromJson(rawData, Map.class); + Boolean electionOpen = (Boolean) data.get("electionOpen"); + if (electionOpen == null || !electionOpen) { + return new GetCandidatesProtocolObject.GetCandidatesResponse(false, List.of()); + } + + List> candidates = (List>) data.get("candidates"); + if (candidates == null || candidates.isEmpty()) { + return new GetCandidatesProtocolObject.GetCandidatesResponse(true, List.of()); + } + + Map votes = (Map) data.get("votes"); + if (votes == null) votes = Map.of(); + + Map tally = new java.util.HashMap<>(); + for (Map c : candidates) { + tally.put((String) c.get("mayorName"), 0L); + } + for (String candidateName : votes.values()) { + tally.merge(candidateName, 1L, Long::sum); + } + long totalVotes = tally.values().stream().mapToLong(Long::longValue).sum(); + + List infos = new ArrayList<>(); + for (Map c : candidates) { + String name = (String) c.get("mayorName"); + List perks = (List) c.get("activePerks"); + if (perks == null) perks = List.of(); + long voteCount = tally.getOrDefault(name, 0L); + double pct = totalVotes > 0 ? (voteCount * 100.0) / totalVotes : 0; + infos.add(new GetCandidatesProtocolObject.CandidateInfo(name, perks, voteCount, pct)); + } + + return new GetCandidatesProtocolObject.GetCandidatesResponse(true, infos); + } catch (Exception e) { + return new GetCandidatesProtocolObject.GetCandidatesResponse(false, List.of()); + } + } +} diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java new file mode 100644 index 000000000..76ee8baef --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java @@ -0,0 +1,29 @@ +package net.swofty.service.election.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.objects.election.GetElectionDataProtocolObject; +import net.swofty.service.election.ElectionDatabase; +import net.swofty.service.generic.redis.ServiceEndpoint; + +public class GetElectionDataEndpoint implements ServiceEndpoint + { + + @Override + public ProtocolObject associatedProtocolObject() { + return new GetElectionDataProtocolObject(); + } + + @Override + public GetElectionDataProtocolObject.GetElectionDataResponse onMessage( + ServiceProxyRequest message, + GetElectionDataProtocolObject.GetElectionDataMessage messageObject) { + String data = ElectionDatabase.loadElectionData(); + if (data == null) { + return new GetElectionDataProtocolObject.GetElectionDataResponse(false, null); + } + return new GetElectionDataProtocolObject.GetElectionDataResponse(true, data); + } +} diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/SaveElectionDataEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/SaveElectionDataEndpoint.java new file mode 100644 index 000000000..aaa074e23 --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/SaveElectionDataEndpoint.java @@ -0,0 +1,30 @@ +package net.swofty.service.election.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.objects.election.SaveElectionDataProtocolObject; +import net.swofty.service.election.ElectionDatabase; +import net.swofty.service.generic.redis.ServiceEndpoint; + +public class SaveElectionDataEndpoint implements ServiceEndpoint + { + + @Override + public ProtocolObject associatedProtocolObject() { + return new SaveElectionDataProtocolObject(); + } + + @Override + public SaveElectionDataProtocolObject.SaveElectionDataResponse onMessage( + ServiceProxyRequest message, + SaveElectionDataProtocolObject.SaveElectionDataMessage messageObject) { + try { + ElectionDatabase.saveElectionData(messageObject.serializedData()); + return new SaveElectionDataProtocolObject.SaveElectionDataResponse(true); + } catch (Exception e) { + return new SaveElectionDataProtocolObject.SaveElectionDataResponse(false); + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index aa5316412..d3db14d90 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -51,4 +51,5 @@ include(":service.orchestrator") include(":service.darkauction") include(":service.friend") include(":service.punishment") +include(":service.elections") include(":anticheat") diff --git a/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointToggles.java b/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointToggles.java index 02f09a1c5..03b5d9d04 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointToggles.java +++ b/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointToggles.java @@ -75,6 +75,7 @@ public enum ToggleType { DISABLE_DROP_MESSAGES(false), HAS_SPOKEN_TO_BEA(false), HAS_SPOKEN_TO_GAVIN(false), + HAS_VISITED_DARK_AUCTION(false), HAS_SPOKEN_TO_TIA(false), HAS_SPOKEN_TO_LIFT_OPERATOR(false), HAS_SPOKEN_TO_LAZY_MINER(false), diff --git a/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java b/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java index 85d1b8096..00bd48257 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java +++ b/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java @@ -219,7 +219,7 @@ public List getProxyRedisListeners() { @Override public List getRequiredServices() { - return List.of(ServiceType.AUCTION_HOUSE, ServiceType.BAZAAR, ServiceType.ITEM_TRACKER, ServiceType.DATA_MUTEX); + return List.of(ServiceType.ELECTION, ServiceType.AUCTION_HOUSE, ServiceType.BAZAAR, ServiceType.ITEM_TRACKER, ServiceType.DATA_MUTEX); } @Override diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java index 72407f950..cda09d9d9 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java @@ -7,7 +7,7 @@ import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import net.swofty.type.skyblockgeneric.gui.inventories.election.GUIMayorMenu; +import net.swofty.type.skyblockgeneric.gui.inventories.election.MayorMenuView; public class NPCCurrentMayor extends HypixelNPC { @@ -53,6 +53,6 @@ public void onClick(NPCInteractEvent event) { event.player().sendMessage("§cHello!!"); return; } - new GUIMayorMenu().open(event.player()); + event.player().openView(new MayorMenuView()); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java index 8c69c8908..19f44afd0 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java @@ -7,7 +7,7 @@ import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import net.swofty.type.skyblockgeneric.gui.inventories.election.GUIMinisterMenu; +import net.swofty.type.skyblockgeneric.gui.inventories.election.MinisterMenuView; public class NPCCurrentMinister extends HypixelNPC { @@ -53,6 +53,6 @@ public void onClick(NPCInteractEvent event) { event.player().sendMessage("§cHello!!"); return; } - new GUIMinisterMenu().open(event.player()); + event.player().openView(new MinisterMenuView()); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCMuseumDisplay.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCMuseumDisplay.java index 7b8137e8c..d6052e563 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCMuseumDisplay.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCMuseumDisplay.java @@ -42,7 +42,7 @@ public String[] holograms(HypixelPlayer p) { return new String[]{ "§b" + username, - "§a" + profileName + "§eProfile: §a" + profileName }; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/SkyBlockGenericLoader.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/SkyBlockGenericLoader.java index 044f64611..69470182a 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/SkyBlockGenericLoader.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/SkyBlockGenericLoader.java @@ -270,10 +270,6 @@ public void initialize(MinecraftServer server) { SkyBlockCalendar.tick(MinecraftServer.getSchedulerManager()); SkyBlockServerAttributes.loadAttributes(AttributeDatabase.getDocument("attributes")); SkyBlockServerAttributes.saveAttributeLoop(); - - ElectionManager.checkElectionCycle(); - MinecraftServer.getSchedulerManager().buildTask(ElectionManager::checkElectionCycle).repeat(10, TimeUnit.SECOND).schedule(); - /** * Register Placement Rules */ @@ -558,6 +554,13 @@ public void initialize(MinecraftServer server) { }); } + public void afterInitialize() { + CompletableFuture.runAsync(() -> { + ElectionManager.loadFromService(); + ElectionManager.checkElectionCycle(); + }).thenRun(() -> MinecraftServer.getSchedulerManager().buildTask(ElectionManager::checkElectionCycle).repeat(10, TimeUnit.SECOND).schedule()); + } + public static List getLoadedPlayers() { List players = new ArrayList<>(); MinecraftServer.getConnectionManager().getOnlinePlayers() diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java index 2bc1e5e00..ecbeae5f0 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java @@ -129,9 +129,8 @@ public static Map getEventsWithDurationUntil(int amoun } long timeUntilBegin = eventElapsed - currentElapsed; - int eventYear = targetYear; - EventInfo info = new EventInfo(timeUntilBegin, event.duration(), eventYear); + EventInfo info = new EventInfo(timeUntilBegin, event.duration(), targetYear); result.put(info, event); foundEvents++; } @@ -145,6 +144,48 @@ public static Map getEventsWithDurationUntil(int amoun return result; } + public static Map getEventsWithDurationUntilSkipSpecific(int amount, List event) { + Map result = new LinkedHashMap<>(); + long currentElapsed = getElapsed(); + int currentYear = getYear(); + + int foundEvents = 0; + int yearsAhead = 0; + + while (foundEvents < amount) { + int targetYear = currentYear + yearsAhead; + long yearStartElapsed = (long) (targetYear - 1) * YEAR; + + for (CalendarEvent e : CalendarEvent.getAllEvents()) { + if (event.contains(e)) continue; // Skip specified events + if (foundEvents >= amount) break; + + for (Long eventTime : e.times()) { + if (foundEvents >= amount) break; + + long eventElapsed = yearStartElapsed + eventTime; + + // Skip events that have already passed (including currently ongoing ones that started) + if (eventElapsed <= currentElapsed) { + continue; + } + + long timeUntilBegin = eventElapsed - currentElapsed; + + EventInfo info = new EventInfo(timeUntilBegin, e.duration(), targetYear); + result.put(info, e); + foundEvents++; + } + } + yearsAhead++; + + // Safety check to prevent infinite loops + if (yearsAhead > 100) break; + } + + return result; + } + public static String getMonthName(long elapsed) { return getMonthName((int) ((elapsed / MONTH) % 12) + 1); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/darkauction/DarkAuctionHandler.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/darkauction/DarkAuctionHandler.java index e808e7ce3..01322e6f0 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/darkauction/DarkAuctionHandler.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/darkauction/DarkAuctionHandler.java @@ -8,12 +8,13 @@ import net.swofty.commons.ServerType; import net.swofty.commons.ServiceType; import net.swofty.commons.StringUtility; +import net.swofty.commons.protocol.objects.darkauction.PlayerLeftAuctionProtocol; import net.swofty.commons.skyblock.auctions.DarkAuctionPhase; import net.swofty.commons.skyblock.item.ItemType; -import net.swofty.commons.protocol.objects.darkauction.PlayerLeftAuctionProtocol; import net.swofty.commons.skyblock.statistics.ItemStatistic; import net.swofty.commons.skyblock.statistics.ItemStatistics; import net.swofty.proxyapi.ProxyService; +import net.swofty.type.generic.data.datapoints.DatapointToggles; import net.swofty.type.skyblockgeneric.SkyBlockGenericLoader; import net.swofty.type.skyblockgeneric.item.SkyBlockItem; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; @@ -145,6 +146,7 @@ public static void handleAuctionBegin(JSONObject msg) { for (UUID playerId : playersInAuction) { SkyBlockPlayer player = SkyBlockGenericLoader.getFromUUID(playerId); + player.getToggles().set(DatapointToggles.Toggles.ToggleType.HAS_VISITED_DARK_AUCTION, true); if (player != null) { player.sendMessage(NPC_PREFIX + "Come on down to the basement, the auction is about to begin!"); player.teleport(new Pos(91, 75, 182, 0, 0)); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionCandidate.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionCandidate.java new file mode 100644 index 000000000..84f3f5e4e --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionCandidate.java @@ -0,0 +1,42 @@ +package net.swofty.type.skyblockgeneric.elections; + +import net.swofty.commons.protocol.objects.election.GetCandidatesProtocolObject; + +import java.util.List; + +public record ElectionCandidate( + SkyBlockMayor mayor, + List activePerks, + long votes, + double votePercentage +) { + + public static ElectionCandidate fromProtocol(GetCandidatesProtocolObject.CandidateInfo info) { + SkyBlockMayor mayor; + try { + mayor = SkyBlockMayor.valueOf(info.mayorName()); + } catch (IllegalArgumentException e) { + return null; + } + + List perks = info.activePerks().stream() + .map(name -> { + try { + return SkyBlockMayor.Perk.valueOf(name); + } catch (IllegalArgumentException e) { + return null; + } + }) + .filter(p -> p != null) + .toList(); + + return new ElectionCandidate(mayor, perks, info.votes(), info.votePercentage()); + } + + public static List fromProtocolList(List infos) { + return infos.stream() + .map(ElectionCandidate::fromProtocol) + .filter(c -> c != null) + .toList(); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java index e42eea92b..9e7ead5f3 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java @@ -1,56 +1,68 @@ package net.swofty.type.skyblockgeneric.elections; +import com.google.gson.Gson; import lombok.Getter; +import net.swofty.commons.ServiceType; +import net.swofty.commons.protocol.objects.election.CastVoteProtocolObject; +import net.swofty.commons.protocol.objects.election.GetCandidatesProtocolObject; +import net.swofty.commons.protocol.objects.election.GetElectionDataProtocolObject; +import net.swofty.commons.protocol.objects.election.SaveElectionDataProtocolObject; +import net.swofty.proxyapi.ProxyService; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; -import net.swofty.type.skyblockgeneric.server.attribute.SkyBlockServerAttributes; -import net.swofty.type.skyblockgeneric.server.attribute.attributes.AttributeString; import org.tinylog.Logger; -import tools.jackson.databind.DeserializationFeature; -import tools.jackson.databind.SerializationFeature; -import tools.jackson.databind.json.JsonMapper; import java.util.Arrays; +import java.util.List; import java.util.UUID; +import java.util.concurrent.CompletableFuture; public class ElectionManager { - private static final JsonMapper MAPPER = JsonMapper.builder() - .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .build(); + + private static final Gson GSON = new Gson(); + private static ProxyService SERVICE; @Getter private static ElectionData electionData = new ElectionData(); - public static void loadFromAttribute() { + public static void loadFromService() { + SERVICE = new ProxyService(ServiceType.ELECTION); try { - SkyBlockServerAttributes attributes = new SkyBlockServerAttributes(); - AttributeString attr = attributes.get( - SkyBlockServerAttributes.Attributes.ELECTION_DATA, AttributeString.class); - String json = attr.getValue(); - if (json != null && !json.isEmpty() && !json.equals("\"\"")) { - electionData = MAPPER.readValue(json, ElectionData.class); + GetElectionDataProtocolObject.GetElectionDataResponse response = + SERVICE.handleRequest( + new GetElectionDataProtocolObject.GetElectionDataMessage() + ).join(); + + if (response.found() && response.serializedData() != null) { + electionData = GSON.fromJson(response.serializedData(), ElectionData.class); if (electionData.getCurrentMayor() == null || electionData.getCurrentMinister() == null) { - Logger.warn("Election data is missing mayor or minister. Reinitializing."); electionData = new ElectionData(); initializeFirstElection(); + saveToService(); + Logger.info("Election data was missing mayor or minister info. Reinitialized first election."); } } else { electionData = new ElectionData(); initializeFirstElection(); + saveToService(); + Logger.info("Election data was missing mayor or minister info."); } } catch (Exception e) { - Logger.error(e, "Failed to load election data"); + Logger.error(e, "Failed to load election data from service"); electionData = new ElectionData(); initializeFirstElection(); } } - public static String serializeData() { + public static void saveToService() { try { - return MAPPER.writeValueAsString(electionData); + String serialized = GSON.toJson(electionData); + SERVICE.handleRequest( + new SaveElectionDataProtocolObject.SaveElectionDataMessage(serialized) + ); } catch (Exception e) { - Logger.error(e, "Failed to serialize election data"); - return "{}"; + Logger.error(e, "Failed to save election data to service"); } } @@ -71,6 +83,7 @@ public static void onElectionStart() { if (electionData.isElectionOpen()) return; electionData.startNewElection(currentYear); + saveToService(); Logger.info("Election started for Year {}", currentYear); } @@ -79,17 +92,27 @@ public static void onElectionEnd() { int currentYear = SkyBlockCalendar.getYear(); electionData.resolveElection(currentYear); + saveToService(); Logger.info("Election resolved for Year {}. New Mayor: {}", currentYear, electionData.getCurrentMayor()); } - public static void castVote(UUID accountId, String candidateName) { - if (!electionData.isElectionOpen()) return; + public static CompletableFuture castVote(UUID accountId, String candidateName) { + if (!electionData.isElectionOpen()) return CompletableFuture.completedFuture(null); boolean validCandidate = electionData.getCandidates().stream() .anyMatch(c -> c.getMayorName().equals(candidateName)); - if (!validCandidate) return; + if (!validCandidate) return CompletableFuture.completedFuture(null); electionData.castVote(accountId, candidateName); + + return SERVICE.handleRequest( + new CastVoteProtocolObject.CastVoteMessage(accountId, candidateName) + ).thenAccept(response -> { + if (response.success() && response.serializedData() != null) { + electionData = GSON.fromJson(response.serializedData(), ElectionData.class); + } + }); } public static String getPlayerVote(UUID accountId) { @@ -117,6 +140,13 @@ public static boolean isPerkActive(SkyBlockMayor.Perk perk) { return isMayorPerkActive(perk) || isMinisterPerkActive(perk); } + public static CompletableFuture> fetchCandidates() { + return SERVICE.handleRequest( + new GetCandidatesProtocolObject.GetCandidatesMessage() + ).thenApply(GetCandidatesProtocolObject.GetCandidatesResponse::candidates); + } + public static void checkElectionCycle() { int currentYear = SkyBlockCalendar.getYear(); int currentMonth = SkyBlockCalendar.getMonth(); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElection.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java similarity index 64% rename from type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElection.java rename to type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java index efc77a75e..b41e2d76e 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElection.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java @@ -1,15 +1,15 @@ package net.swofty.type.skyblockgeneric.gui.inventories.election; import net.minestom.server.entity.PlayerSkin; -import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.inventory.InventoryType; -import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; -import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; -import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; -import net.swofty.type.generic.gui.inventory.item.GUIItem; -import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import net.swofty.type.skyblockgeneric.elections.ElectionData; import net.swofty.type.skyblockgeneric.elections.ElectionManager; @@ -19,35 +19,32 @@ import java.util.List; import java.util.Map; -public class GUIElection extends HypixelInventoryGUI { +public class ElectionView extends StatelessView { - public GUIElection() { - super("Election", InventoryType.CHEST_3_ROW); + @Override + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Election", InventoryType.CHEST_3_ROW); } @Override - public void onOpen(InventoryGUIOpenEvent e) { + public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { + Components.fill(layout); + Components.backOrClose(layout, 22, ctx); + ElectionData data = ElectionManager.getElectionData(); if (!data.isElectionOpen() || data.getCandidates().isEmpty()) { - set(new GUIItem(13) { - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack( - "§cNo Active Election", - Material.BARRIER, - 1, - "§7There is no active election", - "§7at this time." - ); - } - }); - updateItemStacks(getInventory(), getPlayer()); + layout.slot(13, (s, c) -> ItemStackCreator.getStack( + "§cNo Active Election", + Material.BARRIER, + 1, + "§7There is no active election", + "§7at this time." + )); return; } int currentYear = SkyBlockCalendar.getYear(); - String playerVote = ElectionManager.getPlayerVote(getPlayer().getUuid()); Map tally = data.tallyVotes(); long totalVotes = tally.values().stream().mapToLong(Long::longValue).sum(); @@ -60,39 +57,33 @@ public ItemStack.Builder getItem(HypixelPlayer player) { if (mayor == null) continue; int slot = slots[i]; - boolean isVotedFor = candidate.getMayorName().equals(playerVote); long votes = tally.getOrDefault(candidate.getMayorName(), 0L); String voteStr = formatVotes(votes); String pctStr = totalVotes > 0 ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; - int yearsSince = data.getYearsSinceLastElected(candidate.getMayorName(), currentYear); - - set(new GUIClickableItem(slot) { - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - List lore = buildCandidateLore( - mayor, candidate, data.getElectionYear(), - yearsSince, voteStr, pctStr, isVotedFor - ); - return ItemStackCreator.getStackHead( - mayor.getColoredName(), - new PlayerSkin(mayor.getTexture(), mayor.getSignature()), - 1, - lore.toArray(new String[0]) - ); - } - - @Override - public void run(InventoryPreClickEvent event, HypixelPlayer player) { - ElectionManager.castVote(player.getUuid(), candidate.getMayorName()); - player.sendMessage("§aYou voted for " + mayor.getColoredName() + "§a!"); - new GUIElection().open(player); - } + String candidateName = candidate.getMayorName(); + + layout.slot(slot, (s, c) -> { + String playerVote = ElectionManager.getPlayerVote(c.player().getUuid()); + boolean isVotedFor = candidateName.equals(playerVote); + + List lore = buildCandidateLore( + mayor, candidate, data.getElectionYear(), + yearsSince, voteStr, pctStr, isVotedFor + ); + return ItemStackCreator.getStackHead( + mayor.getColoredName(), + new PlayerSkin(mayor.getTexture(), mayor.getSignature()), + 1, + lore + ); + }, (click, c) -> { + ElectionManager.castVote(c.player().getUuid(), candidateName); + c.player().sendMessage("§aYou voted for " + mayor.getColoredName() + "§a!"); + c.replace(new ElectionView()); }); } - - updateItemStacks(getInventory(), getPlayer()); } private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.CandidateData candidate, @@ -160,14 +151,4 @@ private String formatVotes(long votes) { if (votes >= 1_000) return String.format("%.1fk", votes / 1_000.0); return String.valueOf(votes); } - - @Override - public boolean allowHotkeying() { - return false; - } - - @Override - public void onBottomClick(InventoryPreClickEvent e) { - e.setCancelled(true); - } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElectionViewStats.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java similarity index 57% rename from type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElectionViewStats.java rename to type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java index b43870f55..14dd9e5dc 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIElectionViewStats.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java @@ -1,13 +1,14 @@ package net.swofty.type.skyblockgeneric.gui.inventories.election; -import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.inventory.InventoryType; -import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; -import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; -import net.swofty.type.generic.gui.inventory.item.GUIItem; -import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import net.swofty.type.skyblockgeneric.elections.ElectionData; import net.swofty.type.skyblockgeneric.elections.ElectionManager; @@ -17,35 +18,32 @@ import java.util.List; import java.util.Map; -public class GUIElectionViewStats extends HypixelInventoryGUI { +public class ElectionViewStatsView extends StatelessView { - public GUIElectionViewStats() { - super("Election Stats", InventoryType.CHEST_6_ROW); + @Override + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Election Stats", InventoryType.CHEST_6_ROW); } @Override - public void onOpen(InventoryGUIOpenEvent e) { + public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { + Components.fill(layout); + Components.backOrClose(layout, 49, ctx); + ElectionData data = ElectionManager.getElectionData(); if (!data.isElectionOpen() || data.getCandidates().isEmpty()) { - set(new GUIItem(22) { - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack( - "§cNo Active Election", - Material.BARRIER, - 1, - "§7There is no active election", - "§7at this time." - ); - } - }); - updateItemStacks(getInventory(), getPlayer()); + layout.slot(22, (s, c) -> ItemStackCreator.getStack( + "§cNo Active Election", + Material.BARRIER, + 1, + "§7There is no active election", + "§7at this time." + )); return; } int currentYear = SkyBlockCalendar.getYear(); - String playerVote = ElectionManager.getPlayerVote(getPlayer().getUuid()); Map tally = data.tallyVotes(); long totalVotes = tally.values().stream().mapToLong(Long::longValue).sum(); @@ -56,12 +54,12 @@ public ItemStack.Builder getItem(HypixelPlayer player) { SkyBlockMayor mayor = candidate.getMayorEnum(); if (mayor == null) continue; - boolean isVotedFor = candidate.getMayorName().equals(playerVote); long votes = tally.getOrDefault(candidate.getMayorName(), 0L); String voteStr = formatVotes(votes); String pctStr = totalVotes > 0 ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; int yearsSince = data.getYearsSinceLastElected(candidate.getMayorName(), currentYear); + String candidateName = candidate.getMayorName(); int col = i * 2; @@ -69,40 +67,38 @@ public ItemStack.Builder getItem(HypixelPlayer player) { int slot = row * 9 + col; int finalRow = row; - set(new GUIItem(slot) { - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - if (finalRow == 0) { - List lore = buildCandidateLore( - mayor, candidate, data.getElectionYear(), - yearsSince, voteStr, pctStr, isVotedFor - ); - return ItemStackCreator.getStack( - mayor.getColoredName(), - Material.GRAY_STAINED_GLASS_PANE, - 1, - lore.toArray(new String[0]) - ); - } - - int barHeight = totalVotes > 0 ? (int) Math.ceil((votes * 5.0) / totalVotes) : 0; - int barRow = 6 - finalRow; - if (barRow <= barHeight) { - return ItemStackCreator.getStack( - mayor.getColor() + voteStr + " votes", - Material.LIME_STAINED_GLASS_PANE, - 1, - mayor.getColor() + pctStr - ); - } - return ItemStackCreator.getStack(" ", - Material.BLACK_STAINED_GLASS_PANE, 1); + layout.slot(slot, (s, c) -> { + if (finalRow == 0) { + String playerVote = ElectionManager.getPlayerVote(c.player().getUuid()); + boolean isVotedFor = candidateName.equals(playerVote); + + List lore = buildCandidateLore( + mayor, candidate, data.getElectionYear(), + yearsSince, voteStr, pctStr, isVotedFor + ); + return ItemStackCreator.getStack( + mayor.getColoredName(), + Material.GRAY_STAINED_GLASS_PANE, + 1, + lore.toArray(new String[0]) + ); + } + + int barHeight = totalVotes > 0 ? (int) Math.ceil((votes * 5.0) / totalVotes) : 0; + int barRow = 6 - finalRow; + if (barRow <= barHeight) { + return ItemStackCreator.getStack( + mayor.getColor() + voteStr + " votes", + Material.LIME_STAINED_GLASS_PANE, + 1, + mayor.getColor() + pctStr + ); } + return ItemStackCreator.getStack(" ", + Material.BLACK_STAINED_GLASS_PANE, 1); }); } } - - updateItemStacks(getInventory(), getPlayer()); } private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.CandidateData candidate, @@ -155,14 +151,4 @@ private String formatVotes(long votes) { if (votes >= 1_000) return String.format("%.1fk", votes / 1_000.0); return String.valueOf(votes); } - - @Override - public boolean allowHotkeying() { - return false; - } - - @Override - public void onBottomClick(InventoryPreClickEvent e) { - e.setCancelled(true); - } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMayorMenu.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMayorMenu.java deleted file mode 100644 index 2a13de1d4..000000000 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMayorMenu.java +++ /dev/null @@ -1,91 +0,0 @@ -package net.swofty.type.skyblockgeneric.gui.inventories.election; - -import net.minestom.server.entity.PlayerSkin; -import net.minestom.server.event.inventory.InventoryPreClickEvent; -import net.minestom.server.inventory.InventoryType; -import net.minestom.server.item.ItemStack; -import net.minestom.server.item.Material; -import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; -import net.swofty.type.generic.gui.inventory.ItemStackCreator; -import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; -import net.swofty.type.generic.gui.inventory.item.GUIItem; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionData; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; - -import java.util.ArrayList; -import java.util.List; - -public class GUIMayorMenu extends HypixelInventoryGUI { - - public GUIMayorMenu() { - super("Mayor", InventoryType.CHEST_4_ROW); - } - - @Override - public void onOpen(InventoryGUIOpenEvent e) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) return; - - ElectionData data = ElectionManager.getElectionData(); - List activePerks = data.getCurrentMayorPerkEnums(); - - set(new GUIItem(11) { - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - List lore = new ArrayList<>(); - lore.add("§8Perks List"); - lore.add(""); - lore.add("§8§m--------------------------"); - - for (SkyBlockMayor.Perk perk : activePerks) { - lore.add(mayor.getColor() + perk.getDisplayName()); - lore.add(perk.getDescription()); - lore.add(""); - } - - lore.add("§8§m--------------------------"); - lore.add(""); - lore.add("§7The listed perks are available to"); - lore.add("§7all players until the closing of"); - lore.add("§7the next elections."); - - return ItemStackCreator.getStackHead( - mayor.getColor() + "Mayor " + mayor.getDisplayName(), - new PlayerSkin(mayor.getTexture(), mayor.getSignature()), - 1, - lore.toArray(new String[0]) - ); - } - }); - - set(new GUIItem(15) { - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack( - "§bElection & Voting", - Material.JUKEBOX, - 1, - "§7View the current election", - "§7candidates and cast your vote.", - "", - "§eClick to view!" - ); - } - }); - - set(GUIClickableItem.getCloseItem(31)); - updateItemStacks(getInventory(), getPlayer()); - } - - @Override - public boolean allowHotkeying() { - return false; - } - - @Override - public void onBottomClick(InventoryPreClickEvent e) { - e.setCancelled(true); - } -} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMinisterMenu.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMinisterMenu.java deleted file mode 100644 index 6f05c7d7d..000000000 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/GUIMinisterMenu.java +++ /dev/null @@ -1,74 +0,0 @@ -package net.swofty.type.skyblockgeneric.gui.inventories.election; - -import net.minestom.server.entity.PlayerSkin; -import net.minestom.server.event.inventory.InventoryPreClickEvent; -import net.minestom.server.inventory.InventoryType; -import net.minestom.server.item.ItemStack; -import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; -import net.swofty.type.generic.gui.inventory.ItemStackCreator; -import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; -import net.swofty.type.generic.gui.inventory.item.GUIItem; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionData; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; - -import java.util.ArrayList; -import java.util.List; - -public class GUIMinisterMenu extends HypixelInventoryGUI { - - public GUIMinisterMenu() { - super("Minister", InventoryType.CHEST_4_ROW); - } - - @Override - public void onOpen(InventoryGUIOpenEvent e) { - SkyBlockMayor minister = ElectionManager.getCurrentMinister(); - if (minister == null) return; - - ElectionData data = ElectionManager.getElectionData(); - SkyBlockMayor.Perk activePerk = data.getMinisterPerkEnum(); - - set(new GUIItem(11) { - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - List lore = new ArrayList<>(); - lore.add("§8Active Perk"); - lore.add(""); - lore.add("§8§m--------------------------"); - - if (activePerk != null) { - lore.add(minister.getColor() + activePerk.getDisplayName()); - lore.add(activePerk.getDescription()); - } - - lore.add("§8§m--------------------------"); - lore.add(""); - lore.add("§7The Minister is who came in 2nd Place"); - lore.add("§7during the election. They have one"); - lore.add("§7of their perks active."); - - return ItemStackCreator.getStackHead( - minister.getColor() + "Minister " + minister.getDisplayName(), - new PlayerSkin(minister.getTexture(), minister.getSignature()), - 1, - lore.toArray(new String[0]) - ); - } - }); - - set(GUIClickableItem.getCloseItem(31)); - updateItemStacks(getInventory(), getPlayer()); - } - - @Override - public boolean allowHotkeying() { - return false; - } - - @Override - public void onBottomClick(InventoryPreClickEvent e) { - e.setCancelled(true); - } -} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java new file mode 100644 index 000000000..72fa65a01 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java @@ -0,0 +1,74 @@ +package net.swofty.type.skyblockgeneric.gui.inventories.election; + +import net.minestom.server.entity.PlayerSkin; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.Material; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ViewContext; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; + +import java.util.ArrayList; +import java.util.List; + +public class MayorMenuView extends StatelessView { + + @Override + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Mayor", InventoryType.CHEST_4_ROW); + } + + @Override + public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { + Components.fill(layout); + Components.close(layout, 31); + + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return; + + ElectionData data = ElectionManager.getElectionData(); + List activePerks = data.getCurrentMayorPerkEnums(); + + layout.slot(11, (s, c) -> { + List lore = new ArrayList<>(); + lore.add("§8Perks List"); + lore.add(""); + lore.add("§8§m--------------------------"); + + for (SkyBlockMayor.Perk perk : activePerks) { + lore.add(mayor.getColor() + perk.getDisplayName()); + lore.add(perk.getDescription()); + lore.add(""); + } + + lore.add("§8§m--------------------------"); + lore.add(""); + lore.add("§7The listed perks are available to"); + lore.add("§7all players until the closing of"); + lore.add("§7the next elections."); + + return ItemStackCreator.getStackHead( + mayor.getColor() + "Mayor " + mayor.getDisplayName(), + new PlayerSkin(mayor.getTexture(), mayor.getSignature()), + 1, + lore + ); + }); + + layout.slot(15, (s, c) -> ItemStackCreator.getStack( + "§bElection & Voting", + Material.JUKEBOX, + 1, + "§7View the current election", + "§7candidates and cast your vote.", + "", + "§eClick to view!" + ), (click, c) -> c.push(new ElectionView())); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java new file mode 100644 index 000000000..be93d9d43 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java @@ -0,0 +1,62 @@ +package net.swofty.type.skyblockgeneric.gui.inventories.election; + +import net.minestom.server.entity.PlayerSkin; +import net.minestom.server.inventory.InventoryType; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ViewContext; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; + +import java.util.ArrayList; +import java.util.List; + +public class MinisterMenuView extends StatelessView { + + @Override + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Minister", InventoryType.CHEST_4_ROW); + } + + @Override + public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { + Components.fill(layout); + Components.close(layout, 31); + + SkyBlockMayor minister = ElectionManager.getCurrentMinister(); + if (minister == null) return; + + ElectionData data = ElectionManager.getElectionData(); + SkyBlockMayor.Perk activePerk = data.getMinisterPerkEnum(); + + layout.slot(11, (s, c) -> { + List lore = new ArrayList<>(); + lore.add("§8Active Perk"); + lore.add(""); + lore.add("§8§m--------------------------"); + + if (activePerk != null) { + lore.add(minister.getColor() + activePerk.getDisplayName()); + lore.add(activePerk.getDescription()); + } + + lore.add("§8§m--------------------------"); + lore.add(""); + lore.add("§7The Minister is who came in 2nd Place"); + lore.add("§7during the election. They have one"); + lore.add("§7of their perks active."); + + return ItemStackCreator.getStackHead( + minister.getColor() + "Minister " + minister.getDisplayName(), + new PlayerSkin(minister.getTexture(), minister.getSignature()), + 1, + lore + ); + }); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/calendar/GUICalendar.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/calendar/GUICalendar.java index cc507c748..264e8a05b 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/calendar/GUICalendar.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/calendar/GUICalendar.java @@ -3,15 +3,19 @@ import net.kyori.adventure.text.Component; import net.minestom.server.component.DataComponents; import net.minestom.server.inventory.InventoryType; -import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; -import net.swofty.type.generic.gui.inventory.ItemStackCreator; -import net.swofty.type.generic.gui.v2.*; +import net.swofty.type.generic.data.datapoints.DatapointToggles; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.skyblockgeneric.calendar.CalendarEvent; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; -import net.swofty.type.skyblockgeneric.gui.inventories.sbmenu.GUISkyBlockMenu; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -31,7 +35,13 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.close(layout, 40); Components.back(layout, 39, ctx); - Map events = SkyBlockCalendar.getEventsWithDurationUntil(14); + Map events; + + if (ctx.player().getToggles().get(DatapointToggles.Toggles.ToggleType.HAS_VISITED_DARK_AUCTION)) { + events = SkyBlockCalendar.getEventsWithDurationUntil(14); + } else { + events = SkyBlockCalendar.getEventsWithDurationUntilSkipSpecific(14, Collections.singletonList(CalendarEvent.DARK_AUCTION)); + } int index = 0; for (Map.Entry entry : events.entrySet()) { @@ -40,21 +50,22 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont CalendarEvent event = entry.getValue(); int slot = EVENT_SLOTS[index]; - layout.slot(slot, (s, c) -> { - List loreHeader = List.of( - Component.text("§7Starts in: §e" + StringUtility.formatTimeLeft(info.timeUntilBegin() * 50L)), - Component.text("§7Event lasts for §e" + StringUtility.formatTimeLeft(info.duration().toMillis()) + "§7!"), - Component.text(" ") - ); + layout.slot(slot, (_, _) -> { + List loreHeader = new ArrayList<>(List.of(Component.text("§7Starts in: §e" + StringUtility.formatTimeLeft(info.timeUntilBegin() * 50L)))); + if (!info.duration().isZero()) { + loreHeader.add(Component.text("§7Event lasts for §e" + StringUtility.formatTimeLeft(info.duration().toMillis()) + "§7!")); + } + loreHeader.add(Component.text(" ")); + List loreFooter = event.description().stream() - .map(line -> (Component) Component.text(line)) - .toList(); + .map(line -> (Component) Component.text(line)) + .toList(); List lore = Stream.concat(loreHeader.stream(), loreFooter.stream()).toList(); return event.representation().builder() - .set(DataComponents.CUSTOM_NAME, Component.text(event.getDisplayName(info.year()))) - .set(DataComponents.LORE, lore); + .set(DataComponents.CUSTOM_NAME, Component.text(event.getDisplayName(info.year()))) + .set(DataComponents.LORE, lore); }); index++; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/SkyBlockServerAttributes.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/SkyBlockServerAttributes.java index 6ebaff7ae..7e6e7aef9 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/SkyBlockServerAttributes.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/server/attribute/SkyBlockServerAttributes.java @@ -8,9 +8,7 @@ import net.swofty.type.generic.HypixelTypeLoader; import net.swofty.type.generic.data.mongodb.AttributeDatabase; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.server.attribute.attributes.AttributeLong; -import net.swofty.type.skyblockgeneric.server.attribute.attributes.AttributeString; import org.bson.Document; import org.tinylog.Logger; import tools.jackson.core.JacksonException; @@ -75,11 +73,7 @@ public static void saveAttributeLoop() { public enum Attributes { CALENDER_ELAPSED_TIME("elapsed", AttributeLong.class, new AttributeLong("elapsed", 0L), (attribute) -> { SkyBlockCalendar.setElapsed((Long) attribute.getValue()); - }, (server) -> new AttributeLong("elapsed", SkyBlockCalendar.getElapsed())), - ELECTION_DATA("election_data", AttributeString.class, new AttributeString("election_data", ""), (attribute) -> { - ElectionManager.loadFromAttribute(); - }, (server) -> new AttributeString("election_data", ElectionManager.serializeData())); - + }, (server) -> new AttributeLong("elapsed", SkyBlockCalendar.getElapsed())); @Getter private final String key; @Getter From 640e87735537723841d0fa5366f06b03c14e78b2 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:31:16 +0200 Subject: [PATCH 03/17] feat: teleporter warps --- .../commons/skyblock/item/ItemType.java | 10 ++- .../main/java/net/swofty/loader/Hypixel.java | 27 +++++--- .../swofty/type/galatea/npcs/NPCVaeri.java | 61 +++++++++++++++++++ .../entity/hologram/ServerHolograms.java | 45 ++++++++++++++ .../net/swofty/type/hub/TypeHubLoader.java | 36 ++++++++++- .../TypePrototypeLobbyLoader.java | 7 ++- .../calendar/SkyBlockCalendar.java | 27 ++++++++ .../commands/JumpToNextEvent.java | 2 +- .../actions/player/ActionPlayerTravel.java | 36 +++++++---- .../skyblockgeneric/utility/WarpPortal.java | 28 +++++++++ 10 files changed, 247 insertions(+), 32 deletions(-) create mode 100644 type.galatea/src/main/java/net/swofty/type/galatea/npcs/NPCVaeri.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/utility/WarpPortal.java diff --git a/commons/src/generated/java/net/swofty/commons/skyblock/item/ItemType.java b/commons/src/generated/java/net/swofty/commons/skyblock/item/ItemType.java index cb7ae1bf5..ec8113c04 100644 --- a/commons/src/generated/java/net/swofty/commons/skyblock/item/ItemType.java +++ b/commons/src/generated/java/net/swofty/commons/skyblock/item/ItemType.java @@ -1,8 +1,6 @@ // AUTO-GENERATED FILE. DO NOT EDIT. package net.swofty.commons.skyblock.item; -import java.lang.Exception; -import java.lang.String; import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; import org.jetbrains.annotations.Nullable; @@ -876,15 +874,15 @@ public enum ItemType { DIAMOND_BLOCK(Material.DIAMOND_BLOCK, Rarity.COMMON), - DIAMOND_BOOTS(Material.DIAMOND_BOOTS, Rarity.RARE), + DIAMOND_BOOTS(Material.DIAMOND_BOOTS, Rarity.COMMON), - DIAMOND_CHESTPLATE(Material.DIAMOND_CHESTPLATE, Rarity.RARE), + DIAMOND_CHESTPLATE(Material.DIAMOND_CHESTPLATE, Rarity.COMMON), - DIAMOND_HELMET(Material.DIAMOND_HELMET, Rarity.RARE), + DIAMOND_HELMET(Material.DIAMOND_HELMET, Rarity.COMMON), DIAMOND_HOE(Material.DIAMOND_HOE, Rarity.COMMON), - DIAMOND_LEGGINGS(Material.DIAMOND_LEGGINGS, Rarity.RARE), + DIAMOND_LEGGINGS(Material.DIAMOND_LEGGINGS, Rarity.COMMON), DIAMOND_MAGMAFISH(Material.PLAYER_HEAD, Rarity.COMMON), diff --git a/loader/src/main/java/net/swofty/loader/Hypixel.java b/loader/src/main/java/net/swofty/loader/Hypixel.java index efcd5fd8d..2d08545fd 100644 --- a/loader/src/main/java/net/swofty/loader/Hypixel.java +++ b/loader/src/main/java/net/swofty/loader/Hypixel.java @@ -44,6 +44,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -118,17 +119,23 @@ static void main(String[] args) { System.exit(0); return; } - HypixelTypeLoader typeLoader = subTypes.stream().filter(clazz -> { - try { - ServerType type = clazz.getDeclaredConstructor().newInstance().getType(); - Logger.info("Found TypeLoader: " + type.name()); - return type == serverType; - } catch (Exception e) { - return false; - } - }).findFirst().orElseThrow(() -> + + HypixelTypeLoader typeLoader = subTypes.stream() + .map(clazz -> { + try { + HypixelTypeLoader instance = clazz.getDeclaredConstructor().newInstance(); + Logger.info("Found TypeLoader: " + instance.getType().name()); + return instance; + } catch (Exception e) { + return null; + } + }) + .filter(Objects::nonNull) + .filter(instance -> instance.getType() == serverType) + .findFirst() + .orElseThrow(() -> new IllegalStateException("No TypeLoader found for server type " + serverType) - ).getDeclaredConstructor().newInstance(); + ); new HypixelGenericLoader(typeLoader).initialize(minecraftServer); diff --git a/type.galatea/src/main/java/net/swofty/type/galatea/npcs/NPCVaeri.java b/type.galatea/src/main/java/net/swofty/type/galatea/npcs/NPCVaeri.java new file mode 100644 index 000000000..06455fd21 --- /dev/null +++ b/type.galatea/src/main/java/net/swofty/type/galatea/npcs/NPCVaeri.java @@ -0,0 +1,61 @@ +package net.swofty.type.galatea.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; + +public class NPCVaeri extends HypixelNPC { + + + public NPCVaeri() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§bVaeri", "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + return "JZvY6u8/AZgq4M1sSm+wOK7qFtgxle2/0VKL24KblSmjW5mMXtGVDoHVuZCy8t3Te/Lbq80Bz10wnCJZWAflACcf+IWHbc8uIo6kmt5jcxY/dY1VjcQVA8lpufvdb0Y+g/iTNc0X7QAk7K15UtWa1T3F0TRBdIyxJVkaQ6SPS3FuErD43/sUL8wKqLMbLle4wZPI2NmMLQdRllyYeGvS4YKj04cOuc1ZZml7UbQUkut4QHA1VJN2dMFMRLuB48a4aT5yzCK1X8ZxuLNkXg7X74bWbBXi6jYe22/exV/78XAfUZ2eCzw0LdF+IswI2YBuN/XHNfGLaiCD9qoW7288UfqBgdQlGJ0kugReLjTLop+H9/uvApl8f3sNtrx2j1GTKAOhS2QdSyFSDnQ//m4drSr3FM5HggUjg6tF6a+BR8+UlKZD3mKgZWdEWXghW5tNhKJU5eKEHRcFrNKzDkD7QuTsv5v1a2lxhELmBKwjS5efodHobtgYUs5Sqamr+PWLD6NPJ/aAPz5EOFB4v/3WQpi10WkxmiuGatQygCLa+Jz30XiGMBN1fwW6tSuY14AqpYnizqYr0lbAOCENzNJWctjcSEDDM7suSj3DAMT04aqWWb3GENqB//2ot9CwHBfaXsF48A6lmDgeKPyf/n5quw0beFpRcN1revpYMZrOoEg="; + } + + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTcyMTkyMDcwMTgzOCwKICAicHJvZmlsZUlkIiA6ICJjMTJkMmY5ZWJhZGI0ZTllYTIxZmM2M2M3YWY3M2E5NSIsCiAgInByb2ZpbGVOYW1lIiA6ICJEcmVhbXlOZW9uIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzhhZjYxMGQ1YzRhYTgyOTQzY2ZiYjQ3YjQzN2FkYjg0ZTBmNGUzNzgxZGJmZWQ3MGE3ZjE4ZTYwZDc3OGM1NmYiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ=="; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(-688.5, 116, -35.5, -101, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockPlayer player = (SkyBlockPlayer) event.getPlayer(); + if (isInDialogue(player)) return; + setDialogue(player, "idle"); + } + + @Override + protected DialogueSet[] dialogues(HypixelPlayer player) { + return new DialogueSet[]{ + DialogueSet.builder().key("idle").lines(new String[]{ + "How do you do! Are you from §2Galatea§f?", + "Wonderful pl-", + "Did you just say \"Gala-tee\"?", + "No, no! It's §oGala-té-à§f!", + "A lot of folks get it wrong but now you know better!" + }).build() + }; + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/entity/hologram/ServerHolograms.java b/type.generic/src/main/java/net/swofty/type/generic/entity/hologram/ServerHolograms.java index 8f3957674..9447f8e14 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/entity/hologram/ServerHolograms.java +++ b/type.generic/src/main/java/net/swofty/type/generic/entity/hologram/ServerHolograms.java @@ -11,6 +11,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; @Getter public enum ServerHolograms { @@ -68,9 +69,53 @@ public static void addExternalHologram(ExternalHologram hologram) { externalHolograms.put(hologram, entities); } + public static void updateExternalHologramText(UUID uuid, String[] newText) { + List entities = externalHolograms.entrySet() + .stream() + .filter(entry -> entry.getKey().getUuid().equals(uuid)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(null); + + if (entities == null) return; + + ExternalHologram hologram = externalHolograms.keySet() + .stream() + .filter(k -> k.getUuid().equals(uuid)) + .findFirst() + .orElse(null); + + if (hologram == null) return; + + if (entities.size() < newText.length) { + double startY = newText.length * 0.3 - 0.3; + for (int i = entities.size(); i < newText.length; i++) { + HologramEntity entity = new HologramEntity(newText[i]); + entity.setInstance(hologram.instance, hologram.pos.add(0, startY - (i * 0.3), 0)); + entity.setAutoViewable(true); + entities.add(entity); + } + for (int i = 0; i < hologram.text.length; i++) { + entities.get(i).teleport(hologram.pos.add(0, startY - (i * 0.3), 0)); + } + } + else if (entities.size() > newText.length) { + for (int i = newText.length; i < entities.size(); i++) { + entities.get(i).remove(); + } + entities.subList(newText.length, entities.size()).clear(); + } + + for (int i = 0; i < newText.length; i++) { + entities.get(i).setText(newText[i]); + } + } + @Builder @Getter public static class ExternalHologram { + @Builder.Default + private UUID uuid = UUID.randomUUID(); private final Instance instance; private final Pos pos; private final String[] text; diff --git a/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java b/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java index 00bd48257..94d8370b0 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java +++ b/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java @@ -5,6 +5,7 @@ import net.kyori.adventure.text.event.ClickEvent; import net.minestom.server.MinecraftServer; import net.minestom.server.color.Color; +import net.minestom.server.coordinate.BlockVec; import net.minestom.server.coordinate.Pos; import net.minestom.server.network.packet.server.play.ParticlePacket; import net.minestom.server.particle.Particle; @@ -16,12 +17,14 @@ import net.swofty.commons.CustomWorlds; import net.swofty.commons.ServerType; import net.swofty.commons.ServiceType; +import net.swofty.commons.StringUtility; import net.swofty.commons.skyblock.item.ItemType; import net.swofty.proxyapi.ProxyService; import net.swofty.proxyapi.redis.ProxyToClient; import net.swofty.proxyapi.redis.ServiceToClient; import net.swofty.type.generic.HypixelConst; import net.swofty.type.generic.SkyBlockTypeLoader; +import net.swofty.type.generic.entity.hologram.ServerHolograms; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.event.HypixelEventClass; import net.swofty.type.generic.tab.TablistManager; @@ -30,6 +33,8 @@ import net.swofty.type.hub.tab.HubServerModule; import net.swofty.type.hub.util.HubMap; import net.swofty.type.skyblockgeneric.SkyBlockGenericLoader; +import net.swofty.type.skyblockgeneric.calendar.CalendarEvent; +import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import net.swofty.type.skyblockgeneric.darkauction.DarkAuctionHandler; import net.swofty.type.skyblockgeneric.entity.GlassDisplay; import net.swofty.type.skyblockgeneric.furniture.Furniture; @@ -37,11 +42,13 @@ import net.swofty.type.skyblockgeneric.museum.MuseumDisplays; import net.swofty.type.skyblockgeneric.tabmodules.AccountInformationModule; import net.swofty.type.skyblockgeneric.tabmodules.SkyBlockPlayersOnlineModule; +import net.swofty.type.skyblockgeneric.utility.WarpPortal; import org.jetbrains.annotations.Nullable; import org.tinylog.Logger; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @@ -134,13 +141,40 @@ public void afterInitialize(MinecraftServer server) { // Place forest trees //ForestTreePlacement.placeTrees(HypixelConst.getInstanceContainer()); TODO: fix this on new map - HubMap hubMap = new HubMap(); + final HubMap hubMap = new HubMap(); hubMap.placeItemFrames(HypixelConst.getInstanceContainer()); + final UUID electionUUID = UUID.nameUUIDFromBytes("election".getBytes()); + + ServerHolograms.addExternalHologram( + ServerHolograms.ExternalHologram.builder() + .uuid(electionUUID) + .instance(HypixelConst.getInstanceContainer()) + .pos(new Pos(9.5, 81, 13.5)) + .text(electionLines()) + .build() + ); + + MinecraftServer.getSchedulerManager().buildTask(() -> + ServerHolograms.updateExternalHologramText(electionUUID, electionLines()) + ).delay(TaskSchedule.seconds(1)).repeat(TaskSchedule.seconds(1)).schedule(); + + WarpPortal.create(HypixelConst.getInstanceContainer(), new BlockVec(13, 78, 13), Component.text("Election Room"), new Pos(0.5, 50, 45.5, -180, 0)); + WarpPortal.create(HypixelConst.getInstanceContainer(), new BlockVec(0, 49, 47), Component.text("Community Center"), new Pos(9.5, 79, 12.5, 90, 0)); + Furniture.load("hexatorum"); Furniture.load("rune_table"); } + private static String[] electionLines() { + return new String[]{ + "§e§lMAYOR ELECTIONS", + "§bYear " + SkyBlockCalendar.getYear(), + "§eTime left: §a" + StringUtility.formatTimeLeft( + SkyBlockCalendar.timeUntilEvent(CalendarEvent.ELECTION_CLOSE)) + }; + } + @Override public LoaderValues getLoaderValues() { return new LoaderValues( diff --git a/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/TypePrototypeLobbyLoader.java b/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/TypePrototypeLobbyLoader.java index 7733fbb3e..d725d5f49 100644 --- a/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/TypePrototypeLobbyLoader.java +++ b/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/TypePrototypeLobbyLoader.java @@ -1,6 +1,5 @@ package net.swofty.type.prototypelobby; -import io.sentry.Sentry; import net.minestom.server.MinecraftServer; import net.minestom.server.coordinate.Pos; import net.swofty.commons.CustomWorlds; @@ -18,7 +17,11 @@ import net.swofty.type.generic.tab.TablistManager; import net.swofty.type.generic.tab.TablistModule; import net.swofty.type.lobby.LobbyTypeLoader; -import net.swofty.type.lobby.events.*; +import net.swofty.type.lobby.events.LobbyBlockBreak; +import net.swofty.type.lobby.events.LobbyItemEvents; +import net.swofty.type.lobby.events.LobbyParkourEvents; +import net.swofty.type.lobby.events.LobbyPlayerJoinEvents; +import net.swofty.type.lobby.events.LobbyPlayerMove; import net.swofty.type.lobby.item.LobbyItem; import net.swofty.type.lobby.item.LobbyItemHandler; import net.swofty.type.lobby.item.impl.HidePlayers; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java index ecbeae5f0..3d97cd5da 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java @@ -144,6 +144,33 @@ public static Map getEventsWithDurationUntil(int amoun return result; } + // TODO: clean this up + public static long timeUntilEvent(CalendarEvent event) { + long currentElapsed = getElapsed(); + int currentYear = getYear(); + + int yearsAhead = 0; + + do { + int targetYear = currentYear + yearsAhead; + long yearStartElapsed = (long) (targetYear - 1) * YEAR; + + for (Long eventTime : event.times()) { + long eventElapsed = yearStartElapsed + eventTime; + + // Skip events that have already passed (including currently ongoing ones that started) + if (eventElapsed <= currentElapsed) { + continue; + } + + return eventElapsed - currentElapsed; + } + yearsAhead++; + } while (yearsAhead <= 100); + + return -1; // Return -1 if no upcoming event is found within a reasonable timeframe + } + public static Map getEventsWithDurationUntilSkipSpecific(int amount, List event) { Map result = new LinkedHashMap<>(); long currentElapsed = getElapsed(); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/commands/JumpToNextEvent.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/commands/JumpToNextEvent.java index 8e6d6c0c0..35e5b4e8f 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/commands/JumpToNextEvent.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/commands/JumpToNextEvent.java @@ -9,7 +9,7 @@ import net.swofty.type.skyblockgeneric.calendar.CalendarEvent; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; -@CommandParameters(aliases = "jumptonextevent", +@CommandParameters(aliases = "jumptonextevent skiptoevent", description = "Jumps to the next SkyBlock calendar event", usage = "/jumptonextevent ", permission = Rank.STAFF, diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/ActionPlayerTravel.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/ActionPlayerTravel.java index 035db4ad3..13a4e4a24 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/ActionPlayerTravel.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/ActionPlayerTravel.java @@ -1,6 +1,8 @@ package net.swofty.type.skyblockgeneric.event.actions.player; import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.minestom.server.MinecraftServer; import net.minestom.server.event.player.PlayerMoveEvent; import net.minestom.server.instance.block.Block; @@ -13,6 +15,7 @@ import net.swofty.type.skyblockgeneric.mission.MissionSet; import net.swofty.type.skyblockgeneric.mission.missions.MissionUseTeleporter; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import net.swofty.type.skyblockgeneric.utility.WarpPortal; import java.time.Duration; import java.util.ArrayList; @@ -27,19 +30,18 @@ public void run(PlayerMoveEvent event) { final SkyBlockPlayer player = (SkyBlockPlayer) event.getPlayer(); if (delay.contains(player.getUuid())) return; + delay.add(player.getUuid()); + + MinecraftServer.getSchedulerManager().buildTask(() -> delay.remove(player.getUuid())) + .delay(Duration.ofMillis(500)) + .schedule(); Key block = player.getInstance().getBlock(player.getPosition()).key(); if (block == Block.NETHER_PORTAL.key()) { MissionData data = player.getMissionData(); - delay.add(player.getUuid()); - - MinecraftServer.getSchedulerManager().buildTask(() -> delay.remove(player.getUuid())) - .delay(Duration.ofMillis(500)) - .schedule(); - if (!MissionSet.GETTING_STARTED.hasCompleted(player) - && !data.isCurrentlyActive(MissionUseTeleporter.class) + && !data.isCurrentlyActive(MissionUseTeleporter.class) ) { player.sendMessage("§cYou must complete your starting missions!"); return; @@ -50,11 +52,21 @@ public void run(PlayerMoveEvent event) { if (block == Block.END_PORTAL.key()) { player.sendTo(ServerType.SKYBLOCK_ISLAND); - delay.add(player.getUuid()); - - MinecraftServer.getSchedulerManager().buildTask(() -> delay.remove(player.getUuid())) - .delay(Duration.ofMillis(500)) - .schedule(); } + + WarpPortal.getWarpPortals().forEach(warp -> { + // distanceSquared is a micro-optimization + if (event.getNewPosition().distanceSquared(warp.vector().asPos()) < 2) { + player.teleport(warp.pos()); + player.playSound( + Sound.sound( + Key.key("minecraft:entity.enderman.teleport"), + Sound.Source.PLAYER, + 1f, 1f + ) + ); + player.sendMessage("§dWarped to §b" + LegacyComponentSerializer.legacySection().serialize(warp.text()) + "§d!"); + } + }); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/utility/WarpPortal.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/utility/WarpPortal.java new file mode 100644 index 000000000..dc2756c38 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/utility/WarpPortal.java @@ -0,0 +1,28 @@ +package net.swofty.type.skyblockgeneric.utility; + +import lombok.Getter; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minestom.server.coordinate.BlockVec; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.instance.Instance; +import net.swofty.type.generic.entity.hologram.ServerHolograms; + +import java.util.ArrayList; + +public class WarpPortal { + + @Getter + private static ArrayList warpPortals = new ArrayList<>(); + + public static void create(Instance instance, BlockVec vector, Component text, Pos pos) { + ServerHolograms.addExternalHologram(ServerHolograms.ExternalHologram.builder().pos(vector.asPos().add(0.5, 2, 0.5)).instance(instance).text(new String[]{ + "§5✦ §dWarp To §b" + LegacyComponentSerializer.legacySection().serialize(text) + }).build()); + warpPortals.add(new WarpPortalData(vector, text, pos)); + } + + public record WarpPortalData(BlockVec vector, Component text, Pos pos) { + } + +} From 3e816eb7ebbfad72448605ae0d8a8c59e57a27c9 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:52:40 +0200 Subject: [PATCH 04/17] feat: improve fall damage --- .../data/ActionPlayerClearSkyBlockCache.java | 8 +--- .../actions/player/fall/ActionPlayerFall.java | 22 +++++----- .../skyblockgeneric/user/SkyBlockPlayer.java | 40 +++++++++++++++++-- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/data/ActionPlayerClearSkyBlockCache.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/data/ActionPlayerClearSkyBlockCache.java index 1f9309441..b576de21f 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/data/ActionPlayerClearSkyBlockCache.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/data/ActionPlayerClearSkyBlockCache.java @@ -7,7 +7,6 @@ import net.swofty.type.generic.event.HypixelEventClass; import net.swofty.type.generic.packet.packets.client.anticheat.PacketListenerAirJump; import net.swofty.type.skyblockgeneric.event.actions.player.ActionPlayerStrayTooFar; -import net.swofty.type.skyblockgeneric.event.actions.player.fall.ActionPlayerFall; import net.swofty.type.skyblockgeneric.item.updater.PlayerItemOrigin; import net.swofty.type.skyblockgeneric.server.eventcaller.CustomEventCaller; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; @@ -20,15 +19,12 @@ public class ActionPlayerClearSkyBlockCache implements HypixelEventClass { public void run(PlayerDisconnectEvent event) { final SkyBlockPlayer player = (SkyBlockPlayer) event.getPlayer(); - /* - Remove from caches - */ + // remove from caches SkyBlockScoreboard.removeCache(player); - ActionPlayerFall.fallHeight.remove(player); player.getPetData().updatePetEntityImpl(null); PlayerItemOrigin.clearCache(player.getUuid()); PacketListenerAirJump.playerData.remove(player); ActionPlayerStrayTooFar.startedStray.remove(player.getUuid()); - CustomEventCaller.clearCache((SkyBlockPlayer) player); + CustomEventCaller.clearCache(player); } } \ No newline at end of file diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/fall/ActionPlayerFall.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/fall/ActionPlayerFall.java index 127bf2255..7fe31b18d 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/fall/ActionPlayerFall.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/event/actions/player/fall/ActionPlayerFall.java @@ -9,10 +9,8 @@ import net.swofty.type.generic.event.HypixelEventClass; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; -import java.util.HashMap; - public class ActionPlayerFall implements HypixelEventClass { - public static HashMap fallHeight = new HashMap<>(); + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = true) public void run(PlayerMoveEvent event) { @@ -21,23 +19,27 @@ public void run(PlayerMoveEvent event) { Pos currentPosition = player.getPosition(); if (player.isFlying() || player.getGameMode().equals(GameMode.CREATIVE) || player.isInLaunchpad()) { - fallHeight.put(player, currentPosition.blockY()); + player.setFallHeight(currentPosition.blockY()); return; } - fallHeight.computeIfAbsent(player, k -> currentPosition.blockY()); - int currentHeight = fallHeight.get(player); + Integer currentHeight = player.getFallHeight(); + if (currentHeight == null) { + currentHeight = currentPosition.blockY(); + } if (newPosition.y() > currentPosition.y() && currentHeight < newPosition.blockY()) { - fallHeight.put(player, newPosition.blockY()); - } else if (newPosition.y() == currentPosition.y()) { - int fallDistance = currentHeight - newPosition.blockY(); + player.setFallHeight(newPosition.blockY()); + return; + } + if (player.isOnGround()) { + int fallDistance = currentHeight - newPosition.blockY(); if (fallDistance > 4) { player.damage(DamageType.FALL, (float) ((fallDistance * 2) - 4)); } - fallHeight.put(player, currentPosition.blockY()); + player.setFallHeight(newPosition.blockY()); } } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockPlayer.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockPlayer.java index 17aca8a03..82ce85395 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockPlayer.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockPlayer.java @@ -6,7 +6,10 @@ import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; import net.kyori.adventure.text.Component; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.PlayerHand; +import net.minestom.server.entity.RelativeFlags; import net.minestom.server.event.inventory.InventoryCloseEvent; import net.minestom.server.instance.block.Block; import net.minestom.server.inventory.Inventory; @@ -16,16 +19,22 @@ import net.minestom.server.network.packet.server.play.UpdateHealthPacket; import net.minestom.server.network.player.GameProfile; import net.minestom.server.network.player.PlayerConnection; +import net.minestom.server.tag.Tag; +import net.swofty.commons.StringUtility; import net.swofty.commons.skyblock.PlayerShopData; import net.swofty.commons.skyblock.SkyBlockPlayerProfiles; -import net.swofty.commons.StringUtility; import net.swofty.commons.skyblock.item.ItemType; import net.swofty.commons.skyblock.item.Rarity; import net.swofty.commons.skyblock.item.UnderstandableSkyBlockItem; import net.swofty.commons.skyblock.statistics.ItemStatistic; import net.swofty.type.generic.HypixelConst; import net.swofty.type.generic.data.HypixelDataHandler; -import net.swofty.type.generic.data.datapoints.*; +import net.swofty.type.generic.data.datapoints.DatapointBoolean; +import net.swofty.type.generic.data.datapoints.DatapointDouble; +import net.swofty.type.generic.data.datapoints.DatapointInteger; +import net.swofty.type.generic.data.datapoints.DatapointLong; +import net.swofty.type.generic.data.datapoints.DatapointRank; +import net.swofty.type.generic.data.datapoints.DatapointString; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.SkyBlockGenericLoader; @@ -58,10 +67,16 @@ import net.swofty.type.skyblockgeneric.skill.skills.RunecraftingSkill; import net.swofty.type.skyblockgeneric.user.statistics.PlayerStatistics; import net.swofty.type.skyblockgeneric.utility.DeathMessageCreator; +import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.regex.Matcher; @@ -89,6 +104,7 @@ public class SkyBlockPlayer extends HypixelPlayer { public boolean speedManaged = false; @Setter private SkyBlockIsland skyBlockIsland; + private static final Tag fallHeight = Tag.Integer("fallHeight"); private static final Pattern SACK_PATTERN = Pattern.compile("^(?:(SMALL|MEDIUM|LARGE|ENCHANTED)_)?(.+?)_SACK$"); @@ -98,7 +114,7 @@ public SkyBlockPlayer(@NotNull GameProfile gameProfile, @NotNull PlayerConnectio } public SkyBlockDataHandler getSkyblockDataHandler() { - return (SkyBlockDataHandler) SkyBlockDataHandler.getUser(this.getUuid()); + return SkyBlockDataHandler.getUser(this.getUuid()); } public DatapointMuseum.MuseumData getMuseumData() { @@ -127,6 +143,22 @@ public MissionData getMissionData() { return data; } + @Override + public @NotNull CompletableFuture teleport(@NotNull Pos position, @NotNull Vec velocity, long @Nullable [] chunks, + @MagicConstant(flagsFromClass = RelativeFlags.class) int flags, + boolean shouldConfirm) { + setFallHeight(position.blockY()); + return super.teleport(position, velocity, chunks, flags, shouldConfirm); + } + + public void setFallHeight(int fallHeight) { + setTag(SkyBlockPlayer.fallHeight, fallHeight); + } + + public Integer getFallHeight() { + return getTag(SkyBlockPlayer.fallHeight); + } + @Override public String getFullDisplayName() { DatapointSkyBlockExperience.PlayerSkyBlockExperience experience = getSkyBlockExperience(); From 112dbba1382491dba0dc3d57722510ab2efc2cf2 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Thu, 26 Feb 2026 20:51:40 +0200 Subject: [PATCH 05/17] feat: candidates and voting properly --- .../net/swofty/commons/StringUtility.java | 56 +++++++++++++- .../service/election/ElectionService.java | 2 +- .../orchestrator/OrchestratorCache.java | 11 ++- .../type/generic/entity/npc/HypixelNPC.java | 10 +-- .../net/swofty/type/hub/TypeHubLoader.java | 15 ++++ .../type/hub/npcs/election/NPCCandidate1.java | 76 +++++++++++++++++++ .../type/hub/npcs/election/NPCCandidate2.java | 76 +++++++++++++++++++ .../type/hub/npcs/election/NPCCandidate3.java | 76 +++++++++++++++++++ .../type/hub/npcs/election/NPCCandidate4.java | 76 +++++++++++++++++++ .../type/hub/npcs/election/NPCCandidate5.java | 76 +++++++++++++++++++ .../election/NPCClerkSeraphineDuplicate.java | 59 ++++++++++++++ .../npcs/{ => election}/NPCCurrentMayor.java | 2 +- .../election/NPCCurrentMayorDuplicate.java | 58 ++++++++++++++ .../{ => election}/NPCCurrentMinister.java | 2 +- .../events/ActionPlayerDataSpawn.java | 14 +++- .../elections/ElectionData.java | 61 ++++++++++++++- .../elections/ElectionManager.java | 29 ++++--- .../elections/SkyBlockMayor.java | 60 +++++++++------ .../inventories/election/ElectionView.java | 47 +++++++----- .../election/ElectionViewStatsView.java | 52 +++++++------ .../inventories/election/MayorMenuView.java | 48 +++++++++--- .../election/MinisterMenuView.java | 42 +++++++++- 22 files changed, 834 insertions(+), 114 deletions(-) create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate1.java create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate2.java create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate3.java create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate4.java create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate5.java create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCClerkSeraphineDuplicate.java rename type.hub/src/main/java/net/swofty/type/hub/npcs/{ => election}/NPCCurrentMayor.java (97%) create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayorDuplicate.java rename type.hub/src/main/java/net/swofty/type/hub/npcs/{ => election}/NPCCurrentMinister.java (98%) diff --git a/commons/src/main/java/net/swofty/commons/StringUtility.java b/commons/src/main/java/net/swofty/commons/StringUtility.java index 00b5036cc..e130bca41 100644 --- a/commons/src/main/java/net/swofty/commons/StringUtility.java +++ b/commons/src/main/java/net/swofty/commons/StringUtility.java @@ -5,7 +5,6 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.minestom.server.instance.block.Block; import net.minestom.server.item.Material; -import net.swofty.commons.skyblock.statistics.ItemStatistic; import java.math.RoundingMode; import java.text.DecimalFormat; @@ -166,6 +165,18 @@ public static String getAsRomanNumeral(int num) { return roman.toString(); } + /** + * Capitalizes the first letter of the input string and lowercases the rest. + * @param input The string to capitalize. + * @return The input string with the first letter capitalized and the rest lowercased. If the input is null or empty, it returns the input as is. + */ + public static String capitalize(String input) { + if (input == null || input.isEmpty()) { + return input; + } + return input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase(); + } + public static String getTextFromComponent(Component component) { if (component == null) throw new IllegalArgumentException("Component cannot be null"); @@ -263,6 +274,49 @@ public static List splitByWordAndLength(String string, int splitLength) return result; } + public static List splitByWordAndLengthKeepLegacyColor(String string, int splitLength) { + List result = new ArrayList<>(); + String lastColorCode = ""; + + for (String line : string.split("\n", -1)) { + if (line.isEmpty()) { + result.add(""); + continue; + } + + StringBuilder currentLine = new StringBuilder(lastColorCode); + + for (String word : line.split(" ")) { + if (word.isEmpty()) continue; + + int extraSpace = currentLine.length() == lastColorCode.length() ? 0 : 1; + + if (currentLine.length() + extraSpace + word.length() > splitLength) { + if (currentLine.length() > lastColorCode.length()) { + result.add(currentLine.toString()); + currentLine = new StringBuilder(lastColorCode); + } + } else if (extraSpace == 1) { + currentLine.append(' '); + } + + currentLine.append(word); + + // this wont work with bold/italic and those but if you need those don't use this method + int colorIndex = word.lastIndexOf('§'); + if (colorIndex != -1 && colorIndex < word.length() - 1) { + lastColorCode = "§" + word.charAt(colorIndex + 1); + } + } + + if (currentLine.length() > lastColorCode.length()) { + result.add(currentLine.toString()); + } + } + + return result; + } + public static List splitByNewLine(String string) { return new ArrayList<>(Arrays.asList(string.split("\n", -1))); } diff --git a/service.elections/src/main/java/net/swofty/service/election/ElectionService.java b/service.elections/src/main/java/net/swofty/service/election/ElectionService.java index 79396fe4b..e49a391fb 100644 --- a/service.elections/src/main/java/net/swofty/service/election/ElectionService.java +++ b/service.elections/src/main/java/net/swofty/service/election/ElectionService.java @@ -9,7 +9,7 @@ public class ElectionService implements SkyBlockService { - static void main(String[] args) { + static void main() { String mongoUri = ConfigProvider.settings().getMongodb(); new ElectionDatabase(null).connect(mongoUri); SkyBlockService.init(new ElectionService()); diff --git a/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java b/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java index 007c8828e..b4e0ae11f 100644 --- a/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java +++ b/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java @@ -5,7 +5,14 @@ import net.swofty.commons.game.Game; import java.time.Instant; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; @@ -121,7 +128,7 @@ public static GameServerState instantiateServer(ServerType serverType, int maxPl // Prefer servers with more available capacity candidates.sort(Comparator.comparingInt(GameServerState::availableSlots).reversed()); - int topAvail = candidates.get(0).availableSlots(); + int topAvail = candidates.getFirst().availableSlots(); List topServers = new ArrayList<>(); for (GameServerState server : candidates) { diff --git a/type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java b/type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java index 76cf57a5f..b5e7e0d47 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java +++ b/type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java @@ -39,13 +39,8 @@ public abstract class HypixelNPC { @Getter private final NPCConfiguration parameters; private final DialogueController dialogueController; - @Getter - private final String name; - public HypixelNPC(NPCConfiguration configuration) { this.parameters = configuration; - String className = getClass().getSimpleName().replace("NPC", "").replace("Villager", ""); - this.name = parameters.chatName() != null ? parameters.chatName() : className.replaceAll("(?<=.)(?=\\p{Lu})", " "); this.dialogueController = new DialogueController(this); } @@ -197,6 +192,11 @@ public void sendNPCMessage(HypixelPlayer player, String message) { sendNPCMessage(player, message, Sound.sound().type(Key.key("entity.villager.celebrate")).volume(1.0f).pitch(0.8f + new Random().nextFloat() * 0.4f).build()); } + public String getName() { + String className = getClass().getSimpleName().replace("NPC", "").replace("Villager", ""); + return parameters.chatName() != null ? parameters.chatName() : className.replaceAll("(?<=.)(?=\\p{Lu})", " "); + } + public void sendNPCMessage(HypixelPlayer player, String message, Sound sound) { player.sendMessage("§e[NPC] " + getName() + "§f: " + message); player.playSound(sound); diff --git a/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java b/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java index 94d8370b0..5147e9ecc 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java +++ b/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java @@ -24,6 +24,7 @@ import net.swofty.proxyapi.redis.ServiceToClient; import net.swofty.type.generic.HypixelConst; import net.swofty.type.generic.SkyBlockTypeLoader; +import net.swofty.type.generic.entity.InteractionEntity; import net.swofty.type.generic.entity.hologram.ServerHolograms; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.event.HypixelEventClass; @@ -36,12 +37,16 @@ import net.swofty.type.skyblockgeneric.calendar.CalendarEvent; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import net.swofty.type.skyblockgeneric.darkauction.DarkAuctionHandler; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.entity.GlassDisplay; import net.swofty.type.skyblockgeneric.furniture.Furniture; +import net.swofty.type.skyblockgeneric.gui.inventories.election.ElectionView; +import net.swofty.type.skyblockgeneric.gui.inventories.election.ElectionViewStatsView; import net.swofty.type.skyblockgeneric.item.SkyBlockItem; import net.swofty.type.skyblockgeneric.museum.MuseumDisplays; import net.swofty.type.skyblockgeneric.tabmodules.AccountInformationModule; import net.swofty.type.skyblockgeneric.tabmodules.SkyBlockPlayersOnlineModule; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import net.swofty.type.skyblockgeneric.utility.WarpPortal; import org.jetbrains.annotations.Nullable; import org.tinylog.Logger; @@ -164,6 +169,16 @@ public void afterInitialize(MinecraftServer server) { Furniture.load("hexatorum"); Furniture.load("rune_table"); + + new InteractionEntity(1.1f, 1.1f, (player, _) -> { + final SkyBlockPlayer skyBlockPlayer = (SkyBlockPlayer) player; + String text = ElectionManager.getPlayerVote(skyBlockPlayer.getUuid()); + if (text == null) { + player.openView(new ElectionView()); + } else { + player.openView(new ElectionViewStatsView()); + } + }).setInstance(HypixelConst.getInstanceContainer(), new Pos(0.5, 50, 34.5)); } private static String[] electionLines() { diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate1.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate1.java new file mode 100644 index 000000000..9b8532d0f --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate1.java @@ -0,0 +1,76 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public class NPCCandidate1 extends HypixelNPC { + private static final int INDEX = 0; + + private static SkyBlockMayor getCandidate() { + ElectionData data = ElectionManager.getElectionData(); + if (!data.isElectionOpen()) return null; + List candidates = data.getCandidates(); + if (candidates.size() <= INDEX) return null; + return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); + } + + public NPCCandidate1() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; + return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getSignature() : ""; + } + + @Override + public boolean visible(HypixelPlayer player) { + return getCandidate() != null; + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getTexture() : ""; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(-11.5, 50.0625, 34.5, -90, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public @NonNull String chatName() { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return; + sendNPCMessage(event.player(), "Running for mayor!"); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate2.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate2.java new file mode 100644 index 000000000..5b9afaa80 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate2.java @@ -0,0 +1,76 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public class NPCCandidate2 extends HypixelNPC { + private static final int INDEX = 1; + + private static SkyBlockMayor getCandidate() { + ElectionData data = ElectionManager.getElectionData(); + if (!data.isElectionOpen()) return null; + List candidates = data.getCandidates(); + if (candidates.size() <= INDEX) return null; + return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); + } + + public NPCCandidate2() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; + return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getSignature() : ""; + } + + @Override + public boolean visible(HypixelPlayer player) { + return getCandidate() != null; + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getTexture() : ""; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(-8.5, 50.0625, 25.5, -45, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public @NonNull String chatName() { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return; + sendNPCMessage(event.player(), "Running for mayor!"); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate3.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate3.java new file mode 100644 index 000000000..f4e8681d6 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate3.java @@ -0,0 +1,76 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public class NPCCandidate3 extends HypixelNPC { + private static final int INDEX = 2; + + private static SkyBlockMayor getCandidate() { + ElectionData data = ElectionManager.getElectionData(); + if (!data.isElectionOpen()) return null; + List candidates = data.getCandidates(); + if (candidates.size() <= INDEX) return null; + return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); + } + + public NPCCandidate3() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; + return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getSignature() : ""; + } + + @Override + public boolean visible(HypixelPlayer player) { + return getCandidate() != null; + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getTexture() : ""; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(0.5, 50.0625, 22.5, 0, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public @NonNull String chatName() { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return; + sendNPCMessage(event.player(), "Running for mayor!"); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate4.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate4.java new file mode 100644 index 000000000..8af7554fb --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate4.java @@ -0,0 +1,76 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public class NPCCandidate4 extends HypixelNPC { + private static final int INDEX = 3; + + private static SkyBlockMayor getCandidate() { + ElectionData data = ElectionManager.getElectionData(); + if (!data.isElectionOpen()) return null; + List candidates = data.getCandidates(); + if (candidates.size() <= INDEX) return null; + return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); + } + + public NPCCandidate4() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; + return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getSignature() : ""; + } + + @Override + public boolean visible(HypixelPlayer player) { + return getCandidate() != null; + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getTexture() : ""; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(9.5, 50.0625, 25.5, 45, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public @NonNull String chatName() { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return; + sendNPCMessage(event.player(), "Running for mayor!"); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate5.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate5.java new file mode 100644 index 000000000..a6d0ce717 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate5.java @@ -0,0 +1,76 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public class NPCCandidate5 extends HypixelNPC { + private static final int INDEX = 4; + + private static SkyBlockMayor getCandidate() { + ElectionData data = ElectionManager.getElectionData(); + if (!data.isElectionOpen()) return null; + List candidates = data.getCandidates(); + if (candidates.size() <= INDEX) return null; + return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); + } + + public NPCCandidate5() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; + return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getSignature() : ""; + } + + @Override + public boolean visible(HypixelPlayer player) { + return getCandidate() != null; + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getTexture() : ""; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(12.5, 50.0625, 34.5, 90, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public @NonNull String chatName() { + SkyBlockMayor mayor = getCandidate(); + return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor mayor = getCandidate(); + if (mayor == null) return; + sendNPCMessage(event.player(), "Running for mayor!"); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCClerkSeraphineDuplicate.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCClerkSeraphineDuplicate.java new file mode 100644 index 000000000..169cecdf5 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCClerkSeraphineDuplicate.java @@ -0,0 +1,59 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; + +import java.util.stream.Stream; + +public class NPCClerkSeraphineDuplicate extends HypixelNPC { + + public NPCClerkSeraphineDuplicate() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"Clerk Seraphine", "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + return "nlSTknzGOCRA9nT4N8dQce9+2sRkCmpPBN/sKJqIYZxjbF+Uuejbuo32zSFqj1rdB720EA7jVplcZxMP6i9XscUAF83GWwCHX2N75AT1NRW3PeBg0gtrM/qQxKgaH4zOEquGZZ9l8NyV5k2rxDVZRG8YusxsP45WSUV4bnJyLpWeVXO/ZY5luX841BpseLQVTEHjkhYVbL32tauHM6DoB05VKh+5r8utv/OsV8oXQf37+5DMD530ftkriMt+QIlEcVogCk6BR9fvP7tA5Bxvuc6uDbVSkMZaXq62mHVbdRBmnh/nm2hWjrfwNrCPbGi3on5YY5qpnjY9t65Tjw4JsRqmpQXjrscIcfSir8sylisjZfi+kyrjoi4eGVGFVwS2HO1wpX303h3l/z2q9yCEwCHEjnnMx5CI3H8egTTQSLZC8pz60ZaFnyf+ZDwl9gs79wfYGDaqwi7rq7LFYeSrZctABb4oVs/DRuKs+4l8e0LOu90nHnMh7aseAT9YfSip+uTvGaybcpnG8kLcv4sm7J8n3EnhTtcU1ajS/dxZs9i/+p1bQ+wq+k1vwgAOXFLh02ISqUHVVYF9OlyZRiS+/84bPA6WS9SWz+ur6C49fCH44lCPaxxu1UJeHZXI2b1Luh8t7jtKj/gvtzj2GWHADLpcdw2M0IwrRH7ibew8OgE="; + } + + @Override + public String texture(HypixelPlayer player) { + return "eyJ0aW1lc3RhbXAiOjE1NTk2NzYyNzYyNzYsInByb2ZpbGVJZCI6ImEyZjgzNDU5NWM4OTRhMjdhZGQzMDQ5NzE2Y2E5MTBjIiwicHJvZmlsZU5hbWUiOiJiUHVuY2giLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2NkNjU0NTMxODE2ZWM3MjAwYTZhNDYxZDdhMDNjMmRhZGYzMWY0NDlhNTkxYzg1ZjNiMzFjYjJhODNkZDczNjYifX19"; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(4.5, 49, 34.5, 15, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent e) { + if (isInDialogue(e.player())) return; + setDialogue(e.player(), "hello"); + } + + @Override + public DialogueSet[] dialogues(HypixelPlayer player) { + return Stream.of( + DialogueSet.builder() + .key("hello").lines(new String[]{ + "Welcome to the §bCommunity Center§f!", + "Contribute to community projects, upgrade your account, and more by talking to §dElizabeth§f!", + "You can also vote in the §bmayor elections §fby heading through the warp behind me!" + }).build() + ).toArray(DialogueSet[]::new); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayor.java similarity index 97% rename from type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java rename to type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayor.java index cda09d9d9..3debc5f06 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMayor.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayor.java @@ -1,4 +1,4 @@ -package net.swofty.type.hub.npcs; +package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; import net.swofty.type.generic.entity.npc.HypixelNPC; diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayorDuplicate.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayorDuplicate.java new file mode 100644 index 000000000..dc43ef856 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayorDuplicate.java @@ -0,0 +1,58 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import net.swofty.type.skyblockgeneric.gui.inventories.election.MayorMenuView; + +public class NPCCurrentMayorDuplicate extends HypixelNPC { + + public NPCCurrentMayorDuplicate() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return new String[]{"Mayor ???", "§e§lCLICK"}; + return new String[]{"Mayor " + mayor.getDisplayName(), "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return ""; + return mayor.getSignature(); + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return ""; + return mayor.getTexture(); + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(-3.5, 49, 34.5, 0, 0); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) { + event.player().sendMessage("§cHello!!"); + return; + } + event.player().openView(new MayorMenuView()); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMinister.java similarity index 98% rename from type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java rename to type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMinister.java index 19f44afd0..47d5a486f 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCCurrentMinister.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMinister.java @@ -1,4 +1,4 @@ -package net.swofty.type.hub.npcs; +package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; import net.swofty.type.generic.entity.npc.HypixelNPC; diff --git a/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/events/ActionPlayerDataSpawn.java b/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/events/ActionPlayerDataSpawn.java index 42f5e986e..e2f64118f 100644 --- a/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/events/ActionPlayerDataSpawn.java +++ b/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/events/ActionPlayerDataSpawn.java @@ -1,5 +1,8 @@ package net.swofty.type.prototypelobby.events; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.event.player.PlayerSpawnEvent; import net.swofty.type.generic.HypixelGenericLoader; import net.swofty.type.generic.event.EventNodes; @@ -8,10 +11,6 @@ import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.generic.user.categories.Rank; -/** - * Sends rank-based join messages when players spawn in the prototype lobby. - * Note: Data loading is handled by the generic ActionPlayerDataSpawn via GameDataHandler. - */ public class ActionPlayerDataSpawn implements HypixelEventClass { @HypixelEvent(node = EventNodes.PLAYER_DATA, requireDataLoaded = false, isAsync = true) @@ -27,5 +26,12 @@ public void run(PlayerSpawnEvent event) { for (HypixelPlayer onlinePlayer : HypixelGenericLoader.getLoadedPlayers()) { onlinePlayer.sendMessage(player.getFullDisplayName() + " §6joined the lobby!"); } + + player.sendMessage(Component.empty()); + player.sendMessage(Component.text("§f➔ §6§lWelcome to the Prototype Lobby")); + player.sendMessage(Component.text("All games in this lobby are currently in development.", NamedTextColor.GREEN)); + player.sendMessage(Component.text("§eClick here to leave feedback! §f➤ §b§nhttps://hypixel.net/PTL") + .clickEvent(ClickEvent.openUrl("https://hypixel.net/PTL"))); + player.sendMessage(Component.empty()); } } \ No newline at end of file diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java index 03252cb0e..926f2acb2 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java @@ -2,6 +2,7 @@ import lombok.Getter; import lombok.Setter; +import net.swofty.commons.StringUtility; import java.util.ArrayList; import java.util.Arrays; @@ -18,10 +19,12 @@ public class ElectionData { private int electionYear; private String currentMayor; + private String currentMayorColor; private List currentMayorPerks = new ArrayList<>(); private int mayorElectedYear; private String currentMinister; + private String currentMinisterColor; private String ministerPerk; private List candidates = new ArrayList<>(); @@ -32,13 +35,14 @@ public class ElectionData { private Map> candidateActivePerks = new HashMap<>(); private Map failedPerkGainLastTime = new HashMap<>(); private int specialCandidateIndex; + private ElectionResult lastElectionResult; public ElectionData() {} public SkyBlockMayor getMayorEnum() { if (currentMayor == null) return null; try { - return SkyBlockMayor.valueOf(currentMayor); + return SkyBlockMayor.valueOf(currentMayor).setColor(currentMayorColor); } catch (IllegalArgumentException e) { return null; } @@ -47,7 +51,7 @@ public SkyBlockMayor getMayorEnum() { public SkyBlockMayor getMinisterEnum() { if (currentMinister == null) return null; try { - return SkyBlockMayor.valueOf(currentMinister); + return SkyBlockMayor.valueOf(currentMinister).setColor(currentMinisterColor); } catch (IllegalArgumentException e) { return null; } @@ -116,6 +120,7 @@ public void resolveElection(int currentYear) { .findFirst().orElse(null); currentMayor = winnerName; + currentMayorColor = winner.getColor(); currentMayorPerks = winnerCandidate != null ? new ArrayList<>(winnerCandidate.getActivePerks()) : Arrays.stream(winner.getAllPerks()).map(Enum::name).toList(); @@ -125,11 +130,13 @@ public void resolveElection(int currentYear) { if (winner.isSpecial()) { currentMinister = null; ministerPerk = null; + currentMinisterColor = null; } else { String secondPlace = sorted.stream().filter(entry -> !entry.getKey().equals(winnerName)).findFirst().map(Map.Entry::getKey).orElse(null); if (secondPlace != null) { SkyBlockMayor ministerMayor = SkyBlockMayor.valueOf(secondPlace); currentMinister = secondPlace; + currentMinisterColor = ministerMayor.getColor(); CandidateData ministerCandidate = candidates.stream() .filter(c -> c.getMayorName().equals(secondPlace)) @@ -185,6 +192,18 @@ public void resolveElection(int currentYear) { candidateActivePerks.put(winnerName, List.of(randomPerk.name())); } + long totalVoteCount = tally.values().stream().mapToLong(Long::longValue).sum(); + ElectionResult electionResult = new ElectionResult(); + electionResult.setYear(currentYear); + for (Map.Entry entry : sorted) { + CandidateResult cr = new CandidateResult(); + cr.setMayorName(entry.getKey()); + cr.setVotes(entry.getValue()); + cr.setPercentage(totalVoteCount > 0 ? (entry.getValue() * 100.0) / totalVoteCount : 0); + electionResult.getCandidateResults().add(cr); + } + this.lastElectionResult = electionResult; + candidates.clear(); votes.clear(); electionOpen = false; @@ -211,6 +230,7 @@ public void startNewElection(int year) { for (SkyBlockMayor mayor : selected) { CandidateData candidate = new CandidateData(); candidate.setMayorName(mayor.name()); + candidate.setIndex(selected.indexOf(mayor)); List perks = candidateActivePerks.get(mayor.name()); if (perks == null || perks.isEmpty()) { @@ -229,6 +249,7 @@ public void startNewElection(int year) { CandidateData candidate = new CandidateData(); candidate.setMayorName(specialCandidate.name()); + candidate.setIndex(selected.indexOf(specialCandidate)); candidate.setActivePerks(Arrays.stream(specialCandidate.getAllPerks()).map(Enum::name).toList()); candidates.add(candidate); } @@ -244,6 +265,7 @@ public void startNewElection(int year) { if (!alreadyInElection) { CandidateData diazCandidate = new CandidateData(); diazCandidate.setMayorName(SkyBlockMayor.DIAZ.name()); + diazCandidate.setIndex(selected.indexOf(SkyBlockMayor.DIAZ)); diazCandidate.setActivePerks(Arrays.stream(SkyBlockMayor.DIAZ.getAllPerks()).map(Enum::name).toList()); candidates.add(diazCandidate); } @@ -259,6 +281,7 @@ public int getYearsSinceLastElected(String mayorName, int currentYear) { @Getter @Setter public static class CandidateData { + private int index; private String mayorName; private List activePerks = new ArrayList<>(); @@ -282,8 +305,42 @@ public List getActivePerkEnums() { return result; } + public String getColor() { + return switch (index) { + case 0 -> "§c"; + case 1 -> "§a"; + case 2 -> "§b"; + case 3 -> "§e"; + case 4 -> "§d"; + default -> "§f"; + }; + } + + public String getColoredName() { + return getColor() + StringUtility.capitalize(getMayorName()); + } + public boolean hasMinisterPerkMarker(SkyBlockMayor.Perk perk) { return activePerks.contains(perk.name()); } } + + @Getter + @Setter + public static class ElectionResult { + private int year; + private List candidateResults = new ArrayList<>(); + + public ElectionResult() {} + } + + @Getter + @Setter + public static class CandidateResult { + private String mayorName; + private long votes; + private double percentage; + + public CandidateResult() {} + } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java index 9e7ead5f3..12b64b63c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java @@ -28,10 +28,10 @@ public static void loadFromService() { SERVICE = new ProxyService(ServiceType.ELECTION); try { GetElectionDataProtocolObject.GetElectionDataResponse response = - SERVICE.handleRequest( - new GetElectionDataProtocolObject.GetElectionDataMessage() - ).join(); + SERVICE.handleRequest( + new GetElectionDataProtocolObject.GetElectionDataMessage() + ).join(); if (response.found() && response.serializedData() != null) { electionData = GSON.fromJson(response.serializedData(), ElectionData.class); @@ -58,8 +58,8 @@ public static void saveToService() { try { String serialized = GSON.toJson(electionData); SERVICE.handleRequest( - new SaveElectionDataProtocolObject.SaveElectionDataMessage(serialized) + SaveElectionDataProtocolObject.SaveElectionDataResponse>handleRequest( + new SaveElectionDataProtocolObject.SaveElectionDataMessage(serialized) ); } catch (Exception e) { Logger.error(e, "Failed to save election data to service"); @@ -69,13 +69,12 @@ public static void saveToService() { private static void initializeFirstElection() { int currentYear = SkyBlockCalendar.getYear(); electionData.setCurrentMayor(SkyBlockMayor.COLE.name()); - electionData.setCurrentMayorPerks( - Arrays.stream(SkyBlockMayor.COLE.getAllPerks()) - .map(Enum::name).toList() - ); + electionData.setCurrentMayorColor("§d"); + electionData.setCurrentMayorPerks(Arrays.stream(SkyBlockMayor.COLE.getAllPerks()).map(Enum::name).toList()); electionData.setMayorElectedYear(currentYear); electionData.setCurrentMinister(SkyBlockMayor.DIAZ.name()); electionData.setMinisterPerk(SkyBlockMayor.Perk.STOCK_EXCHANGE.name()); + electionData.setCurrentMinisterColor("§c"); } public static void onElectionStart() { @@ -100,14 +99,14 @@ public static CompletableFuture castVote(UUID accountId, String candidateN if (!electionData.isElectionOpen()) return CompletableFuture.completedFuture(null); boolean validCandidate = electionData.getCandidates().stream() - .anyMatch(c -> c.getMayorName().equals(candidateName)); + .anyMatch(c -> c.getMayorName().equals(candidateName)); if (!validCandidate) return CompletableFuture.completedFuture(null); electionData.castVote(accountId, candidateName); return SERVICE.handleRequest( - new CastVoteProtocolObject.CastVoteMessage(accountId, candidateName) + CastVoteProtocolObject.CastVoteResponse>handleRequest( + new CastVoteProtocolObject.CastVoteMessage(accountId, candidateName) ).thenAccept(response -> { if (response.success() && response.serializedData() != null) { electionData = GSON.fromJson(response.serializedData(), ElectionData.class); @@ -142,8 +141,8 @@ public static boolean isPerkActive(SkyBlockMayor.Perk perk) { public static CompletableFuture> fetchCandidates() { return SERVICE.handleRequest( - new GetCandidatesProtocolObject.GetCandidatesMessage() + GetCandidatesProtocolObject.GetCandidatesResponse>handleRequest( + new GetCandidatesProtocolObject.GetCandidatesMessage() ).thenApply(GetCandidatesProtocolObject.GetCandidatesResponse::candidates); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java index b85b17e2e..56134a49f 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java @@ -8,104 +8,97 @@ @Getter public enum SkyBlockMayor { AATROX( - "Aatrox", "§a", false, + "Aatrox", false, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTIyNjczMywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzFiZGY1MDViYjhjMGYxZjMzNjVhMDMwMzJkZTE5MzE2NjNmZjcxYzU3ZTAyMjU1OGRlMzEyYjhmMWI1YzQ0NSIKICAgIH0KICB9Cn0=", "fuSuJuBDgFDBV9878jr/Sgvg5w+DJ1YaXBmgAPurDoScZtarz1pwQ0Tsw+kBPzNYBhD2hOaGHna32ttqlKKufdXFJG09uPlv8nSCHNA7rwl74L0KO7wOn4Bxsa6cS0UsGj3AJYzJ0tnTcF3ILpHUF+C2aYgRvTjm0UXWo1Ai0+bjN67ecb3MlcsuCBDpTQQl8ujvW3xp2krxyJeeKeERMAGTW0QgsuJCrkN3iXrIiv4VWn1TBslutuu8vsltkYcRZcsUljWNtCHYQ/eBt6B8qdoEhierPCepdpdJzwYmcWMaxLWHO336g2Sp541hJDVtS5yCN48rY6UREJfcISJS0HjmVo0862h0JMKNT6ceIAbF/CzLkL+uAnaOCUNdPedrRjevWrKAXAGfd9JXK073ge3X/qDr0HahNFManGA030qHSTz3C7rqTrCVPOLg7QSipFZH0HKGrEyhCPnpZ10zC4UHeFL9zwCEi5L7O+qIrPraJmdJ2lU7QA33mLstL6AEabLZ2LluRRpki+9GIJ/gfjlB50fIHYOJPTykZymPIp1R6fAXyNn32m15WP38c5c4akYTfTq+1+zBupfxYOD2BZTd3x2Ce2klEMnn4Wo4CwkENI/37/kaure7CB0TpM9VCMJaNQZbIc10ehr93qJGCROSxpvT/+KqN6nRhfs7hVk=", new Perk[]{Perk.SLASHED_PRICING, Perk.SLAYER_XP_BUFF, Perk.PATHFINDER} ), COLE( - "Cole", "§e", false, + "Cole", false, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MDkwNjkxMiwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTY0MjJkZTA4ODQ4OTUyZDFjYmVhZDY2YmJiYWQ2ZjA3MTkxYmRjYzk1MmYzZDEwMzZhZWIwYzIyOTM4ZjM5YiIKICAgIH0KICB9Cn0=", "FWvg7q7AORwUPOYVUNH4xjgwxOhzLm2rnBJH4mHkVA/BTYnaLD/hkJkUeMxYFgjArbrw8EvjUmhix7UgptWx0mHWmqssceBuXFHlq1JkzpPubfXpGRpvT+2AUqGSgHGHW9Gxeo0jtGr+mOvIABP+FPHs72dmYWZYW5TJCfw+8e8KhayferdStTKaDanpFi2RGxe3uZjMh3ZoKSxGugCxiAR/7cwIAAW1px4Z9ZmxhzFtQIp+Deyh871IVEjhOyYjs8QZtZCPGr6QAuH4wd1srXU1FJqU2lDGa/DYj4tBFl0bfO2oczJUuy5UJQWFZFbS7uBVAP5P5en2pvg04eqghlksCEQ/npzZolGSjSmobxlOf/8CXy9vYBNp12W1DlzC8RkQnNhC/3Mm8JWciSechunP4NfAig9QG5UJiy2WjeiwWnLyk4OpDaYA09hVjuxJ12xuScggkYwbPDdsyU1SftLynjoB6ktHamiFtg1DvuIqdfl8T4Qd8iGBTk00b49NoI9+LB9Yu6fNiGbYgMKzsr5LAStaAtvFApQolsreGjCUX6K62qr+0HmKX10esO+yi3cFvj20Yy/BS8xfLrakx4Z3f3wzk/0ONSHtoHLO/PbZTlLxtRypjenTnqV95dMRmBhjdS0RG9vUmvtEISN4CiFMTsMJU6QJg77Lmp5Tz7A=", new Perk[]{Perk.PROSPECTION, Perk.MINING_XP_BUFF, Perk.MINING_FIESTA, Perk.MOLTEN_FORGE} ), DIANA( - "Diana", "§d", false, + "Diana", false, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzk0MjU3NDIzMCwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODNjYzFjZjY3MmE0YjI1NDBiZTM0NmVhZDc5YWMyZDllZDE5ZDk1YjYwNzViZjk1YmUwYjZkMGRhNjEzNzdiZSIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9", "FepPcmM5MycgGDcxdEFXgQ0ncPuOWemDQRpJguSUc2Xfyz0Dub5OKDAiBOPkWDt7gR/UUOfenDW8XGg0gRFSvw4VR6maV1twwL3S+sn6rgIYfBZ4A5khrVpKNTvXQFDyMPB4780dsvIrM34CAcLzadxdoldT1Z8iibunDXVmLKiJwj9RctTRwdc3nbk/7a1P2pkpUs9JRUwbLwidZJRFbhSMr87jyNiUJzYKAaQ1vXpsWvkRD860PuLrbi8Nf1GInHuxRaIkeMRP6tQKDY7XubW2wIYrDn5MzZf9htnOBKWRx50s3e2qy3PiBgI7iJNbEo9X1qNHBQe6FkHS6zsZLX63kJDSyzq4+xgKZmSvVnPYFKeJLor/gKf+xX9RkVKzZqlU97jNHV+9vXUWfrVoUfCNpNwmK2YR+HT86Q5g0vQyD3gwq1W/QvvFkmgU7sOHRINVNxH6R6QOx3cKKDVaEqPjRKkEMsJOBLsJjNXDRMKg21oh+mhxzSRyjDy6LBBIPLM6m25GUtBhAuMs65gwWeyUAOml1hNLN9knzPVPigv0iAx8BJxvSIhXWkudA0UDDjnNGFGpxinykftWr1FAKo40M+SSnOG58mpOwGJEPxsWQm4k8IY73c1fiAdugh/LbkD2WBS0nc3qHQhZAW8xM7sZaBLhq7Et+9hrQx8qse8=", new Perk[]{Perk.HUNTRESS_INTUITION, Perk.SHARING_IS_CARING, Perk.LUCKY_PAWS, Perk.PET_XP_BUFF} ), - // TODO: proper skin for Diaz DIAZ( - "Diaz", "§d", false, - "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", - "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + "Diaz", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTU4MDMzNSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWNmNDczN2NkNDQ0YjU5MDU0NTczNGE2NDA4Y2JlMjNjMTgyZjQyODNmMTY3YTNlM2MwOTUzMmNjYmVmMTdmOSIKICAgIH0KICB9Cn0=", + "jdxgkeD/COv++whPWHAYgZjjiO71XLsU7Yqh/iTsZD1WygRxiGyo+xRYU6I3F7Hyn/3PhMyjwwzvhqELpjPvdENgyA/KWygDqLNjzb/yAhqJuitJVddnpdiSgevhda/Rpww6R6WhKfka403wSzKmZIwcGBufkRVJvsOOJa8yTqL3Dk2eHRc8EMDCsuIUIC3NhItcva1rxU4G6PeaZ84gYAYTyw7eAhLJY6ev84f4yUcyqdVM5PBu99xkBq7ui27FHBHEqvdH5pf/JJ/pKIbY7EqWJ67093TMKA6QtkX3gyaz+Vz4cH5opFu+52PE/oeLaRzH0i330SrXif0TJZgFoVKLQuqqvDinXwBTJmH+Ozf0wzADzwNoUuOUMfZ1R0c+aWieg2qrlGHzNXBhkhair/bIWE/4NraIURlNcGf8XfgZ1klIZyIcFT1N9T0utKSZXMAqeWL7Wo29khJ9OO5joJod6iRanJIRGQs7B85ZTxsTQ/17MU73U6fUgldAS+5zvMvM1u217SQCzaIdufC2G9QrNMkmKqHNWblj2AUD+pxs++FIokY4BhEQ0ZqSAUp7jncpy1Te6GmPEFr1uUfieVsUCzMIE6/QFiygRng708JGIhaXjJTrOyfaWwb7BXQ5rUkhXYtT4zciFeCrgO+b8JUjo6X3g/QvgOX1Ky9nwnc=", new Perk[]{Perk.STOCK_EXCHANGE, Perk.LONG_TERM_INVESTMENT, Perk.SHOPPING_SPREE, Perk.VOLUME_TRADING} ), FINNEGAN( - "Finnegan", "§e", false, + "Finnegan", false, "ewogICJ0aW1lc3RhbXAiIDogMTY1NDIwMzAxNDc3MiwKICAicHJvZmlsZUlkIiA6ICI0NGNlMmMwZTFjNTM0ZDhmYmExNmNkNDhlYjkyYTUxZSIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4WGlyYW56dThYeCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9lNzc0N2ZiZWU5ZmIzOWJlMzliMDBkM2Q0ODNlYjJmODhiNGJhZTgyNDE3YWI1Y2IxYjFhYTkzMGRkN2I2Njg5IiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=", "W1VnWYThZuihE6z8wX4XqfYwXIMxSHeXpWabQYntXkBeL+G4tA7Vu5p/IbBIco2w2uVeJZ1HC5HnHFQMgcBSXImHyomGjn4T2NQD9zg4sAAXevh8T9oeAC92qzCCa5wyyzm0hhxFhJ2RHr+JOii0cfaPn+7P6gLxZgVfaRLPJA4d5J+SwaUdTcHBVZm6A0Tzn54T4Acj4tUcWFZNrsqOck9VdJy9gLPvE3xDKDOVk4MTvXUJFRxOEjwWiIKmdP8ccDqy/C3F/zB0fulCXc0e8LWN9RKUQc0NSiz+TFetzZbNhi6PApA7DaicNKbZcj9DCDiGFvZUi2YMiadI25h7yhkF98uUc06Bg1soe8UTKok4LAFpt93CHr9ISFGXF34SnMSphbIWvsp34KgmdDOxAbSCogHDFfbozzljS2t07DHD0TiWfA+6WbzL6WB94774A/c8iPOFcPnmdBHodeYjp5bn8GBn+Bzu4dbOJxFmEj4940ZrYgYG1USwaw69hApXxmDJbzeD6oojiceT2CARGrFAxwpI9TvMU2ZtLATnS01vXxlX8NVcR+ovR1awuPOB/NiCY0kCxs/2pi65Glm09NqAK8AurFJXK/ueHYnV+FzuutSybvc78Mn2+iwgzOoxD0GM9fqw9eC70tI+10daitNyIi9QK0R6yfi3WpzxEzs=", new Perk[]{Perk.PEST_ERADICATOR, Perk.GOATED, Perk.PELT_POCALYPSE, Perk.BLOOMING_BUSINESS} ), FOXY( - "Foxy", "§b", false, + "Foxy", false, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", new Perk[]{Perk.SWEET_BENEVOLENCE, Perk.A_TIME_FOR_GIVING, Perk.CHIVALROUS_CARNIVAL, Perk.EXTRA_EVENT} ), - // TODO: proper skin for Marina MARINA( - "Marina", "§b", false, - "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", - "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", + "Marina", false, + "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTQxNjY5MiwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODA3ZmM5YmVlOGQzMzQ0ZTg0MGU0MDMxYTM3MjQ5YTRjM2M4N2ZjODBjZjE2NDMyY2M1YzIxNTNkMWY5YzUzZCIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9", + "V6CFGoMGqrt0ZdwQnJSHAt8a93/loxkwtYjcp/oDDnX17YSCS9chIp6OzTvyOPyupgB81TXwS17iH2DdTQGQrquJToeyqDXPWCtnK6em8nfkDedsjovgD06BV1FbeWQ+JSNLCFL4M4GIiG2S2mpQZXXu1SboHnA+ZISYUR2qk9s75uDoden8TOB16OJBd6/pyxQ9tNQr0uQIIB5QKE83PiHaqAisFL/R/lWrOO2myRPDP41NTwjwJJthvC2q4/PUE+RBgbyr6JGBO2suchq7pRBfFKq99XCqyb40q4g+QLDaIRnQCLyi4IiYsLtws3WrIzqZ6PsPsFDbiUQClRXii2FTRSo804Oj4A4guPG//zNQ5EaJ8j9LoxZzrZt/wgYUJHI2LyM7f+o8lR3y3O4SmS9R3bQWiVRUQP6A8EKKsKpops1gCSgpZMshX+PKA2JCNt96zW1x1Vue7hvBRSbWxdPLBzrXQQ8pJi4gI2C13iP7D3W1quiKKHWZNAaZNKlx6zF7LVHTsXohPW6iP7nl5+tCzc7dp+5sPrV6UCJEVVjQ6FX1vAhFZMcNxjMi8zLLI83NDG7SEEaY3KHaX6R7VFE+lrsJq+PNdbwoaAQBxWQHBiMhFqqKj08/IjC35tFDqRKLG1kNhllWp0uGfx3NxIABJHUb9S+iSGIf4r+3EpI=", new Perk[]{Perk.FISHING_XP_BUFF, Perk.LUCK_OF_THE_SEA, Perk.FISHING_FESTIVAL, Perk.DOUBLE_TROUBLE} ), PAUL( - "Paul", "§c", false, + "Paul", false, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MDk0OTYzOCwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWI1OWM0M2Q4ZGJjY2ZkN2VjNmU2Mzk0YjYzMDRiNzBkNGVkMzE1YWRkMDQ5NGVlNzdjNzMzZjQxODE4YzczYSIKICAgIH0KICB9Cn0=", "UeEf0Ir81BLTBE0PfVeEtU/6mHUw3xSP7XGcQYN18qlYS6J7qd+bQskaSJQbEHXr+axq2+5aPm/AfGrjNnl9zQn1EucBIwhdRBHnjuJeRY6x9VKEHAtX2gnpnNelU/oP6MKPZ1dUad4iAHQg8BmJR/oQpedvOJDuqdUZowe8WTVFC5qctJQWRIZCX0BWYK1O1xxJx4FZ9LzF++7qWZsVqO+qmOR8R7Xr4jFkF8cdNIRyezgcfhmw3BCqiDDheOzuJzo0l7y9kHR82reHus/JBLGyTy/iqMqlZFgNePEoaOGRgIvROw9oIS4R/19+UABIe0MDD6CSGgsE7VfgWeyCVw3qxmCSAZDHnYuYyH0zpnGQRsmQrx9aTjFXHf6g551MEpx7KGGTMaOm9b7ygOGuVGB/52UXR2W9UU+YtBZoUzDPMeVcM1NQno/fY3rLoSf5PfuaaEpZMlczYpH0DBvApEQ6FBm/XTOPeS5w3a+7UXh/wrjXu5b62rXG4SNZaBZRT76eseX3wZoCGiLYEh+IXfAJxXSKOqmlHmRmv6FGRzMcZpHzr63GqD0jJwpLuUZ54uuMgUtjx/liEZG1pesdUuf0ObRVf+xDxk/iLAiNKRvd6BoP7wVm0CkebDlyPObdKW0Ss+tAhB0y1o4das+n+UjpHUuPM2D/eLZFA01umyw=", new Perk[]{Perk.MARAUDER, Perk.BENEDICTION, Perk.EZPZ} ), // TODO: proper skin for Barry BARRY( - "Barry", "§d", false, + "Barry", false, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", new Perk[]{Perk.SEAL_OF_APPROVAL, Perk.HOT_STUFF, Perk.ARCANE_CATALYST, Perk.GOVERNMENT_REFORM} ), // TODO: proper skin for Scorpius SCORPIUS( - "Scorpius", "§5", true, + "Scorpius", true, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", new Perk[]{Perk.BRIBE, Perk.DARKER_AUCTIONS} ), // TODO: proper skin for Derpy DERPY( - "Derpy", "§6", true, + "Derpy", true, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", new Perk[]{Perk.TURBO_MINIONS, Perk.AH_CLOSED, Perk.DOUBLE_MOBS_HP, Perk.MOAR_SKILLZ} ), // TODO: proper skin for Jerry JERRY( - "Jerry", "§d", true, + "Jerry", true, "ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTM1NTM0MywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzQ4NWE3MTdmYTBmNTFkN2ZhZGM2NmE1ZDVlOTg1MzkwNWJlZjkxNGUzYjI4NDhhMmYxMjhlNjNkMmRiODciLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", "hsdCpEijJf50Jx84oVf2b9sTv9JswZQ6rM+/sszeTpIDhuR9NH/3icxLz16i3PJ2Yvze7f6pd4KNfV2pqJhadO11rNhU3W0XGBAtd2bWJ1Ib16U0Qe1EHFY6g8r5VfRk1ZHBZxlRUQK15bd1MfuTMNr4+kl2BiCt7Ee/8dX+AWsNHXz0mbL4GRnrrBy9Y7bkBAWqOa3fjYnqCGzbmSi2yajxWqmUaba1qVuOA8ko/a1KkC/4yEoxd775gHZXyorZTD3VZEh6wbk9Y5eTeSo0U2fJCxmE18uZaxEm7uyMIpdV8QLH5VoHCvS+7liQ01BI6sITL8HwBINIW80oeSsOFLkB1E7yM185KPbMP3r0ahUuRfmSwiD37cqryMRvRWKlIdg9FojeKQENKXn9cbxSvZSjqerL01+Fp3Kw14iYU7/tIPX7VyAx/Qg0OYam3dTj4CLiEfwJc/NnE0p0mhaGQAiVDP3WJH7yjoHXlwZ1XIirJjWzUyzIz25gPGTR5Q/1WZjho8YQZmqqpNyzkX5yknHcS2iJIKj5wALsblqToy13Rsv1zAJiB6oyN5IfznOjBiHdcgpBApEGuCNQAAwNsUrQgJt2QvXniWCRBK9/SiUNa/9Sl5DoqrA72HgbM7Ty6j7lxBrx0BuLFUMw0Qtir5zzeM3Ndtc+IqeprJpkAdM=", new Perk[]{Perk.PERKPOCALYPSE, Perk.STATSPOCALYPSE, Perk.JERRYPOCALYPSE} ); private final String displayName; - private final String color; private final boolean special; private final String texture; private final String signature; private final Perk[] allPerks; + private String color; - SkyBlockMayor(String displayName, String color, boolean special, String texture, String signature, Perk[] allPerks) { + SkyBlockMayor(String displayName, boolean special, String texture, String signature, Perk[] allPerks) { this.displayName = displayName; - this.color = color; this.special = special; this.texture = texture; this.signature = signature; this.allPerks = allPerks; } - public String getColoredName() { - return color + displayName; - } - public static List getRegularMayors() { return Arrays.stream(values()).filter(m -> !m.special).toList(); } @@ -114,6 +107,23 @@ public static List getSpecialMayors() { return Arrays.stream(values()).filter(m -> m.special).toList(); } + public SkyBlockMayor setColor(String color) { + this.color = color; + return this; + } + + public SkyBlockMayor setColorFromIndex(int index) { + String color = switch (index) { + case 0 -> "§c"; + case 1 -> "§a"; + case 2 -> "§b"; + case 3 -> "§e"; + case 4 -> "§d"; + default -> "§f"; + }; + return setColor(color); + } + @Getter public enum Perk { SLASHED_PRICING("SLASHED Pricing", "§7Starting slayer quests is §ehalf price§7."), diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java index b41e2d76e..a7044019c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java @@ -3,6 +3,7 @@ import net.minestom.server.entity.PlayerSkin; import net.minestom.server.inventory.InventoryType; import net.minestom.server.item.Material; +import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.v2.Components; import net.swofty.type.generic.gui.v2.DefaultState; @@ -35,11 +36,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (!data.isElectionOpen() || data.getCandidates().isEmpty()) { layout.slot(13, (s, c) -> ItemStackCreator.getStack( - "§cNo Active Election", - Material.BARRIER, - 1, - "§7There is no active election", - "§7at this time." + "§cNo Active Election", + Material.BARRIER, + 1, + "§7There is no active election", + "§7at this time." )); return; } @@ -60,7 +61,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont long votes = tally.getOrDefault(candidate.getMayorName(), 0L); String voteStr = formatVotes(votes); String pctStr = totalVotes > 0 - ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; + ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; int yearsSince = data.getYearsSinceLastElected(candidate.getMayorName(), currentYear); String candidateName = candidate.getMayorName(); @@ -69,19 +70,23 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont boolean isVotedFor = candidateName.equals(playerVote); List lore = buildCandidateLore( - mayor, candidate, data.getElectionYear(), - yearsSince, voteStr, pctStr, isVotedFor + mayor, candidate, data.getElectionYear(), + yearsSince, voteStr, pctStr, isVotedFor ); return ItemStackCreator.getStackHead( - mayor.getColoredName(), - new PlayerSkin(mayor.getTexture(), mayor.getSignature()), - 1, - lore + candidate.getColoredName(), + new PlayerSkin(mayor.getTexture(), mayor.getSignature()), + 1, + lore ); - }, (click, c) -> { + }, (_, c) -> { ElectionManager.castVote(c.player().getUuid(), candidateName); - c.player().sendMessage("§aYou voted for " + mayor.getColoredName() + "§a!"); - c.replace(new ElectionView()); + c.player().sendMessage("§c-----------------------------------------------------"); + c.player().sendMessage("§eYou cast §c1 vote §efor " + candidate.getColoredName() + " §ein the §bYear " + data.getElectionYear() + " Elections§e!"); + c.player().sendMessage(" §bNew player §eFame Rank §a+1 vote"); + c.player().sendMessage(candidate.getColoredName() + " §enow has §c" + pctStr + " §eof votes with §c" + voteStr + " votes§e!"); + c.player().sendMessage("§c-----------------------------------------------------"); + c.replace(new ElectionViewStatsView()); }); } } @@ -92,11 +97,11 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid List lore = new ArrayList<>(); lore.add("§8Year " + electionYear + " Candidate"); lore.add(""); - lore.add("§7Votes: " + mayor.getColor() + voteStr + " §7(" + mayor.getColor() + pctStr + "§7)"); + lore.add("§7Votes: " + candidate.getColor() + voteStr + " §7(" + candidate.getColor() + pctStr + "§7)"); if (yearsSince >= 0) { - lore.add("§7Last elected: " + mayor.getColor() + yearsSince + "y ago"); + lore.add("§7Last elected: " + candidate.getColor() + yearsSince + "y ago"); } else { - lore.add("§7Last elected: " + mayor.getColor() + "Never"); + lore.add("§7Last elected: " + candidate.getColor() + "Never"); } lore.add(""); lore.add("§8§m--------------------------"); @@ -105,9 +110,9 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid for (int j = 0; j < activePerks.size(); j++) { SkyBlockMayor.Perk perk = activePerks.get(j); if (j == 0) { - lore.add("§6✯ " + mayor.getColor() + perk.getDisplayName()); + lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor("§6✯ " + candidate.getColor() + perk.getDisplayName(), 50)); } else { - lore.add(mayor.getColor() + perk.getDisplayName()); + lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor(candidate.getColor() + perk.getDisplayName(), 50)); } lore.add(perk.getDescription()); if (j < activePerks.size() - 1) lore.add(""); @@ -117,7 +122,7 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid if (!mayor.isSpecial()) { lore.add(""); - lore.add("§6✯ " + mayor.getColor() + "Minister Perks §7are also granted if"); + lore.add("§6✯ " + candidate.getColor() + "Minister Perks §7are also granted if"); lore.add("§7this mayor wins second place!"); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java index 14dd9e5dc..a1ab5dabe 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java @@ -1,7 +1,9 @@ package net.swofty.type.skyblockgeneric.gui.inventories.election; +import net.minestom.server.entity.PlayerSkin; import net.minestom.server.inventory.InventoryType; import net.minestom.server.item.Material; +import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.v2.Components; import net.swofty.type.generic.gui.v2.DefaultState; @@ -22,7 +24,7 @@ public class ElectionViewStatsView extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>("Election Stats", InventoryType.CHEST_6_ROW); + return new ViewConfiguration<>("Election, Year " + SkyBlockCalendar.getYear(), InventoryType.CHEST_6_ROW); } @Override @@ -34,11 +36,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (!data.isElectionOpen() || data.getCandidates().isEmpty()) { layout.slot(22, (s, c) -> ItemStackCreator.getStack( - "§cNo Active Election", - Material.BARRIER, - 1, - "§7There is no active election", - "§7at this time." + "§cNo Active Election", + Material.BARRIER, + 1, + "§7There is no active election", + "§7at this time." )); return; } @@ -57,7 +59,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont long votes = tally.getOrDefault(candidate.getMayorName(), 0L); String voteStr = formatVotes(votes); String pctStr = totalVotes > 0 - ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; + ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; int yearsSince = data.getYearsSinceLastElected(candidate.getMayorName(), currentYear); String candidateName = candidate.getMayorName(); @@ -73,14 +75,14 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont boolean isVotedFor = candidateName.equals(playerVote); List lore = buildCandidateLore( - mayor, candidate, data.getElectionYear(), - yearsSince, voteStr, pctStr, isVotedFor + mayor, candidate, data.getElectionYear(), + yearsSince, voteStr, pctStr, isVotedFor ); - return ItemStackCreator.getStack( - mayor.getColoredName(), - Material.GRAY_STAINED_GLASS_PANE, - 1, - lore.toArray(new String[0]) + return ItemStackCreator.getStackHead( + candidate.getColoredName(), + new PlayerSkin(candidate.getMayorEnum().getTexture(), candidate.getMayorEnum().getSignature()), + 1, + lore.toArray(new String[0]) ); } @@ -88,14 +90,14 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont int barRow = 6 - finalRow; if (barRow <= barHeight) { return ItemStackCreator.getStack( - mayor.getColor() + voteStr + " votes", - Material.LIME_STAINED_GLASS_PANE, - 1, - mayor.getColor() + pctStr + candidate.getColor() + voteStr + " votes", + Material.LIME_STAINED_GLASS_PANE, + 1, + candidate.getColor() + pctStr ); } return ItemStackCreator.getStack(" ", - Material.BLACK_STAINED_GLASS_PANE, 1); + Material.BLACK_STAINED_GLASS_PANE, 1); }); } } @@ -107,11 +109,11 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid List lore = new ArrayList<>(); lore.add("§8Year " + electionYear + " Candidate"); lore.add(""); - lore.add("§7Votes: " + mayor.getColor() + voteStr + " §7(" + mayor.getColor() + pctStr + "§7)"); + lore.add("§7Votes: " + candidate.getColor() + voteStr + " §7(" + candidate.getColor() + pctStr + "§7)"); if (yearsSince >= 0) { - lore.add("§7Last elected: " + mayor.getColor() + yearsSince + "y ago"); + lore.add("§7Last elected: " + candidate.getColor() + yearsSince + "y ago"); } else { - lore.add("§7Last elected: " + mayor.getColor() + "Never"); + lore.add("§7Last elected: " + candidate.getColor() + "Never"); } lore.add(""); lore.add("§8§m--------------------------"); @@ -120,9 +122,9 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid for (int j = 0; j < activePerks.size(); j++) { SkyBlockMayor.Perk perk = activePerks.get(j); if (j == 0) { - lore.add("§6✯ " + mayor.getColor() + perk.getDisplayName()); + lore.add("§6✯ " + candidate.getColor() + perk.getDisplayName()); } else { - lore.add(mayor.getColor() + perk.getDisplayName()); + lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor(candidate.getColor() + perk.getDisplayName(), 50)); } lore.add(perk.getDescription()); if (j < activePerks.size() - 1) lore.add(""); @@ -132,7 +134,7 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid if (!mayor.isSpecial()) { lore.add(""); - lore.add("§6✯ " + mayor.getColor() + "Minister Perks §7are also granted if"); + lore.add("§6✯ " + candidate.getColor() + "Minister Perks §7are also granted if"); lore.add("§7this mayor wins second place!"); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java index 72fa65a01..89d49e120 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java @@ -3,6 +3,7 @@ import net.minestom.server.entity.PlayerSkin; import net.minestom.server.inventory.InventoryType; import net.minestom.server.item.Material; +import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.v2.Components; import net.swofty.type.generic.gui.v2.DefaultState; @@ -43,7 +44,9 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont for (SkyBlockMayor.Perk perk : activePerks) { lore.add(mayor.getColor() + perk.getDisplayName()); - lore.add(perk.getDescription()); + for (String line : StringUtility.splitByWordAndLengthKeepLegacyColor(perk.getDescription(), 50)) { + lore.add("§7" + line); + } lore.add(""); } @@ -61,14 +64,39 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont ); }); - layout.slot(15, (s, c) -> ItemStackCreator.getStack( - "§bElection & Voting", - Material.JUKEBOX, - 1, - "§7View the current election", - "§7candidates and cast your vote.", - "", - "§eClick to view!" - ), (click, c) -> c.push(new ElectionView())); + layout.slot(15, (s, c) -> { + ElectionData.ElectionResult lastResult = data.getLastElectionResult(); + if (lastResult == null) { + return ItemStackCreator.getStack( + "§bMayor Election Results", + Material.JUKEBOX, + 1, + "§7No previous election data", + "§7available." + ); + } + + List resultLore = new ArrayList<>(); + resultLore.add("§8Year " + lastResult.getYear()); + resultLore.add(""); + + for (ElectionData.CandidateResult cr : lastResult.getCandidateResults()) { + SkyBlockMayor m = null; + try { m = SkyBlockMayor.valueOf(cr.getMayorName()); } catch (IllegalArgumentException ignored) {} + String clr = m != null ? m.getColor() : "§7"; + String name = m != null ? m.getDisplayName() : cr.getMayorName(); + resultLore.add(clr + String.format("%.1f%%", cr.getPercentage()) + + "§8 ○ " + clr + String.format("%,d", cr.getVotes()) + + " votes§8 | " + clr + name); + } + + resultLore.add(""); + resultLore.add("§7These are the votes for the"); + resultLore.add("§7last election in which " + mayor.getDisplayName()); + resultLore.add("§7was elected."); + + return ItemStackCreator.getStack("§bMayor Election Results", Material.JUKEBOX, 1, + resultLore.toArray(new String[0])); + }); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java index be93d9d43..709b52397 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java @@ -2,6 +2,8 @@ import net.minestom.server.entity.PlayerSkin; import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.Material; +import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.v2.Components; import net.swofty.type.generic.gui.v2.DefaultState; @@ -42,7 +44,9 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (activePerk != null) { lore.add(minister.getColor() + activePerk.getDisplayName()); - lore.add(activePerk.getDescription()); + for (String line : StringUtility.splitByWordAndLengthKeepLegacyColor(activePerk.getDescription(), 50)) { + lore.add("§7" + line); + } } lore.add("§8§m--------------------------"); @@ -58,5 +62,41 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont lore ); }); + + layout.slot(15, (s, c) -> { + ElectionData.ElectionResult lastResult = data.getLastElectionResult(); + if (lastResult == null) { + return ItemStackCreator.getStack( + "§bMayor Election Results", + Material.JUKEBOX, + 1, + "§7No previous election data", + "§7available." + ); + } + + SkyBlockMayor currentMayor = ElectionManager.getCurrentMayor(); + List resultLore = new ArrayList<>(); + resultLore.add("§8Year " + lastResult.getYear()); + resultLore.add(""); + + for (ElectionData.CandidateResult cr : lastResult.getCandidateResults()) { + SkyBlockMayor m = null; + try { m = SkyBlockMayor.valueOf(cr.getMayorName()); } catch (IllegalArgumentException ignored) {} + String clr = m != null ? m.getColor() : "§7"; + String name = m != null ? m.getDisplayName() : cr.getMayorName(); + resultLore.add(clr + String.format("%.1f%%", cr.getPercentage()) + + "§8 ○ " + clr + String.format("%,d", cr.getVotes()) + + " votes§8 | " + clr + name); + } + + resultLore.add(""); + resultLore.add("§7These are the votes for the"); + resultLore.add("§7last election in which " + (currentMayor != null ? currentMayor.getDisplayName() : "???")); + resultLore.add("§7was elected."); + + return ItemStackCreator.getStack("§bMayor Election Results", Material.JUKEBOX, 1, + resultLore.toArray(new String[0])); + }); } } From 3cf5c52115bc349595d6c740d657f88289bd7654 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Thu, 26 Feb 2026 22:01:50 +0200 Subject: [PATCH 06/17] feat: scalable and now finished --- .../election/CastVoteProtocolObject.java | 6 +- .../election/GetPlayerVoteProtocolObject.java | 62 ++++++++++++ configuration/skyblock/Minestom.regions.csv | 1 + .../election/endpoints/CastVoteEndpoint.java | 10 +- .../endpoints/GetElectionDataEndpoint.java | 35 ++++++- .../endpoints/GetPlayerVoteEndpoint.java | 47 +++++++++ .../net/swofty/type/hub/ElectionDisplay.java | 62 ++++++++++++ .../net/swofty/type/hub/TypeHubLoader.java | 4 +- .../calendar/SkyBlockCalendar.java | 26 +++-- .../elections/ElectionData.java | 29 ++++-- .../elections/ElectionManager.java | 95 ++++++++++++++++++- .../inventories/election/ElectionView.java | 8 +- .../election/ElectionViewStatsView.java | 78 +++++++++------ .../inventories/election/MayorMenuView.java | 4 +- .../election/MinisterMenuView.java | 4 +- .../skyblockgeneric/region/RegionType.java | 1 + .../user/SkyBlockScoreboard.java | 90 ++++++++++-------- .../net/swofty/velocity/SkyBlockVelocity.java | 2 +- 18 files changed, 460 insertions(+), 104 deletions(-) create mode 100644 commons/src/main/java/net/swofty/commons/protocol/objects/election/GetPlayerVoteProtocolObject.java create mode 100644 service.elections/src/main/java/net/swofty/service/election/endpoints/GetPlayerVoteEndpoint.java create mode 100644 type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java index c2f8b0c36..6420771d8 100644 --- a/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java @@ -44,7 +44,7 @@ public Serializer getReturnSerializer() { public String serialize(CastVoteResponse value) { JSONObject json = new JSONObject(); json.put("success", value.success()); - json.put("serializedData", value.serializedData()); + json.put("talliesJson", value.talliesJson()); return json.toString(); } @@ -53,7 +53,7 @@ public CastVoteResponse deserialize(String json) { JSONObject obj = new JSONObject(json); return new CastVoteResponse( obj.getBoolean("success"), - obj.optString("serializedData", null) + obj.optString("talliesJson", null) ); } @@ -66,5 +66,5 @@ public CastVoteResponse clone(CastVoteResponse value) { public record CastVoteMessage(UUID accountId, String candidateName) {} - public record CastVoteResponse(boolean success, String serializedData) {} + public record CastVoteResponse(boolean success, String talliesJson) {} } diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetPlayerVoteProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetPlayerVoteProtocolObject.java new file mode 100644 index 000000000..1db19f545 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetPlayerVoteProtocolObject.java @@ -0,0 +1,62 @@ +package net.swofty.commons.protocol.objects.election; + +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; +import org.json.JSONObject; + +import java.util.UUID; + +public class GetPlayerVoteProtocolObject + extends ProtocolObject { + + @Override + public Serializer getSerializer() { + return new Serializer<>() { + @Override + public String serialize(GetPlayerVoteMessage value) { + JSONObject json = new JSONObject(); + json.put("accountId", value.accountId().toString()); + return json.toString(); + } + + @Override + public GetPlayerVoteMessage deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new GetPlayerVoteMessage(UUID.fromString(obj.getString("accountId"))); + } + + @Override + public GetPlayerVoteMessage clone(GetPlayerVoteMessage value) { + return value; + } + }; + } + + @Override + public Serializer getReturnSerializer() { + return new Serializer<>() { + @Override + public String serialize(GetPlayerVoteResponse value) { + JSONObject json = new JSONObject(); + json.put("candidateName", value.candidateName()); + return json.toString(); + } + + @Override + public GetPlayerVoteResponse deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new GetPlayerVoteResponse(obj.optString("candidateName", null)); + } + + @Override + public GetPlayerVoteResponse clone(GetPlayerVoteResponse value) { + return value; + } + }; + } + + public record GetPlayerVoteMessage(UUID accountId) {} + + public record GetPlayerVoteResponse(String candidateName) {} +} diff --git a/configuration/skyblock/Minestom.regions.csv b/configuration/skyblock/Minestom.regions.csv index 72221a46a..3de5215db 100644 --- a/configuration/skyblock/Minestom.regions.csv +++ b/configuration/skyblock/Minestom.regions.csv @@ -8,6 +8,7 @@ thaumaturgist_2,THAUMATURGIST,-48,74,-65,-57,70,-59,SKYBLOCK_HUB mountain,MOUNTAIN,-51,98,16,-38,85,1,SKYBLOCK_HUB trade_center,TRADE_CENTER,-29,73,-73,-38,68,-83,SKYBLOCK_HUB combat_settlement,COMBAT_SETTLEMENT,-32,63,-61,-70,88,-98,SKYBLOCK_HUB +election_room,ELECTION_ROOM,-16,63,54,16,47,16,SKYBLOCK_HUB goldmine_1,GOLD_MINE,52,136,-261,-106,14,-404,GOLD_MINE deepcavern_1,DEEP_CAVERNS,-68,235,112,135,0,-72,DEEP_CAVERNS gunpowder,GUNPOWDER_MINES,159,165,42,-38,143,-62,DEEP_CAVERNS diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java index 9eacd1a30..7c3776b6a 100644 --- a/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java @@ -60,7 +60,15 @@ public CastVoteProtocolObject.CastVoteResponse onMessage( String updatedData = GSON.toJson(data); ElectionDatabase.saveElectionData(updatedData); - return new CastVoteProtocolObject.CastVoteResponse(true, updatedData); + Map tally = new HashMap<>(); + for (Map c : candidates) { + tally.put((String) c.get("mayorName"), 0L); + } + for (String candidateName : votes.values()) { + tally.merge(candidateName, 1L, Long::sum); + } + + return new CastVoteProtocolObject.CastVoteResponse(true, GSON.toJson(tally)); } catch (Exception e) { return new CastVoteProtocolObject.CastVoteResponse(false, null); } diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java index 76ee8baef..a860cbd4d 100644 --- a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java @@ -1,15 +1,22 @@ package net.swofty.service.election.endpoints; +import com.google.gson.Gson; import net.swofty.commons.impl.ServiceProxyRequest; import net.swofty.commons.protocol.ProtocolObject; import net.swofty.commons.protocol.objects.election.GetElectionDataProtocolObject; import net.swofty.service.election.ElectionDatabase; import net.swofty.service.generic.redis.ServiceEndpoint; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class GetElectionDataEndpoint implements ServiceEndpoint { + private static final Gson GSON = new Gson(); + @Override public ProtocolObject associatedProtocolObject() { @@ -17,6 +24,7 @@ GetElectionDataProtocolObject.GetElectionDataResponse> associatedProtocolObject( } @Override + @SuppressWarnings("unchecked") public GetElectionDataProtocolObject.GetElectionDataResponse onMessage( ServiceProxyRequest message, GetElectionDataProtocolObject.GetElectionDataMessage messageObject) { @@ -24,6 +32,31 @@ public GetElectionDataProtocolObject.GetElectionDataResponse onMessage( if (data == null) { return new GetElectionDataProtocolObject.GetElectionDataResponse(false, null); } - return new GetElectionDataProtocolObject.GetElectionDataResponse(true, data); + + try { + Map parsed = GSON.fromJson(data, Map.class); + + Map votes = (Map) parsed.get("votes"); + List> candidates = (List>) parsed.get("candidates"); + + Map tallies = new HashMap<>(); + if (candidates != null) { + for (Map c : candidates) { + tallies.put((String) c.get("mayorName"), 0L); + } + } + if (votes != null) { + for (String candidateName : votes.values()) { + tallies.merge(candidateName, 1L, Long::sum); + } + } + + parsed.put("voteTallies", tallies); + parsed.remove("votes"); + + return new GetElectionDataProtocolObject.GetElectionDataResponse(true, GSON.toJson(parsed)); + } catch (Exception e) { + return new GetElectionDataProtocolObject.GetElectionDataResponse(true, data); + } } } diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetPlayerVoteEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetPlayerVoteEndpoint.java new file mode 100644 index 000000000..29e734b99 --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetPlayerVoteEndpoint.java @@ -0,0 +1,47 @@ +package net.swofty.service.election.endpoints; + +import com.google.gson.Gson; +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.objects.election.GetPlayerVoteProtocolObject; +import net.swofty.service.election.ElectionDatabase; +import net.swofty.service.generic.redis.ServiceEndpoint; + +import java.util.Map; + +public class GetPlayerVoteEndpoint implements ServiceEndpoint + { + + private static final Gson GSON = new Gson(); + + @Override + public ProtocolObject associatedProtocolObject() { + return new GetPlayerVoteProtocolObject(); + } + + @Override + @SuppressWarnings("unchecked") + public GetPlayerVoteProtocolObject.GetPlayerVoteResponse onMessage( + ServiceProxyRequest message, + GetPlayerVoteProtocolObject.GetPlayerVoteMessage messageObject) { + try { + String rawData = ElectionDatabase.loadElectionData(); + if (rawData == null) { + return new GetPlayerVoteProtocolObject.GetPlayerVoteResponse(null); + } + + Map data = GSON.fromJson(rawData, Map.class); + Map votes = (Map) data.get("votes"); + if (votes == null) { + return new GetPlayerVoteProtocolObject.GetPlayerVoteResponse(null); + } + + String vote = votes.get(messageObject.accountId().toString()); + return new GetPlayerVoteProtocolObject.GetPlayerVoteResponse(vote); + } catch (Exception e) { + return new GetPlayerVoteProtocolObject.GetPlayerVoteResponse(null); + } + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java b/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java new file mode 100644 index 000000000..7f6de7d14 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java @@ -0,0 +1,62 @@ +package net.swofty.type.hub; + +import net.minestom.server.coordinate.Pos; +import net.swofty.commons.StringUtility; +import net.swofty.type.generic.HypixelGenericLoader; +import net.swofty.type.generic.entity.hologram.PlayerHolograms; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.calendar.CalendarEvent; +import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import org.tinylog.Logger; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ElectionDisplay { + + private static final Map holos = new HashMap<>(); + + public static void addAndUpdate() { + HypixelGenericLoader.getLoadedPlayers().forEach(player -> { + long timeLeft = SkyBlockCalendar.ticksUntilEvent(CalendarEvent.ELECTION_CLOSE); + String timeLeftFormatted = StringUtility.formatTimeLeft(timeLeft * 50L); + + Logger.info(timeLeftFormatted + " until election close for player " + timeLeft); + + List message = new ArrayList<>(List.of( + "§e§lMAYOR ELECTIONS", + "§bYear " + SkyBlockCalendar.getYear(), + "§eTime left: §a" + timeLeftFormatted + )); + + String vote = ElectionManager.getPlayerVote(player.getUuid()); + if (vote != null) { + SkyBlockMayor mayor = SkyBlockMayor.valueOf(vote); + String colouredName = mayor.getColor() + mayor.getDisplayName(); + message.add("§eYour vote: §f" + colouredName); + message.add("§e§lCLICK TO SWITCH"); + } + + if (!holos.containsKey(player)) { + PlayerHolograms.ExternalPlayerHologram holo = PlayerHolograms.ExternalPlayerHologram.builder() + .player(player) + .text(message.toArray(new String[0])) + .pos(new Pos(0.5, 51.5, 34.5)) + .spacing(0.3d) + .instance(player.getInstance()) + .build(); + + PlayerHolograms.addExternalPlayerHologram(holo); + holos.put(player, holo); + return; + } + + PlayerHolograms.updateExternalPlayerHologramText(holos.get(player), message.toArray(new String[0])); + }); + } + +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java b/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java index 5147e9ecc..9f89756ec 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java +++ b/type.hub/src/main/java/net/swofty/type/hub/TypeHubLoader.java @@ -179,6 +179,8 @@ public void afterInitialize(MinecraftServer server) { player.openView(new ElectionViewStatsView()); } }).setInstance(HypixelConst.getInstanceContainer(), new Pos(0.5, 50, 34.5)); + + MinecraftServer.getSchedulerManager().buildTask(ElectionDisplay::addAndUpdate).delay(TaskSchedule.seconds(1)).repeat(TaskSchedule.seconds(1)).schedule(); } private static String[] electionLines() { @@ -186,7 +188,7 @@ private static String[] electionLines() { "§e§lMAYOR ELECTIONS", "§bYear " + SkyBlockCalendar.getYear(), "§eTime left: §a" + StringUtility.formatTimeLeft( - SkyBlockCalendar.timeUntilEvent(CalendarEvent.ELECTION_CLOSE)) + SkyBlockCalendar.ticksUntilEvent(CalendarEvent.ELECTION_CLOSE) * 50L) }; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java index 3d97cd5da..ae2d763ac 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/calendar/SkyBlockCalendar.java @@ -7,7 +7,9 @@ import net.swofty.type.skyblockgeneric.commands.MinionGenerationCommand; import java.time.Duration; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -144,31 +146,27 @@ public static Map getEventsWithDurationUntil(int amoun return result; } - // TODO: clean this up - public static long timeUntilEvent(CalendarEvent event) { + public static long ticksUntilEvent(CalendarEvent event) { long currentElapsed = getElapsed(); int currentYear = getYear(); - int yearsAhead = 0; - - do { + for (int yearsAhead = 0; yearsAhead <= 100; yearsAhead++) { int targetYear = currentYear + yearsAhead; long yearStartElapsed = (long) (targetYear - 1) * YEAR; - for (Long eventTime : event.times()) { + List sortedTimes = new ArrayList<>(event.times()); + Collections.sort(sortedTimes); + + for (Long eventTime : sortedTimes) { long eventElapsed = yearStartElapsed + eventTime; - // Skip events that have already passed (including currently ongoing ones that started) - if (eventElapsed <= currentElapsed) { - continue; + if (eventElapsed > currentElapsed) { + return eventElapsed - currentElapsed; } - - return eventElapsed - currentElapsed; } - yearsAhead++; - } while (yearsAhead <= 100); + } - return -1; // Return -1 if no upcoming event is found within a reasonable timeframe + return -1; } public static Map getEventsWithDurationUntilSkipSpecific(int amount, List event) { diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java index 926f2acb2..4e4878d0b 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java @@ -10,7 +10,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; @Getter @@ -28,7 +27,8 @@ public class ElectionData { private String ministerPerk; private List candidates = new ArrayList<>(); - private Map votes = new HashMap<>(); + private transient Map votes = new HashMap<>(); + private Map voteTallies = new HashMap<>(); private boolean electionOpen; private Map lastElectedYear = new HashMap<>(); @@ -76,15 +76,10 @@ public List getCurrentMayorPerkEnums() { return result; } - public void castVote(UUID accountId, String candidateName) { - votes.put(accountId.toString(), candidateName); - } - - public String getVote(UUID accountId) { - return votes.get(accountId.toString()); - } - public Map tallyVotes() { + if (!voteTallies.isEmpty()) { + return new HashMap<>(voteTallies); + } Map tally = new HashMap<>(); for (CandidateData candidate : candidates) { tally.put(candidate.getMayorName(), 0L); @@ -95,6 +90,18 @@ public Map tallyVotes() { return tally; } + public void updateTallies(Map newTallies) { + voteTallies.clear(); + voteTallies.putAll(newTallies); + } + + public void incrementTally(String candidateName, String previousVote) { + if (previousVote != null) { + voteTallies.computeIfPresent(previousVote, (k, v) -> Math.max(0, v - 1)); + } + voteTallies.merge(candidateName, 1L, Long::sum); + } + public void resolveElection(int currentYear) { Map tally = tallyVotes(); List> sorted = new ArrayList<>(tally.entrySet()); @@ -206,6 +213,7 @@ public void resolveElection(int currentYear) { candidates.clear(); votes.clear(); + voteTallies.clear(); electionOpen = false; } @@ -213,6 +221,7 @@ public void startNewElection(int year) { this.electionYear = year; this.electionOpen = true; this.votes.clear(); + this.voteTallies.clear(); this.candidates.clear(); boolean isSpecialYear = (year % 8 == 0); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java index 12b64b63c..f79d8e238 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java @@ -1,25 +1,33 @@ package net.swofty.type.skyblockgeneric.elections; import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import lombok.Getter; +import net.minestom.server.MinecraftServer; +import net.minestom.server.timer.TaskSchedule; import net.swofty.commons.ServiceType; import net.swofty.commons.protocol.objects.election.CastVoteProtocolObject; import net.swofty.commons.protocol.objects.election.GetCandidatesProtocolObject; import net.swofty.commons.protocol.objects.election.GetElectionDataProtocolObject; +import net.swofty.commons.protocol.objects.election.GetPlayerVoteProtocolObject; import net.swofty.commons.protocol.objects.election.SaveElectionDataProtocolObject; import net.swofty.proxyapi.ProxyService; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import org.tinylog.Logger; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; public class ElectionManager { private static final Gson GSON = new Gson(); private static ProxyService SERVICE; + private static final ConcurrentHashMap playerVoteCache = new ConcurrentHashMap<>(); @Getter private static ElectionData electionData = new ElectionData(); @@ -52,6 +60,8 @@ public static void loadFromService() { electionData = new ElectionData(); initializeFirstElection(); } + + startTallyRefreshTask(); } public static void saveToService() { @@ -89,8 +99,11 @@ public static void onElectionStart() { public static void onElectionEnd() { if (!electionData.isElectionOpen()) return; + refreshTalliesSync(); + int currentYear = SkyBlockCalendar.getYear(); electionData.resolveElection(currentYear); + playerVoteCache.clear(); saveToService(); Logger.info("Election resolved for Year {}. New Mayor: {}", currentYear, electionData.getCurrentMayor()); } @@ -102,20 +115,47 @@ public static CompletableFuture castVote(UUID accountId, String candidateN .anyMatch(c -> c.getMayorName().equals(candidateName)); if (!validCandidate) return CompletableFuture.completedFuture(null); - electionData.castVote(accountId, candidateName); + String previousVote = playerVoteCache.put(accountId, candidateName); + electionData.incrementTally(candidateName, previousVote); return SERVICE.handleRequest( new CastVoteProtocolObject.CastVoteMessage(accountId, candidateName) ).thenAccept(response -> { - if (response.success() && response.serializedData() != null) { - electionData = GSON.fromJson(response.serializedData(), ElectionData.class); + if (response.success() && response.talliesJson() != null) { + Map tallies = GSON.fromJson( + response.talliesJson(), + new TypeToken>(){}.getType() + ); + electionData.updateTallies(tallies); } + }).exceptionally(e -> { + Logger.error(e, "Failed to sync vote to service"); + return null; }); } public static String getPlayerVote(UUID accountId) { - return electionData.getVote(accountId); + return playerVoteCache.get(accountId); + } + + public static CompletableFuture fetchPlayerVote(UUID accountId) { + String cached = playerVoteCache.get(accountId); + if (cached != null) return CompletableFuture.completedFuture(cached); + + return SERVICE.handleRequest( + new GetPlayerVoteProtocolObject.GetPlayerVoteMessage(accountId) + ).thenApply(response -> { + if (response.candidateName() != null) { + playerVoteCache.put(accountId, response.candidateName()); + } + return response.candidateName(); + }); + } + + public static void clearPlayerVoteCache(UUID accountId) { + playerVoteCache.remove(accountId); } public static SkyBlockMayor getCurrentMayor() { @@ -160,4 +200,51 @@ public static void checkElectionCycle() { onElectionEnd(); } } + + private static void startTallyRefreshTask() { + MinecraftServer.getSchedulerManager().submitTask(() -> { + if (electionData.isElectionOpen()) { + refreshTalliesAsync(); + } + return TaskSchedule.seconds(30); + }); + } + + private static void refreshTalliesAsync() { + SERVICE.handleRequest( + new GetCandidatesProtocolObject.GetCandidatesMessage() + ).thenAccept(response -> { + if (response.electionOpen()) { + Map tallies = new HashMap<>(); + for (GetCandidatesProtocolObject.CandidateInfo info : response.candidates()) { + tallies.put(info.mayorName(), info.votes()); + } + electionData.updateTallies(tallies); + } + }).exceptionally(e -> { + Logger.warn("Failed to refresh election tallies: {}", e.getMessage()); + return null; + }); + } + + private static void refreshTalliesSync() { + try { + GetCandidatesProtocolObject.GetCandidatesResponse response = + SERVICE.handleRequest( + new GetCandidatesProtocolObject.GetCandidatesMessage() + ).join(); + + if (response.electionOpen()) { + Map tallies = new HashMap<>(); + for (GetCandidatesProtocolObject.CandidateInfo info : response.candidates()) { + tallies.put(info.mayorName(), info.votes()); + } + electionData.updateTallies(tallies); + } + } catch (Exception e) { + Logger.error(e, "Failed to sync tallies before election resolution"); + } + } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java index a7044019c..7a2567e4f 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java @@ -110,11 +110,13 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid for (int j = 0; j < activePerks.size(); j++) { SkyBlockMayor.Perk perk = activePerks.get(j); if (j == 0) { - lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor("§6✯ " + candidate.getColor() + perk.getDisplayName(), 50)); + lore.add("§6✯ " + candidate.getColor() + perk.getDisplayName()); } else { - lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor(candidate.getColor() + perk.getDisplayName(), 50)); + lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor( + candidate.getColor() + perk.getDisplayName(), 35)); } - lore.add(perk.getDescription()); + lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor( + perk.getDescription(), 35)); if (j < activePerks.size() - 1) lore.add(""); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java index a1ab5dabe..55f5183a5 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java @@ -30,7 +30,6 @@ public ViewConfiguration configuration() { @Override public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { Components.fill(layout); - Components.backOrClose(layout, 49, ctx); ElectionData data = ElectionManager.getElectionData(); @@ -45,12 +44,22 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont return; } - int currentYear = SkyBlockCalendar.getYear(); Map tally = data.tallyVotes(); long totalVotes = tally.values().stream().mapToLong(Long::longValue).sum(); + int currentYear = SkyBlockCalendar.getYear(); List candidates = data.getCandidates(); + String leaderName = null; + long leaderVotes = -1; + for (ElectionData.CandidateData c : candidates) { + long v = tally.getOrDefault(c.getMayorName(), 0L); + if (v > leaderVotes) { + leaderVotes = v; + leaderName = c.getMayorName(); + } + } + for (int i = 0; i < candidates.size() && i < 5; i++) { ElectionData.CandidateData candidate = candidates.get(i); SkyBlockMayor mayor = candidate.getMayorEnum(); @@ -62,42 +71,51 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont ? String.format("%.1f%%", (votes * 100.0) / totalVotes) : "0%"; int yearsSince = data.getYearsSinceLastElected(candidate.getMayorName(), currentYear); String candidateName = candidate.getMayorName(); + boolean isLeader = candidateName.equals(leaderName) && votes > 0; + Material glassMaterial = isLeader ? Material.ORANGE_STAINED_GLASS_PANE : Material.GRAY_STAINED_GLASS_PANE; int col = i * 2; for (int row = 0; row < 6; row++) { int slot = row * 9 + col; - int finalRow = row; + int finalRow = row; layout.slot(slot, (s, c) -> { - if (finalRow == 0) { - String playerVote = ElectionManager.getPlayerVote(c.player().getUuid()); - boolean isVotedFor = candidateName.equals(playerVote); + String playerVote = ElectionManager.getPlayerVote(c.player().getUuid()); + boolean isVotedFor = candidateName.equals(playerVote); - List lore = buildCandidateLore( - mayor, candidate, data.getElectionYear(), - yearsSince, voteStr, pctStr, isVotedFor - ); + List lore = buildCandidateLore( + mayor, candidate, data.getElectionYear(), + yearsSince, voteStr, pctStr, isVotedFor, isLeader + ); + + if (finalRow == 5) { return ItemStackCreator.getStackHead( candidate.getColoredName(), - new PlayerSkin(candidate.getMayorEnum().getTexture(), candidate.getMayorEnum().getSignature()), + new PlayerSkin(mayor.getTexture(), mayor.getSignature()), 1, - lore.toArray(new String[0]) + lore ); } - - int barHeight = totalVotes > 0 ? (int) Math.ceil((votes * 5.0) / totalVotes) : 0; - int barRow = 6 - finalRow; - if (barRow <= barHeight) { - return ItemStackCreator.getStack( - candidate.getColor() + voteStr + " votes", - Material.LIME_STAINED_GLASS_PANE, - 1, - candidate.getColor() + pctStr - ); + return ItemStackCreator.getStack( + candidate.getColoredName(), + glassMaterial, + 1, + lore + ); + }, (_, c) -> { + String playerVote = ElectionManager.getPlayerVote(c.player().getUuid()); + if (candidateName.equals(playerVote)) { + c.player().sendMessage("§aYou voted for this candidate."); + return; } - return ItemStackCreator.getStack(" ", - Material.BLACK_STAINED_GLASS_PANE, 1); + ElectionManager.castVote(c.player().getUuid(), candidateName); + c.player().sendMessage("§c-----------------------------------------------------"); + c.player().sendMessage("§eYou cast §c1 vote §efor " + candidate.getColoredName() + " §ein the §bYear " + data.getElectionYear() + " Elections§e!"); + c.player().sendMessage(" §bNew player §eFame Rank §a+1 vote"); + c.player().sendMessage(candidate.getColoredName() + " §enow has §c" + pctStr + " §eof votes with §c" + voteStr + " votes§e!"); + c.player().sendMessage("§c-----------------------------------------------------"); + c.replace(new ElectionViewStatsView()); }); } } @@ -105,11 +123,15 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.CandidateData candidate, int electionYear, int yearsSince, - String voteStr, String pctStr, boolean votedFor) { + String voteStr, String pctStr, + boolean votedFor, boolean isLeader) { List lore = new ArrayList<>(); lore.add("§8Year " + electionYear + " Candidate"); lore.add(""); lore.add("§7Votes: " + candidate.getColor() + voteStr + " §7(" + candidate.getColor() + pctStr + "§7)"); + if (isLeader) { + lore.add(candidate.getColor() + "Leading in votes!"); + } if (yearsSince >= 0) { lore.add("§7Last elected: " + candidate.getColor() + yearsSince + "y ago"); } else { @@ -124,9 +146,11 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid if (j == 0) { lore.add("§6✯ " + candidate.getColor() + perk.getDisplayName()); } else { - lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor(candidate.getColor() + perk.getDisplayName(), 50)); + lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor( + candidate.getColor() + perk.getDisplayName(), 35)); } - lore.add(perk.getDescription()); + lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor( + perk.getDescription(), 35)); if (j < activePerks.size() - 1) lore.add(""); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java index 89d49e120..da0bc131c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java @@ -22,7 +22,9 @@ public class MayorMenuView extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>("Mayor", InventoryType.CHEST_4_ROW); + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return new ViewConfiguration<>("Mayor", InventoryType.CHEST_4_ROW); + return new ViewConfiguration<>("Mayor " + mayor.getDisplayName(), InventoryType.CHEST_4_ROW); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java index 709b52397..5313e1e26 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java @@ -22,7 +22,9 @@ public class MinisterMenuView extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>("Minister", InventoryType.CHEST_4_ROW); + SkyBlockMayor minister = ElectionManager.getCurrentMinister(); + if (minister == null) return new ViewConfiguration<>("Minister", InventoryType.CHEST_4_ROW); + return new ViewConfiguration<>("Minister " + minister.getDisplayName(), InventoryType.CHEST_4_ROW); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/region/RegionType.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/region/RegionType.java index 5776fe236..e04e9f38c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/region/RegionType.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/region/RegionType.java @@ -45,6 +45,7 @@ public enum RegionType { BUILDERS_HOUSE("Builder's House"), THAUMATURGIST("Thaumaturgist", "§6"), TRADE_CENTER("Trade Center"), + ELECTION_ROOM("Election Room"), MOUNTAIN("Mountain"), WILDERNESS("Wilderness", "§2", Songs.WILDERNESS), PLAYER_MUSEUM("%s's Museum", "§3"), diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockScoreboard.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockScoreboard.java index ae56c9393..703476597 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockScoreboard.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockScoreboard.java @@ -16,6 +16,7 @@ import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import net.swofty.type.skyblockgeneric.darkauction.DarkAuctionHandler; import net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.item.SkyBlockItem; import net.swofty.type.skyblockgeneric.mission.LocationAssociatedMission; import net.swofty.type.skyblockgeneric.mission.MissionData; @@ -28,6 +29,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; public class SkyBlockScoreboard { private static final HypixelScoreboard scoreboard = new HypixelScoreboard(); @@ -67,53 +69,67 @@ public static void start() { lines.add(" §7Unknown"); } lines.add("§7 "); - lines.add("§fPurse: §6" + StringUtility.commaify(dataHandler.get(SkyBlockDataHandler.Data.COINS, DatapointDouble.class).getValue())); - lines.add("§fBits: §b" + StringUtility.commaify(dataHandler.get(SkyBlockDataHandler.Data.BITS, DatapointInteger.class).getValue())); - if (DarkAuctionHandler.isPlayerInAuction(player.getUuid()) + // TODO: make classes / a manager for regions to display scoreboard information. + if (region != null && region.getType() == RegionType.ELECTION_ROOM) { + lines.add("§6Year " + SkyBlockCalendar.getYear() + " Votes"); + Map totalVotes = ElectionManager.getElectionData().tallyVotes(); + long maxVotes = totalVotes.values().stream().mapToLong(Long::longValue).max().orElse(1); + ElectionManager.getElectionData().getCandidates().forEach(candidate -> { + long votes = totalVotes.getOrDefault(candidate.getMayorName(), 0L); + int barLength = maxVotes > 0 ? (int) Math.round((votes * 15.0) / maxVotes) : 0; + String bars = candidate.getColor() + "|".repeat(barLength) + "§f" + "|".repeat(15 - barLength); + lines.add(bars + " " + candidate.getColoredName()); + }); + } else { + lines.add("§fPurse: §6" + StringUtility.commaify(dataHandler.get(SkyBlockDataHandler.Data.COINS, DatapointDouble.class).getValue())); + lines.add("§fBits: §b" + StringUtility.commaify(dataHandler.get(SkyBlockDataHandler.Data.BITS, DatapointInteger.class).getValue())); + + if (DarkAuctionHandler.isPlayerInAuction(player.getUuid()) && DarkAuctionHandler.getLocalState() != null && DarkAuctionHandler.getLocalState().getPhase() == DarkAuctionPhase.BIDDING - ) { - lines.add("§8 "); - DarkAuctionHandler.DarkAuctionLocalState auctionState = DarkAuctionHandler.getLocalState(); - int timeRemaining = DarkAuctionHandler.getTimeLeft().get(); - - lines.add("§fTime Left: §9" + timeRemaining + "s"); - lines.add("§fCurrent Item:"); - - String currentItem = auctionState.getCurrentItemType(); - if (currentItem != null) { - try { - ItemType itemType = ItemType.valueOf(currentItem); - SkyBlockItem item = new SkyBlockItem(itemType); - lines.add(" " + item.getDisplayName()); - } catch (Exception e) { - lines.add(" §f" + currentItem.replace("_", " ")); + ) { + lines.add("§8 "); + DarkAuctionHandler.DarkAuctionLocalState auctionState = DarkAuctionHandler.getLocalState(); + int timeRemaining = DarkAuctionHandler.getTimeLeft().get(); + + lines.add("§fTime Left: §9" + timeRemaining + "s"); + lines.add("§fCurrent Item:"); + + String currentItem = auctionState.getCurrentItemType(); + if (currentItem != null) { + try { + ItemType itemType = ItemType.valueOf(currentItem); + SkyBlockItem item = new SkyBlockItem(itemType); + lines.add(" " + item.getDisplayName()); + } catch (Exception e) { + lines.add(" §f" + currentItem.replace("_", " ")); + } + } else { + lines.add(" §7Waiting..."); } } else { - lines.add(" §7Waiting..."); - } - } else { - if (region != null && + if (region != null && !missionData.getActiveMissions(region.getType()).isEmpty()) { - lines.add("§7 "); - MissionData.ActiveMission mission = missionData.getActiveMissions(region.getType()).getFirst(); - SkyBlockMission skyBlockMission = MissionData.getMissionClass(mission.getMissionID()); + lines.add("§7 "); + MissionData.ActiveMission mission = missionData.getActiveMissions(region.getType()).getFirst(); + SkyBlockMission skyBlockMission = MissionData.getMissionClass(mission.getMissionID()); - if (skyBlockMission instanceof LocationAssociatedMission locationAssociatedMission) { - lines.add("§fObjective " + BlockUtility.getArrow( + if (skyBlockMission instanceof LocationAssociatedMission locationAssociatedMission) { + lines.add("§fObjective " + BlockUtility.getArrow( player.getPosition(), locationAssociatedMission.getLocation() - )); - lines.add("§e" + mission); - } else { - lines.add("§fObjective"); - lines.add("§e" + mission); + )); + lines.add("§e" + mission); + } else { + lines.add("§fObjective"); + lines.add("§e" + mission); + } + + SkyBlockProgressMission progressMission = missionData.getAsProgressMission(mission.getMissionID()); + if (progressMission != null) + lines.add("§7 (§e" + mission.getMissionProgress() + "§7/§a" + progressMission.getMaxProgress() + "§7)"); } - - SkyBlockProgressMission progressMission = missionData.getAsProgressMission(mission.getMissionID()); - if (progressMission != null) - lines.add("§7 (§e" + mission.getMissionProgress() + "§7/§a" + progressMission.getMaxProgress() + "§7)"); } } diff --git a/velocity.extension/src/main/java/net/swofty/velocity/SkyBlockVelocity.java b/velocity.extension/src/main/java/net/swofty/velocity/SkyBlockVelocity.java index b8f5d4033..13df69883 100644 --- a/velocity.extension/src/main/java/net/swofty/velocity/SkyBlockVelocity.java +++ b/velocity.extension/src/main/java/net/swofty/velocity/SkyBlockVelocity.java @@ -392,7 +392,7 @@ public void onPing(ProxyPingEvent event) { event.setPing(new ServerPing( event.getPing().getVersion(), null, - Component.text(" §aHypixel Recreation §c[1.8-1.21]"), + Component.text(" §aHypixel Recreation §c[1.8-1.21]"), event.getPing().getFavicon().orElse(null) )); } From 74533879c823a980f5b4a213de8bf00ef74d7753 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Thu, 26 Feb 2026 22:13:21 +0200 Subject: [PATCH 07/17] feat: calendar now autoupdates --- .../net/swofty/type/hub/ElectionDisplay.java | 3 - .../inventories/sbmenu/GUISkyBlockMenu.java | 221 +++++++++--------- .../sbmenu/calendar/GUICalendar.java | 63 +++-- 3 files changed, 154 insertions(+), 133 deletions(-) diff --git a/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java b/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java index 7f6de7d14..837e71340 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java +++ b/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java @@ -9,7 +9,6 @@ import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import org.tinylog.Logger; import java.util.ArrayList; import java.util.HashMap; @@ -25,8 +24,6 @@ public static void addAndUpdate() { long timeLeft = SkyBlockCalendar.ticksUntilEvent(CalendarEvent.ELECTION_CLOSE); String timeLeftFormatted = StringUtility.formatTimeLeft(timeLeft * 50L); - Logger.info(timeLeftFormatted + " until election close for player " + timeLeft); - List message = new ArrayList<>(List.of( "§e§lMAYOR ELECTIONS", "§bYear " + SkyBlockCalendar.getYear(), diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockMenu.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockMenu.java index a76c22bc3..8ab02aba1 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockMenu.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockMenu.java @@ -5,8 +5,13 @@ import net.minestom.server.item.Material; import net.swofty.commons.ServerType; import net.swofty.commons.StringUtility; +import net.swofty.type.generic.data.datapoints.DatapointToggles; import net.swofty.type.generic.gui.inventory.ItemStackCreator; -import net.swofty.type.generic.gui.v2.*; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.calendar.CalendarEvent; @@ -18,7 +23,6 @@ import net.swofty.type.skyblockgeneric.gui.inventories.sbmenu.levels.GUISkyBlockLevels; import net.swofty.type.skyblockgeneric.gui.inventories.sbmenu.profiles.GUIProfileManagement; import net.swofty.type.skyblockgeneric.gui.inventories.sbmenu.questlog.GUIMissionLog; -import net.swofty.type.skyblockgeneric.gui.inventories.sbmenu.recipe.GUIRecipe; import net.swofty.type.skyblockgeneric.gui.inventories.sbmenu.recipe.GUIRecipeBook; import net.swofty.type.skyblockgeneric.gui.inventories.sbmenu.skills.GUISkills; import net.swofty.type.skyblockgeneric.gui.inventories.sbmenu.storage.GUIStorage; @@ -30,6 +34,7 @@ import java.time.Duration; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -50,12 +55,12 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont PlayerStatistics statistics = player.getStatistics(); List lore = new ArrayList<>(List.of("§7View your equipment, stats, and more!", "§e ")); List stats = new ArrayList<>(List.of("Health", "Defense", "Speed", "Strength", "Intelligence", - "Crit Chance", "Crit Damage", "Swing Range" + "Crit Chance", "Crit Damage", "Swing Range" )); statistics.allStatistics().getOverall().forEach((statistic, value) -> { if (!value.equals(statistic.getBaseAdditiveValue()) || stats.contains(statistic.getDisplayName())) { lore.add(" " + statistic.getFullDisplayName() + " §f" + - StringUtility.decimalify(value, 2) + statistic.getSuffix()); + StringUtility.decimalify(value, 2) + statistic.getSuffix()); } }); @@ -63,8 +68,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont lore.add("§eClick to view!"); return ItemStackCreator.getStackHead("§aYour SkyBlock Profile", - player.getPlayerSkin(), 1, - lore + player.getPlayerSkin(), 1, + lore ); }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); @@ -77,25 +82,25 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont SkyBlockLevelRequirement nextLevel = levelRequirement.getNextLevel(); return ItemStackCreator.getStackHead("§aSkyBlock Leveling", "3255327dd8e90afad681a19231665bea2bd06065a09d77ac1408837f9e0b242", 1, - "§7Your SkyBlock Level: §8[" + levelRequirement.getColor() + levelRequirement + "§8]", - " ", - "§7Determine how far you've", - "§7progressed in SkyBlock and earn", - "§7rewards from completing unique", - "§7tasks.", - " ", - "§7Progress to Level " + (nextLevel == null ? "§cMAX" : nextLevel), - player.getSkyBlockExperience().getNextLevelDisplay(), - " ", - "§eClick to view!" + "§7Your SkyBlock Level: §8[" + levelRequirement.getColor() + levelRequirement + "§8]", + " ", + "§7Determine how far you've", + "§7progressed in SkyBlock and earn", + "§7rewards from completing unique", + "§7tasks.", + " ", + "§7Progress to Level " + (nextLevel == null ? "§cMAX" : nextLevel), + player.getSkyBlockExperience().getNextLevelDisplay(), + " ", + "§eClick to view!" ); }, (click, c) -> c.push(new GUISkyBlockLevels())); layout.slot(29, (s, c) -> ItemStackCreator.getStackHead("§aYour Bags", "961a918c0c49ba8d053e522cb91abc74689367b4d8aa06bfc1ba9154730985ff", 1, - "§7Different bags allow you to store", - "§7many different items inside!", - " ", - "§eClick to view!" + "§7Different bags allow you to store", + "§7many different items inside!", + " ", + "§eClick to view!" ), (click, c) -> { c.push(new GUIYourBags()); }); @@ -103,27 +108,27 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(30, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); return ItemStackCreator.getStack("§aPets", Material.BONE, 1, - "§7View and manage all of your", - "§7Pets.", - " ", - "§7Level up your pets faster by", - "§7gaining XP in their favourite", - "§7skill!", - " ", - "§7Selected pet: " + (player.getPetData().getEnabledPet() == null ? "§cNone" : player.getPetData().getEnabledPet().getDisplayName()), - " ", - "§eClick to view!" + "§7View and manage all of your", + "§7Pets.", + " ", + "§7Level up your pets faster by", + "§7gaining XP in their favourite", + "§7skill!", + " ", + "§7Selected pet: " + (player.getPetData().getEnabledPet() == null ? "§cNone" : player.getPetData().getEnabledPet().getDisplayName()), + " ", + "§eClick to view!" ); }, (click, c) -> c.push(new GUIPets(), GUIPets.createInitialState((SkyBlockPlayer) c.player()))); layout.slot(21, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); List lore = new ArrayList<>(List.of( - "§7Through your adventure, you will", - "§7unlock recipes for all kinds of", - "§7special items! You can view how to", - "§7craft these items here.", - " " + "§7Through your adventure, you will", + "§7unlock recipes for all kinds of", + "§7special items! You can view how to", + "§7craft these items here.", + " " )); SkyBlockRecipe.getMissionDisplay(lore, player.getUuid()); @@ -136,46 +141,46 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont }); layout.slot(25, (s, c) -> ItemStackCreator.getStack("§aStorage", Material.CHEST, 1, - "§7Store global items that you", - "§7want to access at any time", - "§7from anywhere here.", - " ", - "§eClick to view!" + "§7Store global items that you", + "§7want to access at any time", + "§7from anywhere here.", + " ", + "§eClick to view!" ), (click, c) -> c.push(new GUIStorage())); layout.slot(23, (s, c) -> ItemStackCreator.getStack("§aQuests & Chapters", Material.WRITABLE_BOOK, 1, - "§7Each island has its own series of", - "§bChapters §7for you to complete!", - " ", - "§7Complete tasks within a Chapter to", - "§7earn small §6rewards§7, or complete", - "§7entire Chapters to earn big ones!", - " ", - "§7Some islands also have §aQuests §7for", - "§7you to complete! Some items can only", - "§7be obtained through Quests.", - " ", - "§eClick to view!" + "§7Each island has its own series of", + "§bChapters §7for you to complete!", + " ", + "§7Complete tasks within a Chapter to", + "§7earn small §6rewards§7, or complete", + "§7entire Chapters to earn big ones!", + " ", + "§7Some islands also have §aQuests §7for", + "§7you to complete! Some items can only", + "§7be obtained through Quests.", + " ", + "§eClick to view!" ), (click, c) -> c.push(new GUIMissionLog())); - layout.autoUpdating(24, (s, c) -> ItemStackCreator.getStack("§aCalendar and Events", Material.CLOCK, 1, getCalendarLore()), - (click, c) -> c.push(new GUICalendar()), Duration.ofSeconds(1)); + layout.autoUpdating(24, (s, c) -> ItemStackCreator.getStack("§aCalendar and Events", Material.CLOCK, 1, getCalendarLore(ctx)), + (_, c) -> c.push(new GUICalendar()), Duration.ofSeconds(1)); layout.slot(19, (s, c) -> ItemStackCreator.getStack("§aYour Skills", Material.DIAMOND_SWORD, 1, - "§7View your Skill progression and", - "§7rewards.", - " ", - "§eClick to view!" + "§7View your Skill progression and", + "§7rewards.", + " ", + "§eClick to view!" ), (click, c) -> c.push(new GUISkills())); layout.slot(20, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); List lore = new ArrayList<>(List.of( - "§7View all of the items available in", - "§7SkyBlock. Collect more of an item to", - "§7unlock rewards on your way to", - "§7becoming a master of SkyBlock!", - " " + "§7View all of the items available in", + "§7SkyBlock. Collect more of an item to", + "§7unlock rewards on your way to", + "§7becoming a master of SkyBlock!", + " " )); player.getCollection().getDisplay(lore); @@ -189,17 +194,17 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont }); layout.slot(31, (s, c) -> ItemStackCreator.getStack("§aCrafting Table", Material.CRAFTING_TABLE, 1, - "§7Opens the crafting grid.", - " ", - "§eClick to open!" + "§7Opens the crafting grid.", + " ", + "§eClick to open!" ), (click, c) -> c.push(new GUICrafting())); layout.slot(47, (s, c) -> ItemStackCreator.getStackHead("§bFast Travel", "f151cffdaf303673531a7651b36637cad912ba485643158e548d59b2ead5011", 1, - "§7Teleport to islands you've already", - "§7visited.", - " ", - "§8Right-click to warp home!", - "§eClick to pick location!" + "§7Teleport to islands you've already", + "§7visited.", + " ", + "§8Right-click to warp home!", + "§eClick to pick location!" ), (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); if (click.click() instanceof Click.Right) { @@ -213,29 +218,29 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(48, (s, c) -> { HypixelPlayer player = c.player(); return ItemStackCreator.getStack("§aProfile Management", Material.NAME_TAG, 1, - "§7You can have multiple SkyBlock", - "§7profiles at the same time.", - " ", - "§7Each profile has its own island,", - "§7inventory, quest log...", - " ", - "§7Profiles: §e" + ((SkyBlockPlayer) player).getProfiles().getProfiles().size() + "§6/§e4", - " ", - "§eClick to manage!" + "§7You can have multiple SkyBlock", + "§7profiles at the same time.", + " ", + "§7Each profile has its own island,", + "§7inventory, quest log...", + " ", + "§7Profiles: §e" + ((SkyBlockPlayer) player).getProfiles().getProfiles().size() + "§6/§e4", + " ", + "§eClick to manage!" ); }, (click, c) -> c.push(new GUIProfileManagement())); } - private static @NonNull List getCalendarLore() { + private static @NonNull List getCalendarLore(ViewContext ctx) { List currentEvents = SkyBlockCalendar.getCurrentEvents(); boolean multipleEvents = currentEvents.size() > 1; List lore = new ArrayList<>(List.of("§7View the SkyBlock Calendar, upcoming", - "§7events, and event rewards!", - " ", - "§7Date: §a" + StringUtility.ntify(SkyBlockCalendar.getDay()) + " " + SkyBlockCalendar.getMonthName() + " " + SkyBlockCalendar.getYear(), - "")); - if(multipleEvents) { + "§7events, and event rewards!", + " ", + "§7Date: §a" + StringUtility.ntify(SkyBlockCalendar.getDay()) + " " + SkyBlockCalendar.getMonthName() + " " + SkyBlockCalendar.getYear(), + "")); + if (multipleEvents) { lore.add("§7Current events: "); for (CalendarEvent event : currentEvents) { lore.add(event.getDisplayName(SkyBlockCalendar.getYear())); @@ -251,7 +256,13 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont lore.add(" "); - Map upcomingEvents = SkyBlockCalendar.getEventsWithDurationUntil(1); + Map upcomingEvents; + if (ctx.player().getToggles().get(DatapointToggles.Toggles.ToggleType.HAS_VISITED_DARK_AUCTION)) { + upcomingEvents = SkyBlockCalendar.getEventsWithDurationUntil(1); + } else { + upcomingEvents = SkyBlockCalendar.getEventsWithDurationUntilSkipSpecific(1, Collections.singletonList(CalendarEvent.DARK_AUCTION)); + } + if (!upcomingEvents.isEmpty()) { Map.Entry entry = upcomingEvents.entrySet().iterator().next(); SkyBlockCalendar.EventInfo info = entry.getKey(); @@ -264,26 +275,26 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } lore.addAll( - List.of( - " ", - "§8Also accessible via /calendar", - " ", - "§eClick to view!" - ) + List.of( + " ", + "§8Also accessible via /calendar", + " ", + "§eClick to view!" + ) ); return lore; } - private static long getTicksRemaining(CalendarEvent currentEvent) { - long currentElapsedInYear = SkyBlockCalendar.getElapsed() % SkyBlockCalendar.YEAR; - long eventEndTime = 0; - for (Long eventStartTime : currentEvent.times()) { - if (currentElapsedInYear >= eventStartTime && currentElapsedInYear < eventStartTime + currentEvent.duration().toMillis() / 50) { - eventEndTime = eventStartTime + currentEvent.duration().toMillis() / 50; - break; - } - } - return eventEndTime - currentElapsedInYear; - } + private static long getTicksRemaining(CalendarEvent currentEvent) { + long currentElapsedInYear = SkyBlockCalendar.getElapsed() % SkyBlockCalendar.YEAR; + long eventEndTime = 0; + for (Long eventStartTime : currentEvent.times()) { + if (currentElapsedInYear >= eventStartTime && currentElapsedInYear < eventStartTime + currentEvent.duration().toMillis() / 50) { + eventEndTime = eventStartTime + currentEvent.duration().toMillis() / 50; + break; + } + } + return eventEndTime - currentElapsedInYear; + } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/calendar/GUICalendar.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/calendar/GUICalendar.java index 264e8a05b..49a31c41d 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/calendar/GUICalendar.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/calendar/GUICalendar.java @@ -14,6 +14,7 @@ import net.swofty.type.skyblockgeneric.calendar.CalendarEvent; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -35,39 +36,51 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.close(layout, 40); Components.back(layout, 39, ctx); - Map events; + boolean includeDarkAuction = ctx.player().getToggles().get(DatapointToggles.Toggles.ToggleType.HAS_VISITED_DARK_AUCTION); - if (ctx.player().getToggles().get(DatapointToggles.Toggles.ToggleType.HAS_VISITED_DARK_AUCTION)) { - events = SkyBlockCalendar.getEventsWithDurationUntil(14); - } else { - events = SkyBlockCalendar.getEventsWithDurationUntilSkipSpecific(14, Collections.singletonList(CalendarEvent.DARK_AUCTION)); - } + Map initialEvents = includeDarkAuction + ? SkyBlockCalendar.getEventsWithDurationUntil(14) + : SkyBlockCalendar.getEventsWithDurationUntilSkipSpecific(14, Collections.singletonList(CalendarEvent.DARK_AUCTION)); + List orderedEvents = new ArrayList<>(initialEvents.values()); + + for (int i = 0; i < Math.min(orderedEvents.size(), EVENT_SLOTS.length); i++) { + final CalendarEvent event = orderedEvents.get(i); + final int slot = EVENT_SLOTS[i]; + + layout.autoUpdating(slot, (_, _) -> { + Map freshEvents = includeDarkAuction + ? SkyBlockCalendar.getEventsWithDurationUntil(14) + : SkyBlockCalendar.getEventsWithDurationUntilSkipSpecific(14, Collections.singletonList(CalendarEvent.DARK_AUCTION)); - int index = 0; - for (Map.Entry entry : events.entrySet()) { - if (index >= EVENT_SLOTS.length) break; - SkyBlockCalendar.EventInfo info = entry.getKey(); - CalendarEvent event = entry.getValue(); - int slot = EVENT_SLOTS[index]; + SkyBlockCalendar.EventInfo freshInfo = freshEvents.entrySet().stream() + .filter(e -> e.getValue() == event) + .map(Map.Entry::getKey) + .findFirst() + .orElse(null); - layout.slot(slot, (_, _) -> { - List loreHeader = new ArrayList<>(List.of(Component.text("§7Starts in: §e" + StringUtility.formatTimeLeft(info.timeUntilBegin() * 50L)))); - if (!info.duration().isZero()) { - loreHeader.add(Component.text("§7Event lasts for §e" + StringUtility.formatTimeLeft(info.duration().toMillis()) + "§7!")); + if (freshInfo == null) { + return event.representation().builder() + .set(DataComponents.CUSTOM_NAME, Component.text(event.getDisplayName(0))) + .set(DataComponents.LORE, List.of()); } - loreHeader.add(Component.text(" ")); - List loreFooter = event.description().stream() - .map(line -> (Component) Component.text(line)) - .toList(); + List loreHeader = new ArrayList<>(List.of( + Component.text("§7Starts in: §e" + StringUtility.formatTimeLeft(freshInfo.timeUntilBegin() * 50L)) + )); + if (!freshInfo.duration().isZero()) { + loreHeader.add(Component.text("§7Event lasts for §e" + StringUtility.formatTimeLeft(freshInfo.duration().toMillis()) + "§7!")); + } + loreHeader.add(Component.text(" ")); - List lore = Stream.concat(loreHeader.stream(), loreFooter.stream()).toList(); + List lore = Stream.concat( + loreHeader.stream(), + event.description().stream().map(line -> (Component) Component.text(line)) + ).toList(); return event.representation().builder() - .set(DataComponents.CUSTOM_NAME, Component.text(event.getDisplayName(info.year()))) + .set(DataComponents.CUSTOM_NAME, Component.text(event.getDisplayName(freshInfo.year()))) .set(DataComponents.LORE, lore); - }); - index++; + }, Duration.ofSeconds(1)); } } -} +} \ No newline at end of file From ed87bc736bff6c2f3f60554c716bcec47ca7758b Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Thu, 26 Feb 2026 22:21:12 +0200 Subject: [PATCH 08/17] fix: move Swofty out of the wall --- .../src/main/java/net/swofty/type/hub/npcs/NPCSwofty.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCSwofty.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCSwofty.java index e01586e3f..8def31a27 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCSwofty.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCSwofty.java @@ -29,7 +29,7 @@ public String texture(HypixelPlayer player) { @Override public Pos position(HypixelPlayer player) { - return new Pos(-34.5, 70, -5.5, 180, 0); + return new Pos(0.5, 79, 20.5, 180, 0); } @Override @@ -50,7 +50,7 @@ public DialogueSet[] dialogues(HypixelPlayer player) { return Stream.of( DialogueSet.builder() .key("hello").lines(new String[]{ - "Make sure to check out our discord server at discord.gg/paper!", + "Make sure to check out our discord server at https://discord.swofty.net/!", "Feel free to create a pull request to help us :)" }).build() ).toArray(DialogueSet[]::new); From 489e32eda641f4f26065ad996bcf90387957fb83 Mon Sep 17 00:00:00 2001 From: Swofty Date: Fri, 27 Feb 2026 11:10:03 +1100 Subject: [PATCH 09/17] feat(i18n): add locale-aware infrastructure for per-player translations Add I18n.lore/dialogueLines locale overloads, HypixelPlayer.sendTranslated(), TranslatableItemStackCreator, ViewConfiguration.translatable(), and locale-aware HypixelNPC.DialogueSet.ofTranslation overloads. --- .../type/generic/entity/npc/HypixelNPC.java | 22 ++++++++ .../TranslatableItemStackCreator.java | 54 +++++++++++++++++++ .../generic/gui/v2/ViewConfiguration.java | 5 ++ .../net/swofty/type/generic/i18n/I18n.java | 13 +++++ .../type/generic/user/HypixelPlayer.java | 10 ++++ 5 files changed, 104 insertions(+) create mode 100644 type.generic/src/main/java/net/swofty/type/generic/gui/inventory/TranslatableItemStackCreator.java diff --git a/type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java b/type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java index ef1ffbae1..b4fdea495 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java +++ b/type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java @@ -18,10 +18,12 @@ import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; +import org.jetbrains.annotations.Nullable; import org.tinylog.Logger; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Random; import java.util.UUID; @@ -285,5 +287,25 @@ public static DialogueSet ofTranslation(String key, String translationKey, Map placeholders, Sound sound) { return new DialogueSet(key, I18n.dialogueLines(translationKey, placeholders), sound); } + + public static DialogueSet ofTranslation(String key, String translationKey, @Nullable HypixelPlayer player) { + Locale locale = player != null ? player.getLocale() : Locale.US; + return new DialogueSet(key, I18n.dialogueLines(translationKey, locale), null); + } + + public static DialogueSet ofTranslation(String key, String translationKey, @Nullable HypixelPlayer player, Sound sound) { + Locale locale = player != null ? player.getLocale() : Locale.US; + return new DialogueSet(key, I18n.dialogueLines(translationKey, locale), sound); + } + + public static DialogueSet ofTranslation(String key, String translationKey, @Nullable HypixelPlayer player, Map placeholders) { + Locale locale = player != null ? player.getLocale() : Locale.US; + return new DialogueSet(key, I18n.dialogueLines(translationKey, locale, placeholders), null); + } + + public static DialogueSet ofTranslation(String key, String translationKey, @Nullable HypixelPlayer player, Map placeholders, Sound sound) { + Locale locale = player != null ? player.getLocale() : Locale.US; + return new DialogueSet(key, I18n.dialogueLines(translationKey, locale, placeholders), sound); + } } } diff --git a/type.generic/src/main/java/net/swofty/type/generic/gui/inventory/TranslatableItemStackCreator.java b/type.generic/src/main/java/net/swofty/type/generic/gui/inventory/TranslatableItemStackCreator.java new file mode 100644 index 000000000..b70cb6669 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/gui/inventory/TranslatableItemStackCreator.java @@ -0,0 +1,54 @@ +package net.swofty.type.generic.gui.inventory; + +import net.minestom.server.entity.PlayerSkin; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.type.generic.i18n.I18n; +import net.swofty.type.generic.user.HypixelPlayer; + +import java.util.List; +import java.util.Locale; +import java.util.Map; + +public class TranslatableItemStackCreator { + + public static ItemStack.Builder getStack(HypixelPlayer p, String nameKey, Material mat, int amt, String loreKey) { + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string(nameKey, l), mat, amt, I18n.lore(loreKey, l)); + } + + public static ItemStack.Builder getStack(HypixelPlayer p, String nameKey, Material mat, int amt, String loreKey, Map ph) { + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string(nameKey, l), mat, amt, I18n.lore(loreKey, l, ph)); + } + + public static ItemStack.Builder getStack(HypixelPlayer p, String nameKey, Material mat, int amt, List lore) { + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string(nameKey, l), mat, amt, lore); + } + + public static ItemStack.Builder getStack(HypixelPlayer p, String nameKey, Material mat, int amt) { + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string(nameKey, l), mat, amt); + } + + public static ItemStack.Builder getStackHead(HypixelPlayer p, String nameKey, String texture, int amt, String loreKey) { + Locale l = p.getLocale(); + return ItemStackCreator.getStackHead(I18n.string(nameKey, l), texture, amt, I18n.lore(loreKey, l)); + } + + public static ItemStack.Builder getStackHead(HypixelPlayer p, String nameKey, String texture, int amt, String loreKey, Map ph) { + Locale l = p.getLocale(); + return ItemStackCreator.getStackHead(I18n.string(nameKey, l), texture, amt, I18n.lore(loreKey, l, ph)); + } + + public static ItemStack.Builder getStackHead(HypixelPlayer p, String nameKey, String texture, int amt, List lore) { + Locale l = p.getLocale(); + return ItemStackCreator.getStackHead(I18n.string(nameKey, l), texture, amt, lore); + } + + public static ItemStack.Builder getStackHead(HypixelPlayer p, String nameKey, PlayerSkin skin, int amt, List lore) { + Locale l = p.getLocale(); + return ItemStackCreator.getStackHead(I18n.string(nameKey, l), skin, amt, lore); + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/gui/v2/ViewConfiguration.java b/type.generic/src/main/java/net/swofty/type/generic/gui/v2/ViewConfiguration.java index 78937ec4e..dd5b50959 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/gui/v2/ViewConfiguration.java +++ b/type.generic/src/main/java/net/swofty/type/generic/gui/v2/ViewConfiguration.java @@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component; import net.minestom.server.inventory.InventoryType; import net.swofty.type.generic.gui.v2.context.ViewContext; +import net.swofty.type.generic.i18n.I18n; import java.util.function.BiFunction; @@ -41,6 +42,10 @@ public static ViewConfiguration withString(StringTitle title, Inventor return new ViewConfiguration<>(title, type); } + public static ViewConfiguration translatable(String titleKey, InventoryType type) { + return new ViewConfiguration<>((StringTitle) (s, ctx) -> I18n.string(titleKey, ctx.player().getLocale()), type); + } + @FunctionalInterface public interface Title { Component getTitle(S state, ViewContext ctx); diff --git a/type.generic/src/main/java/net/swofty/type/generic/i18n/I18n.java b/type.generic/src/main/java/net/swofty/type/generic/i18n/I18n.java index ff04a5d16..aa30d3b7e 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/i18n/I18n.java +++ b/type.generic/src/main/java/net/swofty/type/generic/i18n/I18n.java @@ -68,10 +68,18 @@ public static List lore(String key) { return List.of(string(key).split("\n")); } + public static List lore(String key, Locale locale) { + return List.of(string(key, locale).split("\n")); + } + public static List lore(String key, Map placeholders) { return List.of(string(key, placeholders).split("\n")); } + public static List lore(String key, Locale locale, Map placeholders) { + return List.of(string(key, locale, placeholders).split("\n")); + } + public static String[] dialogueLines(String key) { return dialogueLines(key, HypixelTranslator.defaultLocale); } @@ -85,4 +93,9 @@ public static String[] dialogueLines(String key, Map placeholder String resolved = string(key, placeholders); return resolved.split(DIALOGUE_SEPARATOR); } + + public static String[] dialogueLines(String key, Locale locale, Map placeholders) { + String resolved = string(key, locale, placeholders); + return resolved.split(DIALOGUE_SEPARATOR); + } } diff --git a/type.generic/src/main/java/net/swofty/type/generic/user/HypixelPlayer.java b/type.generic/src/main/java/net/swofty/type/generic/user/HypixelPlayer.java index 29d1b14be..675f7d2c5 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/user/HypixelPlayer.java +++ b/type.generic/src/main/java/net/swofty/type/generic/user/HypixelPlayer.java @@ -20,11 +20,13 @@ import net.swofty.type.generic.achievement.PlayerAchievementHandler; import net.swofty.type.generic.experience.PlayerExperienceHandler; import net.swofty.type.generic.gui.v2.*; +import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.quest.PlayerQuestHandler; import net.swofty.type.generic.user.categories.Rank; import org.jetbrains.annotations.NotNull; import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -141,6 +143,14 @@ public PlayerQuestHandler getQuestHandler() { return new PlayerQuestHandler(this); } + public void sendTranslated(String key) { + sendMessage(Component.text(I18n.string(key, getLocale()))); + } + + public void sendTranslated(String key, Map placeholders) { + sendMessage(Component.text(I18n.string(key, getLocale(), placeholders))); + } + public PlayerSkin getPlayerSkin() { String texture = getDataHandler().get(HypixelDataHandler.Data.SKIN_TEXTURE, DatapointString.class).getValue(); String signature = getDataHandler().get(HypixelDataHandler.Data.SKIN_SIGNATURE, DatapointString.class).getValue(); From 28190f574931a9a5995a9c50be0fa60de10e5df4 Mon Sep 17 00:00:00 2001 From: Swofty Date: Fri, 27 Feb 2026 11:10:24 +1100 Subject: [PATCH 10/17] feat(i18n): migrate all callsites to use per-player locale Update ~110 files across GUIs, commands, scoreboards, tab modules, and NPCs to resolve translations using the player's client locale instead of the hardcoded default (Locale.US). --- .../tab/BackwaterBayouServerModule.java | 8 +- .../bedwarsgame/BedWarsGameScoreboard.java | 30 ++--- .../bedwarslobby/BedWarsLobbyScoreboard.java | 34 +++--- .../tab/BedWarsPlayersOnlineModule.java | 4 +- .../tab/CrimsonIsleServerModule.java | 8 +- .../tab/DeepCavernsServerModule.java | 8 +- .../dungeonhub/tab/DungeonServerModule.java | 8 +- .../tab/DwarvenMinesServerModule.java | 8 +- .../type/galatea/tab/GalateaServerModule.java | 8 +- .../generic/command/commands/BanCommand.java | 21 ++-- .../command/commands/FriendCommand.java | 39 ++++--- .../command/commands/MessageCommand.java | 6 +- .../generic/command/commands/MuteCommand.java | 17 ++- .../command/commands/PartyCommand.java | 65 ++++++----- .../goldmine/tab/GoldMineServerModule.java | 8 +- .../subguis/GUIBitsSubCategorys.java | 4 +- .../swofty/type/hub/npcs/NPCAdventurer.java | 3 +- .../swofty/type/hub/npcs/NPCAlchemist.java | 3 +- .../net/swofty/type/hub/npcs/NPCArthur.java | 15 ++- .../type/hub/npcs/NPCAuctionMaster.java | 3 +- .../net/swofty/type/hub/npcs/NPCBaker.java | 4 +- .../net/swofty/type/hub/npcs/NPCBanker.java | 3 +- .../swofty/type/hub/npcs/NPCBartender.java | 7 +- .../swofty/type/hub/npcs/NPCFarmerRigby.java | 5 +- .../swofty/type/hub/tab/HubServerModule.java | 8 +- .../type/island/tab/IslandGuestsModule.java | 4 +- .../type/island/tab/IslandMemberModule.java | 4 +- .../type/island/tab/IslandServerModule.java | 19 ++-- .../tab/JerrysWorkshopServerModule.java | 8 +- .../MurderMysteryGameScoreboard.java | 88 ++++++++------- .../MurderMysteryLobbyScoreboard.java | 24 ++-- .../tab/MurderMysteryPlayersOnlineModule.java | 4 +- .../PrototypeLobbyScoreboard.java | 26 +++-- .../gui/inventories/GUIAnvil.java | 49 ++++---- .../gui/inventories/GUIBoosterCookie.java | 9 +- .../gui/inventories/GUIBrewingStand.java | 15 ++- .../gui/inventories/GUIConsumeSoulflow.java | 14 ++- .../gui/inventories/GUICreative.java | 21 ++-- .../gui/inventories/GUIEnchantmentTable.java | 74 ++++++------ .../gui/inventories/GUIMinion.java | 28 ++--- .../gui/inventories/GUIReforge.java | 32 +++--- .../gui/inventories/GUIViewPlayerProfile.java | 64 ++++++----- .../gui/inventories/abiphone/GUIAbiphone.java | 29 +++-- .../abiphone/GUIConfirmAbiphone.java | 9 +- .../abiphone/GUIContactManagement.java | 9 +- .../auction/GUIAuctionBrowser.java | 35 +++--- .../auction/GUIAuctionCreateItem.java | 81 ++++++++------ .../auction/GUIAuctionDuration.java | 28 +++-- .../inventories/auction/GUIAuctionHouse.java | 27 ++--- .../auction/GUIAuctionHouseStats.java | 13 ++- .../auction/GUIAuctionViewItem.java | 2 +- .../auction/GUIManageAuctions.java | 7 +- .../gui/inventories/auction/GUIViewBids.java | 2 +- .../auction/view/AuctionViewSelfBIN.java | 36 +++--- .../auction/view/AuctionViewSelfNormal.java | 37 +++--- .../auction/view/AuctionViewThirdBin.java | 55 +++++---- .../auction/view/AuctionViewThirdNormal.java | 102 +++++++++-------- .../gui/inventories/banker/GUIBanker.java | 43 ++++--- .../inventories/banker/GUIBankerDeposit.java | 55 +++++---- .../inventories/banker/GUIBankerWithdraw.java | 70 ++++++------ .../gui/inventories/bazaar/GUIBazaar.java | 28 ++--- .../gui/inventories/bazaar/GUIBazaarItem.java | 96 ++++++++-------- .../inventories/bazaar/GUIBazaarItemSet.java | 38 ++++--- .../GUIBazaarOrderCompletedOptions.java | 60 +++++----- .../bazaar/GUIBazaarOrderOptions.java | 105 ++++++++++-------- .../inventories/bazaar/GUIBazaarOrders.java | 60 +++++----- .../GUIBazaarOrderAmountSelection.java | 35 +++--- .../selections/GUIBazaarPriceSelection.java | 66 +++++------ .../gui/inventories/builder/GUIBuilder.java | 21 ++-- .../inventories/coop/GUICoopInviteSender.java | 25 +++-- .../inventories/coop/GUICoopInviteTarget.java | 27 +++-- .../museum/GUIMuseumArmorCategory.java | 48 ++++---- .../inventories/museum/GUIMuseumCategory.java | 42 +++---- .../museum/GUIMuseumEmptyDisplay.java | 37 +++--- .../museum/GUIMuseumNonEmptyDisplay.java | 26 +++-- .../gui/inventories/museum/GUIYourMuseum.java | 28 +++-- .../gui/inventories/rusty/GUIRusty.java | 31 ++---- .../inventories/rusty/GUIRustySubMenu.java | 29 +++-- .../gui/inventories/sbmenu/GUICrafting.java | 11 +- .../gui/inventories/sbmenu/GUIPets.java | 36 +++--- .../inventories/sbmenu/GUISkyBlockMenu.java | 78 +++++++------ .../sbmenu/GUISkyBlockProfile.java | 31 +++--- .../sbmenu/bags/GUIAccessoryBag.java | 13 ++- .../inventories/sbmenu/bags/GUIQuiver.java | 9 +- .../gui/inventories/sbmenu/bags/GUISack.java | 15 ++- .../sbmenu/bags/GUISackOfSacks.java | 13 ++- .../inventories/sbmenu/bags/GUIYourBags.java | 45 ++++---- .../sbmenu/levels/GUILevelsGuide.java | 13 ++- .../sbmenu/levels/GUISkyBlockLevel.java | 4 +- .../sbmenu/levels/GUISkyBlockLevels.java | 58 +++++----- .../levels/rewards/GUILevelRewards.java | 47 ++++---- .../sbmenu/profiles/GUIProfileCreate.java | 9 +- .../sbmenu/profiles/GUIProfileManagement.java | 27 +++-- .../sbmenu/profiles/GUIProfileSelect.java | 20 ++-- .../sbmenu/profiles/GUIProfileSelectMode.java | 13 ++- .../sbmenu/questlog/GUIFairySoulsGuide.java | 19 ++-- .../sbmenu/questlog/GUIMissionLog.java | 32 ++++-- .../sbmenu/recipe/GUIMinionRecipes.java | 3 +- .../inventories/sbmenu/recipe/GUIRecipe.java | 27 +++-- .../sbmenu/recipe/GUIRecipeBook.java | 25 +++-- .../sbmenu/recipe/GUIRecipeCategory.java | 15 ++- .../sbmenu/recipe/GUIRecipeSlayers.java | 13 ++- .../sbmenu/recipe/GUISearchRecipe.java | 26 +++-- .../sbmenu/skills/GUISkillCategory.java | 32 ++++-- .../inventories/sbmenu/skills/GUISkills.java | 17 ++- .../sbmenu/storage/GUIStorage.java | 54 +++++---- .../storage/GUIStorageBackpackPage.java | 15 ++- .../storage/GUIStorageIconSelection.java | 7 +- .../sbmenu/storage/GUIStoragePage.java | 17 +-- .../gui/inventories/shop/ConfirmBuyView.java | 18 +-- .../inventories/shop/TradingOptionsView.java | 18 +-- .../gui/inventories/stash/GUIStashItem.java | 31 +++--- .../inventories/stash/GUIStashMaterial.java | 45 ++++---- .../type/skyblockgeneric/item/ItemLore.java | 34 +++--- .../tabmodules/AccountInformationModule.java | 22 ++-- .../SkyBlockPlayersOnlineModule.java | 4 +- .../user/SkyBlockScoreboard.java | 30 ++--- .../skywarsgame/SkywarsGameScoreboard.java | 52 ++++----- .../skywarslobby/SkywarsLobbyScoreboard.java | 30 ++--- .../tab/SpidersDenServerModule.java | 8 +- .../type/theend/tab/TheEndServerModule.java | 8 +- .../tab/TheFarmingIslandsServerModule.java | 8 +- .../type/thepark/tab/TheParkServerModule.java | 8 +- 123 files changed, 1810 insertions(+), 1502 deletions(-) diff --git a/type.backwaterbayou/src/main/java/net/swofty/type/backwaterbayou/tab/BackwaterBayouServerModule.java b/type.backwaterbayou/src/main/java/net/swofty/type/backwaterbayou/tab/BackwaterBayouServerModule.java index 56fe73dbb..2e8cb45f3 100644 --- a/type.backwaterbayou/src/main/java/net/swofty/type/backwaterbayou/tab/BackwaterBayouServerModule.java +++ b/type.backwaterbayou/src/main/java/net/swofty/type/backwaterbayou/tab/BackwaterBayouServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class BackwaterBayouServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.backwater_bayou"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.backwater_bayou", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameScoreboard.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameScoreboard.java index 902e83e69..c0ac6d288 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameScoreboard.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameScoreboard.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Map; public class BedWarsGameScoreboard { @@ -40,6 +41,7 @@ public static void start(Game game) { if (player.joined - System.currentTimeMillis() > 5000) { continue; } + Locale l = player.getLocale(); HypixelDataHandler dataHandler = player.getDataHandler(); BedWarsDataHandler bwDataHandler = BedWarsDataHandler.getUser(player); @@ -48,17 +50,17 @@ public static void start(Game game) { } List lines = new ArrayList<>(); - lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format")).format(new Date()) + " §8" + HypixelConst.getServerName()); + lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); if (game.getGameStatus() == GameStatus.WAITING) { - lines.add(I18n.string("scoreboard.bedwars_game.map_label") + game.getMapEntry().getName()); - lines.add(I18n.string("scoreboard.bedwars_game.players_label") + game.getPlayers().size() + "/" + game.getMapEntry().getConfiguration().getTeams().size()); + lines.add(I18n.string("scoreboard.bedwars_game.map_label", l) + game.getMapEntry().getName()); + lines.add(I18n.string("scoreboard.bedwars_game.players_label", l) + game.getPlayers().size() + "/" + game.getMapEntry().getConfiguration().getTeams().size()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.bedwars_game.starting_in_label") + game.getCountdown().getRemainingSeconds() + I18n.string("scoreboard.bedwars_game.starting_in_suffix")); + lines.add(I18n.string("scoreboard.bedwars_game.starting_in_label", l) + game.getCountdown().getRemainingSeconds() + I18n.string("scoreboard.bedwars_game.starting_in_suffix", l)); lines.add("§7 "); - lines.add(I18n.string("scoreboard.bedwars_game.mode_label") + game.getBedwarsGameType().getDisplayName()); - lines.add(I18n.string("scoreboard.bedwars_game.version_label")); + lines.add(I18n.string("scoreboard.bedwars_game.mode_label", l) + game.getBedwarsGameType().getDisplayName()); + lines.add(I18n.string("scoreboard.bedwars_game.version_label", l)); } else { String eventName = game.getEventManager().getNextEvent() != null ? game.getEventManager().getNextEvent().getDisplayName() @@ -67,7 +69,7 @@ public static void start(Game game) { long minutesPart = seconds / 60; long secondsPart = seconds % 60; String timeLeft = String.format("%d:%02d", minutesPart, secondsPart); - lines.add(I18n.string("scoreboard.bedwars_game.event_in_label", Map.of("event_name", eventName, "time_left", timeLeft))); + lines.add(I18n.string("scoreboard.bedwars_game.event_in_label", l, Map.of("event_name", eventName, "time_left", timeLeft))); lines.add("§7 "); for (Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { TeamKey teamKey = entry.getKey(); @@ -75,20 +77,20 @@ public static void start(Game game) { String teamInitial = teamName.substring(0, 1).toUpperCase(); String bedStatus = game.getTeamManager().isBedAlive(teamKey) - ? I18n.string("scoreboard.bedwars_game.bed_alive") - : I18n.string("scoreboard.bedwars_game.bed_dead"); + ? I18n.string("scoreboard.bedwars_game.bed_alive", l) + : I18n.string("scoreboard.bedwars_game.bed_dead", l); lines.add(String.format("%s%s §f%s %s", teamKey.chatColor(), teamInitial, teamName, bedStatus)); } } lines.add("§7 "); - lines.add(I18n.string("scoreboard.common.footer")); + lines.add(I18n.string("scoreboard.common.footer", l)); if (!scoreboard.hasScoreboard(player)) { - scoreboard.createScoreboard(player, getSidebarName(prototypeName)); + scoreboard.createScoreboard(player, getSidebarName(prototypeName, l)); } scoreboard.updateLines(player, lines); - scoreboard.updateTitle(player, getSidebarName(prototypeName)); + scoreboard.updateTitle(player, getSidebarName(prototypeName, l)); } return TaskSchedule.tick(4); }); @@ -98,8 +100,8 @@ public static void removeCache(Player player) { scoreboard.removeScoreboard(player); } - private static String getSidebarName(int counter) { - String baseText = I18n.string("scoreboard.bedwars_game.title_base"); + private static String getSidebarName(int counter, Locale locale) { + String baseText = I18n.string("scoreboard.bedwars_game.title_base", locale); String[] colors = {"§f§l", "§6§l", "§e§l"}; String endColor = "§a§l"; diff --git a/type.bedwarslobby/src/main/java/net/swofty/type/bedwarslobby/BedWarsLobbyScoreboard.java b/type.bedwarslobby/src/main/java/net/swofty/type/bedwarslobby/BedWarsLobbyScoreboard.java index d19d50e37..39e5931fd 100644 --- a/type.bedwarslobby/src/main/java/net/swofty/type/bedwarslobby/BedWarsLobbyScoreboard.java +++ b/type.bedwarslobby/src/main/java/net/swofty/type/bedwarslobby/BedWarsLobbyScoreboard.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import static net.swofty.commons.bedwars.BedwarsLevelUtil.suffix; @@ -36,6 +37,7 @@ public static void start() { } for (HypixelPlayer player : HypixelGenericLoader.getLoadedPlayers()) { + Locale l = player.getLocale(); HypixelDataHandler dataHandler = player.getDataHandler(); BedWarsDataHandler bwDataHandler = BedWarsDataHandler.getUser(player); @@ -49,41 +51,41 @@ public static void start() { double percentage = Math.min(1.0, (double) progress / maxExperience); int filledSquares = (int) Math.round(percentage * 10); - StringBuilder progressBar = new StringBuilder(" " + I18n.string("scoreboard.bedwars_lobby.progress_bar_open")); + StringBuilder progressBar = new StringBuilder(" " + I18n.string("scoreboard.bedwars_lobby.progress_bar_open", l)); for (int i = 0; i < 10; i++) { if (i < filledSquares) { - progressBar.append(I18n.string("scoreboard.bedwars_lobby.progress_bar_filled")); + progressBar.append(I18n.string("scoreboard.bedwars_lobby.progress_bar_filled", l)); } else { - progressBar.append(I18n.string("scoreboard.bedwars_lobby.progress_bar_empty")); + progressBar.append(I18n.string("scoreboard.bedwars_lobby.progress_bar_empty", l)); } } - progressBar.append(I18n.string("scoreboard.bedwars_lobby.progress_bar_close")); + progressBar.append(I18n.string("scoreboard.bedwars_lobby.progress_bar_close", l)); long tokens = bwDataHandler.get(BedWarsDataHandler.Data.TOKENS, DatapointLeaderboardLong.class).getValue(); long tickets = bwDataHandler.get(BedWarsDataHandler.Data.SLUMBER_TICKETS, DatapointLeaderboardLong.class).getValue(); List lines = new ArrayList<>(); - lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format")).format(new Date()) + " §8" + HypixelConst.getServerName()); + lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.bedwars_lobby.level_label") + BedwarsLevelColor.constructLevelString(BedwarsLevelUtil.calculateLevel(experience))); + lines.add(I18n.string("scoreboard.bedwars_lobby.level_label", l) + BedwarsLevelColor.constructLevelString(BedwarsLevelUtil.calculateLevel(experience))); lines.add("§7 "); - lines.add(I18n.string("scoreboard.bedwars_lobby.progress_label") + suffix(progress) + I18n.string("scoreboard.bedwars_lobby.progress_separator") + suffix(maxExperience)); + lines.add(I18n.string("scoreboard.bedwars_lobby.progress_label", l) + suffix(progress) + I18n.string("scoreboard.bedwars_lobby.progress_separator", l) + suffix(maxExperience)); lines.add(progressBar.toString()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.bedwars_lobby.tokens_label") + tokens); - lines.add(I18n.string("scoreboard.bedwars_lobby.tickets_label") + tickets + I18n.string("scoreboard.bedwars_lobby.tickets_max")); + lines.add(I18n.string("scoreboard.bedwars_lobby.tokens_label", l) + tokens); + lines.add(I18n.string("scoreboard.bedwars_lobby.tickets_label", l) + tickets + I18n.string("scoreboard.bedwars_lobby.tickets_max", l)); lines.add("§7 "); - lines.add(I18n.string("scoreboard.bedwars_lobby.total_kills_label")); - lines.add(I18n.string("scoreboard.bedwars_lobby.total_wins_label")); + lines.add(I18n.string("scoreboard.bedwars_lobby.total_kills_label", l)); + lines.add(I18n.string("scoreboard.bedwars_lobby.total_wins_label", l)); lines.add("§7 "); - lines.add(I18n.string("scoreboard.common.footer")); + lines.add(I18n.string("scoreboard.common.footer", l)); if (!scoreboard.hasScoreboard(player)) { - scoreboard.createScoreboard(player, getSidebarName(prototypeName)); + scoreboard.createScoreboard(player, getSidebarName(prototypeName, l)); } scoreboard.updateLines(player, lines); - scoreboard.updateTitle(player, getSidebarName(prototypeName)); + scoreboard.updateTitle(player, getSidebarName(prototypeName, l)); } return TaskSchedule.tick(4); }); @@ -93,8 +95,8 @@ public static void removeCache(Player player) { scoreboard.removeScoreboard(player); } - private static String getSidebarName(int counter) { - String baseText = I18n.string("scoreboard.bedwars_lobby.title_base"); + private static String getSidebarName(int counter, Locale locale) { + String baseText = I18n.string("scoreboard.bedwars_lobby.title_base", locale); String[] colors = {"§f§l", "§6§l", "§e§l"}; String endColor = "§a§l"; diff --git a/type.bedwarslobby/src/main/java/net/swofty/type/bedwarslobby/tab/BedWarsPlayersOnlineModule.java b/type.bedwarslobby/src/main/java/net/swofty/type/bedwarslobby/tab/BedWarsPlayersOnlineModule.java index d5c682476..4c7fb2f14 100644 --- a/type.bedwarslobby/src/main/java/net/swofty/type/bedwarslobby/tab/BedWarsPlayersOnlineModule.java +++ b/type.bedwarslobby/src/main/java/net/swofty/type/bedwarslobby/tab/BedWarsPlayersOnlineModule.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; public class BedWarsPlayersOnlineModule extends TablistModule { @@ -27,10 +28,11 @@ public BedWarsPlayersOnlineModule(int page) { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); List players = HypixelGenericLoader.getLoadedPlayers(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.players", Map.of("count", String.valueOf(players.size())))), TablistSkinRegistry.GREEN) + new TablistEntry(getCentered(I18n.string("tablist.module.players", l, Map.of("count", String.valueOf(players.size())))), TablistSkinRegistry.GREEN) )); List toShow = new ArrayList<>(); diff --git a/type.crimsonisle/src/main/java/net/swofty/type/crimsonisle/tab/CrimsonIsleServerModule.java b/type.crimsonisle/src/main/java/net/swofty/type/crimsonisle/tab/CrimsonIsleServerModule.java index 7c682b638..830842e3d 100644 --- a/type.crimsonisle/src/main/java/net/swofty/type/crimsonisle/tab/CrimsonIsleServerModule.java +++ b/type.crimsonisle/src/main/java/net/swofty/type/crimsonisle/tab/CrimsonIsleServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class CrimsonIsleServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.crimson_isle"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.crimson_isle", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.deepcaverns/src/main/java/net/swofty/type/deepcaverns/tab/DeepCavernsServerModule.java b/type.deepcaverns/src/main/java/net/swofty/type/deepcaverns/tab/DeepCavernsServerModule.java index f07dd0556..d5da223e0 100644 --- a/type.deepcaverns/src/main/java/net/swofty/type/deepcaverns/tab/DeepCavernsServerModule.java +++ b/type.deepcaverns/src/main/java/net/swofty/type/deepcaverns/tab/DeepCavernsServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class DeepCavernsServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.deep_caverns"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.deep_caverns", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.dungeonhub/src/main/java/net/swofty/type/dungeonhub/tab/DungeonServerModule.java b/type.dungeonhub/src/main/java/net/swofty/type/dungeonhub/tab/DungeonServerModule.java index 9a580c367..5a8363e2c 100644 --- a/type.dungeonhub/src/main/java/net/swofty/type/dungeonhub/tab/DungeonServerModule.java +++ b/type.dungeonhub/src/main/java/net/swofty/type/dungeonhub/tab/DungeonServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class DungeonServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.dungeon_hub"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.dungeon_hub", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/tab/DwarvenMinesServerModule.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/tab/DwarvenMinesServerModule.java index 6dfe6b1da..c3d571b93 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/tab/DwarvenMinesServerModule.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/tab/DwarvenMinesServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class DwarvenMinesServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.dwarven_mines"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.dwarven_mines", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.galatea/src/main/java/net/swofty/type/galatea/tab/GalateaServerModule.java b/type.galatea/src/main/java/net/swofty/type/galatea/tab/GalateaServerModule.java index 79fd2b5f5..189367eca 100644 --- a/type.galatea/src/main/java/net/swofty/type/galatea/tab/GalateaServerModule.java +++ b/type.galatea/src/main/java/net/swofty/type/galatea/tab/GalateaServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GalateaServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.galatea"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.galatea", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.generic/src/main/java/net/swofty/type/generic/command/commands/BanCommand.java b/type.generic/src/main/java/net/swofty/type/generic/command/commands/BanCommand.java index 778624aa0..8ad029924 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/command/commands/BanCommand.java +++ b/type.generic/src/main/java/net/swofty/type/generic/command/commands/BanCommand.java @@ -14,7 +14,6 @@ import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.command.CommandParameters; import net.swofty.type.generic.command.HypixelCommand; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.generic.user.categories.Rank; import org.jetbrains.annotations.Nullable; @@ -60,7 +59,7 @@ public void registerUsage(MinestomCommand command) { try { type = BanType.valueOf(context.get(reasonArg)); } catch (IllegalArgumentException e) { - player.sendMessage(I18n.string("commands.ban.invalid_reason")); + player.sendTranslated("commands.ban.invalid_reason"); return; } @@ -71,7 +70,7 @@ public void registerUsage(MinestomCommand command) { long expiryTime = System.currentTimeMillis() + actualTime; banPlayer(player, targetUuid, type, player.getUuid(), actualTime, expiryTime, playerName, null); } catch (IOException e) { - player.sendMessage(I18n.string("commands.common.player_not_found_short", Map.of("player", playerName))); + player.sendTranslated("commands.common.player_not_found_short", Map.of("player", playerName)); } }); }, playerArg, durationArg, reasonArg); @@ -84,7 +83,7 @@ public void registerUsage(MinestomCommand command) { try { reason = BanType.valueOf(context.get(reasonArg)); } catch (IllegalArgumentException e) { - player.sendMessage(I18n.string("commands.ban.invalid_reason")); + player.sendTranslated("commands.ban.invalid_reason"); return; } @@ -93,7 +92,7 @@ public void registerUsage(MinestomCommand command) { banPlayer(player, net.minestom.server.utils.mojang.MojangUtils.getUUID(playerName), reason, player.getUuid(), 0, -1, playerName, null); } catch (IOException e) { - player.sendMessage(I18n.string("commands.common.player_not_found_short", Map.of("player", playerName))); + player.sendTranslated("commands.common.player_not_found_short", Map.of("player", playerName)); } }); }, playerArg, reasonArg); @@ -106,7 +105,7 @@ public void registerUsage(MinestomCommand command) { try { reason = BanType.valueOf(context.get(reasonArg)); } catch (IllegalArgumentException e) { - player.sendMessage(I18n.string("commands.ban.invalid_reason")); + player.sendTranslated("commands.ban.invalid_reason"); return; } @@ -117,7 +116,7 @@ public void registerUsage(MinestomCommand command) { banPlayer(player, net.minestom.server.utils.mojang.MojangUtils.getUUID(playerName), reason, player.getUuid(), 0, -1, playerName, tags); } catch (IOException e) { - player.sendMessage(I18n.string("commands.common.player_not_found_short", Map.of("player", playerName))); + player.sendTranslated("commands.common.player_not_found_short", Map.of("player", playerName)); } }); }, playerArg, reasonArg, extraArg); @@ -157,15 +156,15 @@ private void banPlayer(HypixelPlayer sender, UUID targetUuid, BanType type, UUID if (result instanceof PunishPlayerProtocolObject.PunishPlayerResponse response) { if (response.success()) { new ProxyPlayer(targetUuid).transferToLimbo(); - sender.sendMessage(I18n.string("commands.ban.success", Map.of("player", playerName, "id", response.punishmentId()))); + sender.sendTranslated("commands.ban.success", Map.of("player", playerName, "id", response.punishmentId())); } else if (response.errorCode() == PunishPlayerProtocolObject.ErrorCode.ALREADY_PUNISHED) { - sender.sendMessage(I18n.string("commands.ban.already_banned", Map.of("id", response.errorMessage()))); + sender.sendTranslated("commands.ban.already_banned", Map.of("id", response.errorMessage())); } else { - sender.sendMessage(I18n.string("commands.ban.failed", Map.of("error", response.errorMessage()))); + sender.sendTranslated("commands.ban.failed", Map.of("error", response.errorMessage())); } } }).orTimeout(5, TimeUnit.SECONDS).exceptionally(_ -> { - sender.sendMessage(I18n.string("commands.ban.service_offline")); + sender.sendTranslated("commands.ban.service_offline"); return null; }); } diff --git a/type.generic/src/main/java/net/swofty/type/generic/command/commands/FriendCommand.java b/type.generic/src/main/java/net/swofty/type/generic/command/commands/FriendCommand.java index d3554cea1..4e12548c7 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/command/commands/FriendCommand.java +++ b/type.generic/src/main/java/net/swofty/type/generic/command/commands/FriendCommand.java @@ -7,7 +7,6 @@ import net.swofty.type.generic.command.CommandParameters; import net.swofty.type.generic.command.HypixelCommand; import net.swofty.type.generic.friend.FriendManager; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.generic.user.categories.Rank; @@ -48,7 +47,7 @@ public void registerUsage(MinestomCommand command) { pendingCommands.add(player.getUuid()); if (!friendService.isOnline().join()) { - sender.sendMessage(I18n.string("commands.common.service_offline_friend")); + player.sendTranslated("commands.common.service_offline_friend"); pendingCommands.remove(player.getUuid()); return; } @@ -80,7 +79,7 @@ public void registerUsage(MinestomCommand command) { pendingCommands.add(player.getUuid()); if (!friendService.isOnline().join()) { - sender.sendMessage(I18n.string("commands.common.service_offline_friend")); + player.sendTranslated("commands.common.service_offline_friend"); pendingCommands.remove(player.getUuid()); return; } @@ -106,7 +105,7 @@ public void registerUsage(MinestomCommand command) { int page = parsePageNumber(arg); FriendManager.listRequests(player, page); } - default -> player.sendMessage(I18n.string("commands.common.unknown_command_use_help", Map.of("command", "friend"))); + default -> player.sendTranslated("commands.common.unknown_command_use_help", Map.of("command", "friend")); } pendingCommands.remove(player.getUuid()); @@ -124,7 +123,7 @@ public void registerUsage(MinestomCommand command) { pendingCommands.add(player.getUuid()); if (!friendService.isOnline().join()) { - sender.sendMessage(I18n.string("commands.common.service_offline_friend")); + player.sendTranslated("commands.common.service_offline_friend"); pendingCommands.remove(player.getUuid()); return; } @@ -136,7 +135,7 @@ public void registerUsage(MinestomCommand command) { if (sub.equalsIgnoreCase("nickname")) { FriendManager.setNickname(player, target, extra); } else { - player.sendMessage(I18n.string("commands.common.unknown_command_use_help", Map.of("command", "friend"))); + player.sendTranslated("commands.common.unknown_command_use_help", Map.of("command", "friend")); } pendingCommands.remove(player.getUuid()); @@ -144,20 +143,20 @@ public void registerUsage(MinestomCommand command) { } private void showHelp(HypixelPlayer player) { - player.sendMessage(I18n.string("commands.common.separator")); - player.sendMessage(I18n.string("commands.friend.help_header")); - player.sendMessage(I18n.string("commands.friend.help_add")); - player.sendMessage(I18n.string("commands.friend.help_accept")); - player.sendMessage(I18n.string("commands.friend.help_deny")); - player.sendMessage(I18n.string("commands.friend.help_remove")); - player.sendMessage(I18n.string("commands.friend.help_removeall")); - player.sendMessage(I18n.string("commands.friend.help_best")); - player.sendMessage(I18n.string("commands.friend.help_nickname")); - player.sendMessage(I18n.string("commands.friend.help_list")); - player.sendMessage(I18n.string("commands.friend.help_requests")); - player.sendMessage(I18n.string("commands.friend.help_toggle")); - player.sendMessage(I18n.string("commands.friend.help_notifications")); - player.sendMessage(I18n.string("commands.common.separator")); + player.sendTranslated("commands.common.separator"); + player.sendTranslated("commands.friend.help_header"); + player.sendTranslated("commands.friend.help_add"); + player.sendTranslated("commands.friend.help_accept"); + player.sendTranslated("commands.friend.help_deny"); + player.sendTranslated("commands.friend.help_remove"); + player.sendTranslated("commands.friend.help_removeall"); + player.sendTranslated("commands.friend.help_best"); + player.sendTranslated("commands.friend.help_nickname"); + player.sendTranslated("commands.friend.help_list"); + player.sendTranslated("commands.friend.help_requests"); + player.sendTranslated("commands.friend.help_toggle"); + player.sendTranslated("commands.friend.help_notifications"); + player.sendTranslated("commands.common.separator"); } private int parsePageNumber(String arg) { diff --git a/type.generic/src/main/java/net/swofty/type/generic/command/commands/MessageCommand.java b/type.generic/src/main/java/net/swofty/type/generic/command/commands/MessageCommand.java index 38c7d46b1..5c9e2ca53 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/command/commands/MessageCommand.java +++ b/type.generic/src/main/java/net/swofty/type/generic/command/commands/MessageCommand.java @@ -38,19 +38,19 @@ public void registerUsage(MinestomCommand command) { @Nullable UUID targetUUID = HypixelDataHandler.getPotentialUUIDFromName(playerName); if (targetUUID == null) { - player.sendMessage(I18n.string("commands.message.player_not_found", Map.of("player", playerName))); + player.sendTranslated("commands.message.player_not_found", Map.of("player", playerName)); return; } ProxyPlayer target = new ProxyPlayer(targetUUID); if (!target.isOnline().join()) { - player.sendMessage(I18n.string("commands.message.player_not_online", Map.of("player", playerName))); + player.sendTranslated("commands.message.player_not_online", Map.of("player", playerName)); return; } String targetName = HypixelPlayer.getDisplayName(targetUUID); String ourName = player.getFullDisplayName(); - player.sendMessage(I18n.string("commands.message.outgoing", Map.of("target", targetName, "message", String.join(" ", message)))); + player.sendTranslated("commands.message.outgoing", Map.of("target", targetName, "message", String.join(" ", message))); target.sendMessage(I18n.string("commands.message.incoming", Map.of("sender", ourName, "message", String.join(" ", message)))); }, playerArgument, messageArgument); } diff --git a/type.generic/src/main/java/net/swofty/type/generic/command/commands/MuteCommand.java b/type.generic/src/main/java/net/swofty/type/generic/command/commands/MuteCommand.java index a1e59f3c2..f8ecc3054 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/command/commands/MuteCommand.java +++ b/type.generic/src/main/java/net/swofty/type/generic/command/commands/MuteCommand.java @@ -14,7 +14,6 @@ import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.command.CommandParameters; import net.swofty.type.generic.command.HypixelCommand; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.generic.user.categories.Rank; @@ -53,7 +52,7 @@ public void registerUsage(MinestomCommand command) { try { type = MuteType.valueOf(context.get(reasonArg)); } catch (IllegalArgumentException e) { - player.sendMessage(I18n.string("commands.mute.invalid_reason")); + player.sendTranslated("commands.mute.invalid_reason"); return; } @@ -64,7 +63,7 @@ public void registerUsage(MinestomCommand command) { long expiryTime = System.currentTimeMillis() + actualTime; mutePlayer(player, targetUuid, type, player.getUuid(), actualTime, expiryTime, playerName); } catch (IOException e) { - player.sendMessage(I18n.string("commands.common.player_not_found_short", Map.of("player", playerName))); + player.sendTranslated("commands.common.player_not_found_short", Map.of("player", playerName)); } }); }, playerArg, durationArg, reasonArg); @@ -77,7 +76,7 @@ public void registerUsage(MinestomCommand command) { try { reason = MuteType.valueOf(context.get(reasonArg)); } catch (IllegalArgumentException e) { - player.sendMessage(I18n.string("commands.mute.invalid_reason")); + player.sendTranslated("commands.mute.invalid_reason"); return; } @@ -86,7 +85,7 @@ public void registerUsage(MinestomCommand command) { mutePlayer(player, net.minestom.server.utils.mojang.MojangUtils.getUUID(playerName), reason, player.getUuid(), 0, -1, playerName); } catch (IOException e) { - player.sendMessage(I18n.string("commands.common.player_not_found_short", Map.of("player", playerName))); + player.sendTranslated("commands.common.player_not_found_short", Map.of("player", playerName)); } }); }, playerArg, reasonArg); @@ -108,15 +107,15 @@ private void mutePlayer(HypixelPlayer sender, UUID targetUuid, MuteType type, UU punishmentService.handleRequest(message).thenAccept(result -> { if (result instanceof PunishPlayerProtocolObject.PunishPlayerResponse response) { if (response.success()) { - sender.sendMessage(I18n.string("commands.mute.success", Map.of("player", playerName, "id", response.punishmentId()))); + sender.sendTranslated("commands.mute.success", Map.of("player", playerName, "id", response.punishmentId())); } else if (response.errorCode() == PunishPlayerProtocolObject.ErrorCode.ALREADY_PUNISHED) { - sender.sendMessage(I18n.string("commands.mute.already_muted", Map.of("id", response.errorMessage()))); + sender.sendTranslated("commands.mute.already_muted", Map.of("id", response.errorMessage())); } else { - sender.sendMessage(I18n.string("commands.mute.failed", Map.of("error", response.errorMessage()))); + sender.sendTranslated("commands.mute.failed", Map.of("error", response.errorMessage())); } } }).orTimeout(5, TimeUnit.SECONDS).exceptionally(_ -> { - sender.sendMessage(I18n.string("commands.mute.service_offline")); + sender.sendTranslated("commands.mute.service_offline"); return null; }); } diff --git a/type.generic/src/main/java/net/swofty/type/generic/command/commands/PartyCommand.java b/type.generic/src/main/java/net/swofty/type/generic/command/commands/PartyCommand.java index 9c0dd9c45..23ddd84ab 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/command/commands/PartyCommand.java +++ b/type.generic/src/main/java/net/swofty/type/generic/command/commands/PartyCommand.java @@ -8,7 +8,6 @@ import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.command.CommandParameters; import net.swofty.type.generic.command.HypixelCommand; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.party.PartyManager; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.generic.user.categories.Rank; @@ -49,7 +48,7 @@ public void registerUsage(MinestomCommand command) { pendingCommands.add(player.getUuid()); if (!partyService.isOnline().join()) { - sender.sendMessage(I18n.string("commands.common.service_offline_party")); + player.sendTranslated("commands.common.service_offline_party"); pendingCommands.remove(player.getUuid()); return; } @@ -59,20 +58,20 @@ public void registerUsage(MinestomCommand command) { switch (sub.toLowerCase()) { case "list" -> { if (!PartyManager.isInParty(player)) { - player.sendMessage(I18n.string("commands.common.separator")); - player.sendMessage(I18n.string("commands.party.not_in_party")); - player.sendMessage(I18n.string("commands.common.separator")); + player.sendTranslated("commands.common.separator"); + player.sendTranslated("commands.party.not_in_party"); + player.sendTranslated("commands.common.separator"); return; } FullParty party = PartyManager.getPartyFromPlayer(player); int partySize = party.getMembers().size(); - player.sendMessage(I18n.string("commands.common.separator")); - player.sendMessage(I18n.string("commands.party.list_header", Map.of("count", String.valueOf(partySize)))); - player.sendMessage(I18n.string("commands.common.empty_line")); + player.sendTranslated("commands.common.separator"); + player.sendTranslated("commands.party.list_header", Map.of("count", String.valueOf(partySize))); + player.sendTranslated("commands.common.empty_line"); FullParty.Member leader = party.getLeader(); - player.sendMessage(I18n.string("commands.party.list_leader", Map.of("leader", HypixelPlayer.getDisplayName(leader.getUuid())))); + player.sendTranslated("commands.party.list_leader", Map.of("leader", HypixelPlayer.getDisplayName(leader.getUuid()))); boolean hasMods = false; for (FullParty.Member member : party.getMembers()) { @@ -83,12 +82,12 @@ public void registerUsage(MinestomCommand command) { } if (hasMods) { - player.sendMessage(I18n.string("commands.common.empty_line")); + player.sendTranslated("commands.common.empty_line"); String modList = party.getMembers().stream() .filter(member -> member.getRole() == FullParty.Role.MODERATOR) .map(member -> HypixelPlayer.getDisplayName(member.getUuid())) .collect(Collectors.joining(", ")); - player.sendMessage(I18n.string("commands.party.list_moderators", Map.of("moderators", modList))); + player.sendTranslated("commands.party.list_moderators", Map.of("moderators", modList)); } boolean hasMembers = false; @@ -104,10 +103,10 @@ public void registerUsage(MinestomCommand command) { .map(member -> HypixelPlayer.getDisplayName(member.getUuid())) .collect(Collectors.joining(", ")); if (hasMembers) { - player.sendMessage(I18n.string("commands.common.empty_line")); - player.sendMessage(I18n.string("commands.party.list_members", Map.of("members", memberList))); + player.sendTranslated("commands.common.empty_line"); + player.sendTranslated("commands.party.list_members", Map.of("members", memberList)); } - player.sendMessage(I18n.string("commands.common.separator")); + player.sendTranslated("commands.common.separator"); } case "leave" -> PartyManager.leaveParty(player); case "disband" -> PartyManager.disbandParty(player); @@ -129,7 +128,7 @@ public void registerUsage(MinestomCommand command) { pendingCommands.add(player.getUuid()); if (!partyService.isOnline().join()) { - sender.sendMessage(I18n.string("commands.common.service_offline_party")); + player.sendTranslated("commands.common.service_offline_party"); pendingCommands.remove(player.getUuid()); return; } @@ -150,7 +149,7 @@ public void registerUsage(MinestomCommand command) { UUID targetServer = UUID.fromString(target); player.asProxyPlayer().transferToWithIndication(targetServer); } - default -> player.sendMessage(I18n.string("commands.common.unknown_command_use_help", Map.of("command", "party"))); + default -> player.sendTranslated("commands.common.unknown_command_use_help", Map.of("command", "party")); } pendingCommands.remove(player.getUuid()); @@ -167,7 +166,7 @@ public void registerUsage(MinestomCommand command) { pendingCommands.add(player.getUuid()); if (!partyService.isOnline().join()) { - sender.sendMessage(I18n.string("commands.common.service_offline_party_alt")); + player.sendTranslated("commands.common.service_offline_party_alt"); pendingCommands.remove(player.getUuid()); return; } @@ -177,7 +176,7 @@ public void registerUsage(MinestomCommand command) { switch (sub.toLowerCase()) { case "chat" -> PartyManager.sendChat(player, message); - default -> player.sendMessage(I18n.string("commands.common.unknown_command_use_help", Map.of("command", "party"))); + default -> player.sendTranslated("commands.common.unknown_command_use_help", Map.of("command", "party")); } pendingCommands.remove(player.getUuid()); @@ -185,22 +184,22 @@ public void registerUsage(MinestomCommand command) { } private void showHelp(HypixelPlayer player) { - player.sendMessage(I18n.string("commands.common.separator")); - player.sendMessage(I18n.string("commands.party.help_header")); - player.sendMessage(I18n.string("commands.party.help_accept")); - player.sendMessage(I18n.string("commands.party.help_invite")); - player.sendMessage(I18n.string("commands.party.help_list")); - player.sendMessage(I18n.string("commands.party.help_leave")); - player.sendMessage(I18n.string("commands.party.help_warp")); - player.sendMessage(I18n.string("commands.party.help_disband")); - player.sendMessage(I18n.string("commands.party.help_transfer")); - player.sendMessage(I18n.string("commands.party.help_kick")); - player.sendMessage(I18n.string("commands.party.help_promote")); - player.sendMessage(I18n.string("commands.party.help_demote")); - player.sendMessage(I18n.string("commands.party.help_chat")); + player.sendTranslated("commands.common.separator"); + player.sendTranslated("commands.party.help_header"); + player.sendTranslated("commands.party.help_accept"); + player.sendTranslated("commands.party.help_invite"); + player.sendTranslated("commands.party.help_list"); + player.sendTranslated("commands.party.help_leave"); + player.sendTranslated("commands.party.help_warp"); + player.sendTranslated("commands.party.help_disband"); + player.sendTranslated("commands.party.help_transfer"); + player.sendTranslated("commands.party.help_kick"); + player.sendTranslated("commands.party.help_promote"); + player.sendTranslated("commands.party.help_demote"); + player.sendTranslated("commands.party.help_chat"); if (player.getRank().isEqualOrHigherThan(Rank.STAFF)) { - player.sendMessage(I18n.string("commands.party.help_hijack")); + player.sendTranslated("commands.party.help_hijack"); } - player.sendMessage(I18n.string("commands.common.separator")); + player.sendTranslated("commands.common.separator"); } } \ No newline at end of file diff --git a/type.goldmine/src/main/java/net/swofty/type/goldmine/tab/GoldMineServerModule.java b/type.goldmine/src/main/java/net/swofty/type/goldmine/tab/GoldMineServerModule.java index bac35d1b8..d2c89b18b 100644 --- a/type.goldmine/src/main/java/net/swofty/type/goldmine/tab/GoldMineServerModule.java +++ b/type.goldmine/src/main/java/net/swofty/type/goldmine/tab/GoldMineServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GoldMineServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.gold_mine"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.gold_mine", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.hub/src/main/java/net/swofty/type/hub/gui/elizabeth/subguis/GUIBitsSubCategorys.java b/type.hub/src/main/java/net/swofty/type/hub/gui/elizabeth/subguis/GUIBitsSubCategorys.java index 8b367f660..675140609 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/gui/elizabeth/subguis/GUIBitsSubCategorys.java +++ b/type.hub/src/main/java/net/swofty/type/hub/gui/elizabeth/subguis/GUIBitsSubCategorys.java @@ -32,7 +32,7 @@ public class GUIBitsSubCategorys extends HypixelInventoryGUI { private final String guiName; private final HypixelInventoryGUI previousGUI; -public GUIBitsSubCategorys(List items, String guiName, HypixelInventoryGUI previousGUI) { + public GUIBitsSubCategorys(List items, String guiName, HypixelInventoryGUI previousGUI) { super("Bits Shop - " + guiName, InventoryType.CHEST_5_ROW); this.items = items; this.guiName = guiName; @@ -100,4 +100,4 @@ public boolean allowHotkeying() { @Override public void onBottomClick(InventoryPreClickEvent e) { } -} +} \ No newline at end of file diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAdventurer.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAdventurer.java index 547562108..5958a6a81 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAdventurer.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAdventurer.java @@ -5,7 +5,6 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.hub.gui.GUIShopAdventurer; @@ -58,7 +57,7 @@ public void onClick(NPCInteractEvent e) { @Override public DialogueSet[] dialogues(HypixelPlayer player) { return new DialogueSet[] { - DialogueSet.ofTranslation("hello", "npcs_hub.adventurer.dialogue.hello") + DialogueSet.ofTranslation("hello", "npcs_hub.adventurer.dialogue.hello", player) }; } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAlchemist.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAlchemist.java index f01b5676c..62ea5fb6b 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAlchemist.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAlchemist.java @@ -6,7 +6,6 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.AnimalConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.hub.gui.GUIShopAlchemist; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; @@ -63,7 +62,7 @@ public void onClick(NPCInteractEvent e) { @Override public DialogueSet[] dialogues(HypixelPlayer player) { return new DialogueSet[] { - DialogueSet.ofTranslation("hello", "npcs_hub.alchemist.dialogue.hello", Map.of("player", player.getUsername())) + DialogueSet.ofTranslation("hello", "npcs_hub.alchemist.dialogue.hello", player, Map.of("player", player.getUsername())) }; } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCArthur.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCArthur.java index dd030b8b2..117f806be 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCArthur.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCArthur.java @@ -4,7 +4,6 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import java.util.stream.Stream; @@ -50,13 +49,13 @@ public void onClick(NPCInteractEvent e) { @Override public DialogueSet[] dialogues(HypixelPlayer player) { return new DialogueSet[] { - DialogueSet.ofTranslation("dialogue-1", "npcs_hub.arthur.dialogue.dialogue_1"), - DialogueSet.ofTranslation("dialogue-2", "npcs_hub.arthur.dialogue.dialogue_2"), - DialogueSet.ofTranslation("dialogue-3", "npcs_hub.arthur.dialogue.dialogue_3"), - DialogueSet.ofTranslation("dialogue-4", "npcs_hub.arthur.dialogue.dialogue_4"), - DialogueSet.ofTranslation("dialogue-5", "npcs_hub.arthur.dialogue.dialogue_5"), - DialogueSet.ofTranslation("dialogue-6", "npcs_hub.arthur.dialogue.dialogue_6"), - DialogueSet.ofTranslation("dialogue-7", "npcs_hub.arthur.dialogue.dialogue_7") + DialogueSet.ofTranslation("dialogue-1", "npcs_hub.arthur.dialogue.dialogue_1", player), + DialogueSet.ofTranslation("dialogue-2", "npcs_hub.arthur.dialogue.dialogue_2", player), + DialogueSet.ofTranslation("dialogue-3", "npcs_hub.arthur.dialogue.dialogue_3", player), + DialogueSet.ofTranslation("dialogue-4", "npcs_hub.arthur.dialogue.dialogue_4", player), + DialogueSet.ofTranslation("dialogue-5", "npcs_hub.arthur.dialogue.dialogue_5", player), + DialogueSet.ofTranslation("dialogue-6", "npcs_hub.arthur.dialogue.dialogue_6", player), + DialogueSet.ofTranslation("dialogue-7", "npcs_hub.arthur.dialogue.dialogue_7", player) }; } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAuctionMaster.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAuctionMaster.java index b147f559a..9a045e16e 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAuctionMaster.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCAuctionMaster.java @@ -4,7 +4,6 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.gui.inventories.auction.GUIAuctionHouse; import net.swofty.type.skyblockgeneric.mission.MissionData; @@ -46,7 +45,7 @@ public boolean looking(HypixelPlayer player) { @Override public DialogueSet[] dialogues(HypixelPlayer player) { return new DialogueSet[] { - DialogueSet.ofTranslation("quest-hello", "npcs_hub.auction_master.dialogue.quest_hello") + DialogueSet.ofTranslation("quest-hello", "npcs_hub.auction_master.dialogue.quest_hello", player) }; } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBaker.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBaker.java index 7f7d35825..d7b95af2a 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBaker.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBaker.java @@ -15,8 +15,6 @@ import net.swofty.type.skyblockgeneric.item.SkyBlockItem; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; -import net.swofty.type.generic.i18n.I18n; - import java.util.List; import java.util.stream.Stream; @@ -90,7 +88,7 @@ public void onClick(NPCInteractEvent event) { @Override protected DialogueSet[] dialogues(HypixelPlayer player) { return new DialogueSet[] { - DialogueSet.ofTranslation("initial-hello", "npcs_hub.baker.dialogue.initial_hello") + DialogueSet.ofTranslation("initial-hello", "npcs_hub.baker.dialogue.initial_hello", player) }; } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBanker.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBanker.java index 30dc646e7..adb1e575a 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBanker.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBanker.java @@ -4,7 +4,6 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.gui.inventories.banker.GUIBanker; import net.swofty.type.skyblockgeneric.mission.MissionData; @@ -60,7 +59,7 @@ public void onClick(NPCInteractEvent e) { @Override public DialogueSet[] dialogues(HypixelPlayer player) { return new DialogueSet[] { - DialogueSet.ofTranslation("quest-hello", "npcs_hub.banker.dialogue.quest_hello") + DialogueSet.ofTranslation("quest-hello", "npcs_hub.banker.dialogue.quest_hello", player) }; } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBartender.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBartender.java index 581e99441..a8dd69745 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBartender.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCBartender.java @@ -4,7 +4,6 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.hub.gui.GUIShopBartender; import net.swofty.type.skyblockgeneric.mission.missions.MissionKillZombies; @@ -70,9 +69,9 @@ public void onClick(NPCInteractEvent e) { @Override public DialogueSet[] dialogues(HypixelPlayer player) { return new DialogueSet[] { - DialogueSet.ofTranslation("quest-hello", "npcs_hub.bartender.dialogue.quest_hello"), - DialogueSet.ofTranslation("quest-talk", "npcs_hub.bartender.dialogue.quest_talk"), - DialogueSet.ofTranslation("quest-complete", "npcs_hub.bartender.dialogue.quest_complete") + DialogueSet.ofTranslation("quest-hello", "npcs_hub.bartender.dialogue.quest_hello", player), + DialogueSet.ofTranslation("quest-talk", "npcs_hub.bartender.dialogue.quest_talk", player), + DialogueSet.ofTranslation("quest-complete", "npcs_hub.bartender.dialogue.quest_complete", player) }; } } \ No newline at end of file diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCFarmerRigby.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCFarmerRigby.java index 8b2193f30..a79135ce4 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCFarmerRigby.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/NPCFarmerRigby.java @@ -4,7 +4,6 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.mission.MissionData; import net.swofty.type.skyblockgeneric.mission.missions.farmer.MissionCollectWheat; @@ -72,8 +71,8 @@ public void onClick(NPCInteractEvent e) { @Override public DialogueSet[] dialogues(HypixelPlayer player) { return new DialogueSet[] { - DialogueSet.ofTranslation("initial-hello", "npcs_hub.farmer_rigby.dialogue.initial_hello"), - DialogueSet.ofTranslation("spoke-again", "npcs_hub.farmer_rigby.dialogue.spoke_again") + DialogueSet.ofTranslation("initial-hello", "npcs_hub.farmer_rigby.dialogue.initial_hello", player), + DialogueSet.ofTranslation("spoke-again", "npcs_hub.farmer_rigby.dialogue.spoke_again", player) }; } diff --git a/type.hub/src/main/java/net/swofty/type/hub/tab/HubServerModule.java b/type.hub/src/main/java/net/swofty/type/hub/tab/HubServerModule.java index ead43c646..80c045edf 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/tab/HubServerModule.java +++ b/type.hub/src/main/java/net/swofty/type/hub/tab/HubServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class HubServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.hub"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.hub", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.island/src/main/java/net/swofty/type/island/tab/IslandGuestsModule.java b/type.island/src/main/java/net/swofty/type/island/tab/IslandGuestsModule.java index 50eb71386..e2de95807 100644 --- a/type.island/src/main/java/net/swofty/type/island/tab/IslandGuestsModule.java +++ b/type.island/src/main/java/net/swofty/type/island/tab/IslandGuestsModule.java @@ -7,12 +7,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; public class IslandGuestsModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.guests")), TablistSkinRegistry.PURPLE) + new TablistEntry(getCentered(I18n.string("tablist.module.guests", l)), TablistSkinRegistry.PURPLE) )); fillRestWithGray(entries); diff --git a/type.island/src/main/java/net/swofty/type/island/tab/IslandMemberModule.java b/type.island/src/main/java/net/swofty/type/island/tab/IslandMemberModule.java index 10b861711..f2460d0e1 100644 --- a/type.island/src/main/java/net/swofty/type/island/tab/IslandMemberModule.java +++ b/type.island/src/main/java/net/swofty/type/island/tab/IslandMemberModule.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; public class IslandMemberModule extends TablistModule { @@ -18,6 +19,7 @@ public class IslandMemberModule extends TablistModule { @Override public List getEntries(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = player.getLocale(); ArrayList toShow; if (player.isCoop()) toShow = new ArrayList<>(player.getSkyBlockIsland().getCoop().getOnlineMembers()); @@ -25,7 +27,7 @@ public List getEntries(HypixelPlayer p) { toShow = new ArrayList<>(Collections.singletonList(player)); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.island", Map.of("count", String.valueOf(toShow.size())))), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.island", l, Map.of("count", String.valueOf(toShow.size())))), TablistSkinRegistry.CYAN) )); // Sort players by their rank ordinal in reverse diff --git a/type.island/src/main/java/net/swofty/type/island/tab/IslandServerModule.java b/type.island/src/main/java/net/swofty/type/island/tab/IslandServerModule.java index adb1dc34c..b82652044 100644 --- a/type.island/src/main/java/net/swofty/type/island/tab/IslandServerModule.java +++ b/type.island/src/main/java/net/swofty/type/island/tab/IslandServerModule.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class IslandServerModule extends TablistModule { @@ -21,6 +22,7 @@ public class IslandServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = player.getLocale(); List minions = player.getSkyBlockIsland().getMinionData().getMinions(); DatapointMinionData.ProfileMinionData data = player.getSkyblockDataHandler().get( SkyBlockDataHandler.Data.MINION_DATA, @@ -28,28 +30,27 @@ public List getEntries(HypixelPlayer p) { ).getValue(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.private_island"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.island.minions_label", Map.of("current", String.valueOf(minions.size()), "max", String.valueOf(data.getSlots()))), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.private_island", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.island.minions_label", l, Map.of("current", String.valueOf(minions.size()), "max", String.valueOf(data.getSlots()))), TablistSkinRegistry.GRAY)); entries.add(getGrayEntry()); - entries.add(new TablistEntry(I18n.string("tablist.module.minions", Map.of("count", String.valueOf(minions.size()))), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.module.minions", l, Map.of("count", String.valueOf(minions.size()))), TablistSkinRegistry.GRAY)); minions.forEach(minion -> { String content = " " + minion.getMinion().getDisplay().replace(" Minion", ""); - // Add tier content = content + " " + StringUtility.getAsRomanNumeral(minion.getTier()); MinionHandler.InternalMinionTags.State minionState = minion.getInternalMinionTags().getState(); switch (minionState) { - case BAD_FULL -> content = content + " " + I18n.string("tablist.island.minion_state.full"); - case BAD_LOCATION -> content = content + " " + I18n.string("tablist.island.minion_state.blocked"); - default -> content = content + " " + I18n.string("tablist.island.minion_state.active"); + case BAD_FULL -> content = content + " " + I18n.string("tablist.island.minion_state.full", l); + case BAD_LOCATION -> content = content + " " + I18n.string("tablist.island.minion_state.blocked", l); + default -> content = content + " " + I18n.string("tablist.island.minion_state.active", l); } entries.add(new TablistEntry(content, TablistSkinRegistry.GRAY)); diff --git a/type.jerrysworkshop/src/main/java/net/swofty/type/jerrysworkshop/tab/JerrysWorkshopServerModule.java b/type.jerrysworkshop/src/main/java/net/swofty/type/jerrysworkshop/tab/JerrysWorkshopServerModule.java index 04c55f231..15ffb5b9d 100644 --- a/type.jerrysworkshop/src/main/java/net/swofty/type/jerrysworkshop/tab/JerrysWorkshopServerModule.java +++ b/type.jerrysworkshop/src/main/java/net/swofty/type/jerrysworkshop/tab/JerrysWorkshopServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class JerrysWorkshopServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.jerrys_workshop"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.jerrys_workshop", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.murdermysterygame/src/main/java/net/swofty/type/murdermysterygame/MurderMysteryGameScoreboard.java b/type.murdermysterygame/src/main/java/net/swofty/type/murdermysterygame/MurderMysteryGameScoreboard.java index 8ea1cbb0c..0e4eb144e 100644 --- a/type.murdermysterygame/src/main/java/net/swofty/type/murdermysterygame/MurderMysteryGameScoreboard.java +++ b/type.murdermysterygame/src/main/java/net/swofty/type/murdermysterygame/MurderMysteryGameScoreboard.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Map; public class MurderMysteryGameScoreboard { @@ -37,132 +38,133 @@ public static void start() { for (Game game : TypeMurderMysteryGameLoader.getGames()) { for (MurderMysteryPlayer player : game.getPlayers()) { if (player.getInstance() == null) continue; + Locale l = player.getLocale(); List lines = new ArrayList<>(); - lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format")).format(new Date()) + " §8" + HypixelConst.getServerName()); + lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); if (game.getGameStatus() == GameStatus.WAITING) { - lines.add(I18n.string("scoreboard.murdermystery_game.map_label") + game.getMapEntry().getName()); - lines.add(I18n.string("scoreboard.murdermystery_game.players_label") + game.getPlayers().size() + "/" + game.getGameType().getMaxPlayers()); + lines.add(I18n.string("scoreboard.murdermystery_game.map_label", l) + game.getMapEntry().getName()); + lines.add(I18n.string("scoreboard.murdermystery_game.players_label", l) + game.getPlayers().size() + "/" + game.getGameType().getMaxPlayers()); lines.add("§7 "); if (game.getCountdown().isActive()) { - lines.add(I18n.string("scoreboard.murdermystery_game.starting_in_label") + game.getCountdown().getSecondsRemaining() + I18n.string("scoreboard.murdermystery_game.starting_in_suffix")); + lines.add(I18n.string("scoreboard.murdermystery_game.starting_in_label", l) + game.getCountdown().getSecondsRemaining() + I18n.string("scoreboard.murdermystery_game.starting_in_suffix", l)); } else { - lines.add(I18n.string("scoreboard.murdermystery_game.waiting_for_players")); + lines.add(I18n.string("scoreboard.murdermystery_game.waiting_for_players", l)); } lines.add("§7 "); - lines.add(I18n.string("scoreboard.murdermystery_game.mode_label") + game.getGameType().getDisplayName()); + lines.add(I18n.string("scoreboard.murdermystery_game.mode_label", l) + game.getGameType().getDisplayName()); int playerCount = game.getPlayers().size(); int murdererChance = playerCount > 0 ? Math.round(100f / playerCount) : 0; int detectiveChance = playerCount > 0 ? Math.round(100f / playerCount) : 0; Component actionBar = Component.empty() - .append(Component.text(I18n.string("scoreboard.murdermystery_game.actionbar.murderer_chance", Map.of("chance", String.valueOf(murdererChance))), NamedTextColor.RED)) + .append(Component.text(I18n.string("scoreboard.murdermystery_game.actionbar.murderer_chance", l, Map.of("chance", String.valueOf(murdererChance))), NamedTextColor.RED)) .append(Component.text(" ", NamedTextColor.GRAY)) - .append(Component.text(I18n.string("scoreboard.murdermystery_game.actionbar.detective_chance", Map.of("chance", String.valueOf(detectiveChance))), NamedTextColor.AQUA)); + .append(Component.text(I18n.string("scoreboard.murdermystery_game.actionbar.detective_chance", l, Map.of("chance", String.valueOf(detectiveChance))), NamedTextColor.AQUA)); player.sendActionBar(actionBar); } else if (game.getGameStatus() == GameStatus.IN_PROGRESS) { GameRole role = game.getRoleManager().getRole(player.getUuid()); if (player.isEliminated()) { - lines.add(I18n.string("scoreboard.murdermystery_game.spectating_label")); + lines.add(I18n.string("scoreboard.murdermystery_game.spectating_label", l)); lines.add("§7 "); if (role != null) { - lines.add(I18n.string("scoreboard.murdermystery_game.your_role_label") + " " + getScoreboardRoleColor(role) + role.getDisplayName()); + lines.add(I18n.string("scoreboard.murdermystery_game.your_role_label", l) + " " + getScoreboardRoleColor(role, l) + role.getDisplayName()); } lines.add("§7 "); int playersAlive = game.getRoleManager().countAliveWithRole(GameRole.INNOCENT) + game.getRoleManager().countAliveWithRole(GameRole.DETECTIVE) + game.getRoleManager().countAliveWithRole(GameRole.MURDERER); - lines.add(I18n.string("scoreboard.murdermystery_game.players_alive_label") + playersAlive); + lines.add(I18n.string("scoreboard.murdermystery_game.players_alive_label", l) + playersAlive); - String timeLeft = formatTimeRemaining(game.getGameStartTime()); - lines.add(I18n.string("scoreboard.murdermystery_game.time_left_label") + timeLeft); + String timeLeft = formatTimeRemaining(game.getGameStartTime(), l); + lines.add(I18n.string("scoreboard.murdermystery_game.time_left_label", l) + timeLeft); lines.add("§7 "); boolean detectiveAlive = game.getRoleManager().countAliveWithRole(GameRole.DETECTIVE) > 0; String detectiveStatus = detectiveAlive - ? I18n.string("scoreboard.murdermystery_game.detective_alive") - : I18n.string("scoreboard.murdermystery_game.detective_dead"); - lines.add(I18n.string("scoreboard.murdermystery_game.detective_label") + " " + detectiveStatus); + ? I18n.string("scoreboard.murdermystery_game.detective_alive", l) + : I18n.string("scoreboard.murdermystery_game.detective_dead", l); + lines.add(I18n.string("scoreboard.murdermystery_game.detective_label", l) + " " + detectiveStatus); lines.add("§7 "); - lines.add(I18n.string("scoreboard.murdermystery_game.map_label") + game.getMapEntry().getName()); + lines.add(I18n.string("scoreboard.murdermystery_game.map_label", l) + game.getMapEntry().getName()); } else { if (role != null) { - lines.add(I18n.string("scoreboard.murdermystery_game.role_label") + " " + getScoreboardRoleColor(role) + role.getDisplayName()); + lines.add(I18n.string("scoreboard.murdermystery_game.role_label", l) + " " + getScoreboardRoleColor(role, l) + role.getDisplayName()); } lines.add("§7 "); int innocentsLeft = game.getRoleManager().countAliveWithRole(GameRole.INNOCENT) + game.getRoleManager().countAliveWithRole(GameRole.DETECTIVE); - lines.add(I18n.string("scoreboard.murdermystery_game.innocents_left_label") + innocentsLeft); + lines.add(I18n.string("scoreboard.murdermystery_game.innocents_left_label", l) + innocentsLeft); - String timeLeft = formatTimeRemaining(game.getGameStartTime()); - lines.add(I18n.string("scoreboard.murdermystery_game.time_left_label") + timeLeft); + String timeLeft = formatTimeRemaining(game.getGameStartTime(), l); + lines.add(I18n.string("scoreboard.murdermystery_game.time_left_label", l) + timeLeft); lines.add("§7 "); boolean detectiveAlive = game.getRoleManager().countAliveWithRole(GameRole.DETECTIVE) > 0; String detectiveStatus = detectiveAlive - ? I18n.string("scoreboard.murdermystery_game.detective_alive") - : I18n.string("scoreboard.murdermystery_game.detective_dead"); - lines.add(I18n.string("scoreboard.murdermystery_game.detective_label") + " " + detectiveStatus); + ? I18n.string("scoreboard.murdermystery_game.detective_alive", l) + : I18n.string("scoreboard.murdermystery_game.detective_dead", l); + lines.add(I18n.string("scoreboard.murdermystery_game.detective_label", l) + " " + detectiveStatus); lines.add("§7 "); - lines.add(I18n.string("scoreboard.murdermystery_game.map_label") + game.getMapEntry().getName()); + lines.add(I18n.string("scoreboard.murdermystery_game.map_label", l) + game.getMapEntry().getName()); } } else if (game.getGameStatus() == GameStatus.ENDING) { - lines.add(I18n.string("scoreboard.murdermystery_game.game_over")); + lines.add(I18n.string("scoreboard.murdermystery_game.game_over", l)); lines.add("§7 "); GameRole role = game.getRoleManager().getRole(player.getUuid()); if (role != null) { - lines.add(I18n.string("scoreboard.murdermystery_game.your_role_label") + " " + getScoreboardRoleColor(role) + role.getDisplayName()); + lines.add(I18n.string("scoreboard.murdermystery_game.your_role_label", l) + " " + getScoreboardRoleColor(role, l) + role.getDisplayName()); } lines.add("§7 "); int kills = player.getKillsThisGame(); if (kills > 0) { - lines.add(I18n.string("scoreboard.murdermystery_game.your_kills_label") + kills); + lines.add(I18n.string("scoreboard.murdermystery_game.your_kills_label", l) + kills); } int tokens = player.getTokensEarnedThisGame(); - lines.add(I18n.string("scoreboard.murdermystery_game.tokens_earned_label") + tokens); + lines.add(I18n.string("scoreboard.murdermystery_game.tokens_earned_label", l) + tokens); lines.add("§7 "); - lines.add(I18n.string("scoreboard.murdermystery_game.map_label") + game.getMapEntry().getName()); - lines.add(I18n.string("scoreboard.murdermystery_game.mode_label") + game.getGameType().getDisplayName()); + lines.add(I18n.string("scoreboard.murdermystery_game.map_label", l) + game.getMapEntry().getName()); + lines.add(I18n.string("scoreboard.murdermystery_game.mode_label", l) + game.getGameType().getDisplayName()); } lines.add("§7 "); - lines.add(I18n.string("scoreboard.common.footer")); + lines.add(I18n.string("scoreboard.common.footer", l)); if (!scoreboard.hasScoreboard(player)) { - scoreboard.createScoreboard(player, getSidebarName(animationFrame)); + scoreboard.createScoreboard(player, getSidebarName(animationFrame, l)); } scoreboard.updateLines(player, lines); - scoreboard.updateTitle(player, getSidebarName(animationFrame)); + scoreboard.updateTitle(player, getSidebarName(animationFrame, l)); } } return TaskSchedule.tick(4); }); } - private static String getScoreboardRoleColor(GameRole role) { + private static String getScoreboardRoleColor(GameRole role, Locale locale) { return switch (role) { - case MURDERER -> I18n.string("scoreboard.murdermystery_game.role_color.murderer"); - case DETECTIVE -> I18n.string("scoreboard.murdermystery_game.role_color.detective"); - case INNOCENT -> I18n.string("scoreboard.murdermystery_game.role_color.innocent"); - case ASSASSIN -> I18n.string("scoreboard.murdermystery_game.role_color.assassin"); + case MURDERER -> I18n.string("scoreboard.murdermystery_game.role_color.murderer", locale); + case DETECTIVE -> I18n.string("scoreboard.murdermystery_game.role_color.detective", locale); + case INNOCENT -> I18n.string("scoreboard.murdermystery_game.role_color.innocent", locale); + case ASSASSIN -> I18n.string("scoreboard.murdermystery_game.role_color.assassin", locale); }; } - private static String formatTimeRemaining(long gameStartTime) { - if (gameStartTime == 0) return I18n.string("scoreboard.murdermystery_game.time_left_default"); + private static String formatTimeRemaining(long gameStartTime, Locale locale) { + if (gameStartTime == 0) return I18n.string("scoreboard.murdermystery_game.time_left_default", locale); long elapsed = System.currentTimeMillis() - gameStartTime; long remaining = GAME_DURATION_MS - elapsed; if (remaining < 0) remaining = 0; @@ -176,8 +178,8 @@ public static void removeCache(Player player) { scoreboard.removeScoreboard(player); } - private static String getSidebarName(int counter) { - String baseText = I18n.string("scoreboard.murdermystery_game.title_base"); + private static String getSidebarName(int counter, Locale locale) { + String baseText = I18n.string("scoreboard.murdermystery_game.title_base", locale); String[] colors = {"§f§l", "§6§l", "§e§l"}; String endColor = "§a§l"; diff --git a/type.murdermysterylobby/src/main/java/net/swofty/type/murdermysterylobby/MurderMysteryLobbyScoreboard.java b/type.murdermysterylobby/src/main/java/net/swofty/type/murdermysterylobby/MurderMysteryLobbyScoreboard.java index 01b941cf7..7c0b368ed 100644 --- a/type.murdermysterylobby/src/main/java/net/swofty/type/murdermysterylobby/MurderMysteryLobbyScoreboard.java +++ b/type.murdermysterylobby/src/main/java/net/swofty/type/murdermysterylobby/MurderMysteryLobbyScoreboard.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; public class MurderMysteryLobbyScoreboard { private static final HypixelScoreboard scoreboard = new HypixelScoreboard(); @@ -36,6 +37,7 @@ public static void start() { if (player.getDataHandler() == null) { continue; } + Locale l = player.getLocale(); MurderMysteryDataHandler handler = MurderMysteryDataHandler.getUser(player); long totalKills = 0; @@ -57,24 +59,24 @@ public static void start() { } List lines = new ArrayList<>(); - lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format")).format(new Date()) + " §8" + HypixelConst.getServerName()); + lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.murdermystery_lobby.total_kills_label") + totalKills); - lines.add(I18n.string("scoreboard.murdermystery_lobby.total_wins_label") + totalWins); + lines.add(I18n.string("scoreboard.murdermystery_lobby.total_kills_label", l) + totalKills); + lines.add(I18n.string("scoreboard.murdermystery_lobby.total_wins_label", l) + totalWins); lines.add("§7 "); - lines.add(I18n.string("scoreboard.murdermystery_lobby.wins_as_detective_label") + detectiveWins); - lines.add(I18n.string("scoreboard.murdermystery_lobby.wins_as_murderer_label") + murdererWins); + lines.add(I18n.string("scoreboard.murdermystery_lobby.wins_as_detective_label", l) + detectiveWins); + lines.add(I18n.string("scoreboard.murdermystery_lobby.wins_as_murderer_label", l) + murdererWins); lines.add("§7 "); - lines.add(I18n.string("scoreboard.murdermystery_lobby.tokens_label") + tokens); + lines.add(I18n.string("scoreboard.murdermystery_lobby.tokens_label", l) + tokens); lines.add("§7 "); - lines.add(I18n.string("scoreboard.common.footer")); + lines.add(I18n.string("scoreboard.common.footer", l)); if (!scoreboard.hasScoreboard(player)) { - scoreboard.createScoreboard(player, getSidebarName(animationFrame)); + scoreboard.createScoreboard(player, getSidebarName(animationFrame, l)); } scoreboard.updateLines(player, lines); - scoreboard.updateTitle(player, getSidebarName(animationFrame)); + scoreboard.updateTitle(player, getSidebarName(animationFrame, l)); } return TaskSchedule.tick(4); }); @@ -84,8 +86,8 @@ public static void removeCache(Player player) { scoreboard.removeScoreboard(player); } - private static String getSidebarName(int counter) { - String baseText = I18n.string("scoreboard.murdermystery_lobby.title_base"); + private static String getSidebarName(int counter, Locale locale) { + String baseText = I18n.string("scoreboard.murdermystery_lobby.title_base", locale); String[] colors = {"§f§l", "§6§l", "§e§l"}; String endColor = "§a§l"; diff --git a/type.murdermysterylobby/src/main/java/net/swofty/type/murdermysterylobby/tab/MurderMysteryPlayersOnlineModule.java b/type.murdermysterylobby/src/main/java/net/swofty/type/murdermysterylobby/tab/MurderMysteryPlayersOnlineModule.java index 556aee7c3..23163d6ab 100644 --- a/type.murdermysterylobby/src/main/java/net/swofty/type/murdermysterylobby/tab/MurderMysteryPlayersOnlineModule.java +++ b/type.murdermysterylobby/src/main/java/net/swofty/type/murdermysterylobby/tab/MurderMysteryPlayersOnlineModule.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; public class MurderMysteryPlayersOnlineModule extends TablistModule { @@ -23,10 +24,11 @@ public MurderMysteryPlayersOnlineModule(int page) { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); List players = HypixelGenericLoader.getLoadedPlayers(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.players_murder_mystery", Map.of("count", String.valueOf(players.size())))), TablistSkinRegistry.ORANGE) + new TablistEntry(getCentered(I18n.string("tablist.module.players_murder_mystery", l, Map.of("count", String.valueOf(players.size())))), TablistSkinRegistry.ORANGE) )); List toShow = new ArrayList<>(); diff --git a/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/PrototypeLobbyScoreboard.java b/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/PrototypeLobbyScoreboard.java index 076bc153c..9ede9c5e0 100644 --- a/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/PrototypeLobbyScoreboard.java +++ b/type.prototypelobby/src/main/java/net/swofty/type/prototypelobby/PrototypeLobbyScoreboard.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; public class PrototypeLobbyScoreboard { private static final HypixelScoreboard scoreboard = new HypixelScoreboard(); @@ -32,6 +33,7 @@ public static void start() { } for (HypixelPlayer player : HypixelGenericLoader.getLoadedPlayers()) { + Locale l = player.getLocale(); HypixelDataHandler dataHandler = player.getDataHandler(); PrototypeLobbyDataHandler prototypeDataHandler = PrototypeLobbyDataHandler.getUser(player); @@ -42,25 +44,25 @@ public static void start() { long hype = prototypeDataHandler.get(PrototypeLobbyDataHandler.Data.HYPE, DatapointLeaderboardLong.class).getValue(); List lines = new ArrayList<>(); - lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format")).format(new Date()) + " §8" + HypixelConst.getServerName()); + lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.prototype_lobby.dev_notice_line1")); - lines.add(I18n.string("scoreboard.prototype_lobby.dev_notice_line2")); + lines.add(I18n.string("scoreboard.prototype_lobby.dev_notice_line1", l)); + lines.add(I18n.string("scoreboard.prototype_lobby.dev_notice_line2", l)); lines.add("§7 "); - lines.add(I18n.string("scoreboard.prototype_lobby.bug_report_line1")); - lines.add(I18n.string("scoreboard.prototype_lobby.bug_report_line2")); - lines.add(I18n.string("scoreboard.prototype_lobby.bug_report_url")); + lines.add(I18n.string("scoreboard.prototype_lobby.bug_report_line1", l)); + lines.add(I18n.string("scoreboard.prototype_lobby.bug_report_line2", l)); + lines.add(I18n.string("scoreboard.prototype_lobby.bug_report_url", l)); lines.add("§7 "); - lines.add(I18n.string("scoreboard.prototype_lobby.hype_label") + hype + I18n.string("scoreboard.prototype_lobby.hype_max")); + lines.add(I18n.string("scoreboard.prototype_lobby.hype_label", l) + hype + I18n.string("scoreboard.prototype_lobby.hype_max", l)); lines.add("§7 "); - lines.add(I18n.string("scoreboard.common.footer")); + lines.add(I18n.string("scoreboard.common.footer", l)); if (!scoreboard.hasScoreboard(player)) { - scoreboard.createScoreboard(player, getSidebarName(prototypeName)); + scoreboard.createScoreboard(player, getSidebarName(prototypeName, l)); } scoreboard.updateLines(player, lines); - scoreboard.updateTitle(player, getSidebarName(prototypeName)); + scoreboard.updateTitle(player, getSidebarName(prototypeName, l)); } return TaskSchedule.tick(4); }); @@ -70,8 +72,8 @@ public static void removeCache(Player player) { scoreboard.removeScoreboard(player); } - private static String getSidebarName(int counter) { - String baseText = I18n.string("scoreboard.prototype_lobby.title_base"); + private static String getSidebarName(int counter, Locale locale) { + String baseText = I18n.string("scoreboard.prototype_lobby.title_base", locale); String[] colors = {"§f§l", "§6§l", "§e§l"}; String endColor = "§a§l"; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIAnvil.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIAnvil.java index dab7ef2bf..aac32d537 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIAnvil.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIAnvil.java @@ -9,6 +9,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -20,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIAnvil extends HypixelInventoryGUI { @@ -60,8 +62,8 @@ private void setupCombineButton() { set(new GUIItem(COMBINE_BUTTON_SLOT) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_anvil.combine_items"), Material.ANVIL, 1, - I18n.lore("gui_anvil.combine_items.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_anvil.combine_items", Material.ANVIL, 1, + "gui_anvil.combine_items.lore"); } }); } @@ -70,8 +72,8 @@ private void setupResultSlot() { set(new GUIItem(RESULT_SLOT) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_anvil.result_empty"), Material.BARRIER, 1, - I18n.lore("gui_anvil.result_empty.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_anvil.result_empty", Material.BARRIER, 1, + "gui_anvil.result_empty.lore"); } }); } @@ -265,6 +267,7 @@ private void updateIndicators() { } private void updateIndicators(boolean isUpgradeValid, boolean isSacrificeValid, boolean canCraft) { + Locale l = getPlayer().getLocale(); Material upgradeMaterial = (canCraft || (isUpgradeValid && !isSacrificeValid)) ? Material.LIME_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE; @@ -273,11 +276,11 @@ private void updateIndicators(boolean isUpgradeValid, boolean isSacrificeValid, ? Material.LIME_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE; - ItemStack.Builder upgradeIndicator = ItemStackCreator.getStack(I18n.string("gui_anvil.item_to_upgrade"), upgradeMaterial, 1, - I18n.lore("gui_anvil.item_to_upgrade.lore")); + ItemStack.Builder upgradeIndicator = ItemStackCreator.getStack(I18n.string("gui_anvil.item_to_upgrade", l), upgradeMaterial, 1, + I18n.lore("gui_anvil.item_to_upgrade.lore", l)); - ItemStack.Builder sacrificeIndicator = ItemStackCreator.getStack(I18n.string("gui_anvil.item_to_sacrifice"), sacrificeMaterial, 1, - I18n.lore("gui_anvil.item_to_sacrifice.lore")); + ItemStack.Builder sacrificeIndicator = ItemStackCreator.getStack(I18n.string("gui_anvil.item_to_sacrifice", l), sacrificeMaterial, 1, + I18n.lore("gui_anvil.item_to_sacrifice.lore", l)); for (int slot : UPGRADE_INDICATOR_SLOTS) { set(slot, upgradeIndicator); @@ -302,16 +305,16 @@ private void updateResultPreview(boolean isUpgradeValid, boolean isSacrificeVali set(new GUIItem(RESULT_SLOT) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_anvil.result_error"), Material.BARRIER, 1, - I18n.lore("gui_anvil.result_error.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_anvil.result_error", Material.BARRIER, 1, + "gui_anvil.result_error.lore"); } }); } else { set(new GUIItem(RESULT_SLOT) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_anvil.result_empty"), Material.BARRIER, 1, - I18n.lore("gui_anvil.result_empty.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_anvil.result_empty", Material.BARRIER, 1, + "gui_anvil.result_empty.lore"); } }); } @@ -335,8 +338,8 @@ private void updateCombineButton(boolean canCraft) { set(new GUIItem(COMBINE_BUTTON_SLOT) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_anvil.combine_items"), Material.ANVIL, 1, - I18n.lore("gui_anvil.combine_items.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_anvil.combine_items", Material.ANVIL, 1, + "gui_anvil.combine_items.lore"); } }); return; @@ -345,16 +348,17 @@ public ItemStack.Builder getItem(HypixelPlayer p) { int levelCost = sacrificeItem.getComponent(AnvilCombinableComponent.class) .applyCostLevels(upgradeItem, sacrificeItem, (SkyBlockPlayer) getPlayer()); - List lore = new ArrayList<>(I18n.lore("gui_anvil.combine_items.lore")); + Locale l = getPlayer().getLocale(); + List lore = new ArrayList<>(I18n.lore("gui_anvil.combine_items.lore", l)); if (levelCost > 0) { lore.add(""); - lore.add(I18n.string("gui_anvil.cost_label")); - lore.add(I18n.string("gui_anvil.cost_exp_levels", Map.of("cost", String.valueOf(levelCost)))); + lore.add(I18n.string("gui_anvil.cost_label", l)); + lore.add(I18n.string("gui_anvil.cost_exp_levels", l, Map.of("cost", String.valueOf(levelCost)))); } lore.add(""); - lore.add(I18n.string("gui_anvil.click_to_combine")); + lore.add(I18n.string("gui_anvil.click_to_combine", l)); set(new GUIClickableItem(COMBINE_BUTTON_SLOT) { @Override @@ -365,7 +369,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_anvil.combine_items"), Material.ANVIL, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_anvil.combine_items", l), Material.ANVIL, 1, lore); } }); } @@ -381,7 +385,8 @@ private void performCraft(SkyBlockPlayer player) { int requiredLevels = component.applyCostLevels(upgradeItem, sacrificeItem, player); if (player.getLevel() < requiredLevels) { - player.sendMessage(I18n.string("gui_anvil.not_enough_levels")); + Locale l = player.getLocale(); + player.sendMessage(I18n.string("gui_anvil.not_enough_levels", l)); return; } @@ -408,8 +413,8 @@ private void performCraft(SkyBlockPlayer player) { set(new GUIItem(COMBINE_BUTTON_SLOT) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_anvil.claim_result"), Material.OAK_SIGN, 1, - I18n.lore("gui_anvil.claim_result.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_anvil.claim_result", Material.OAK_SIGN, 1, + "gui_anvil.claim_result.lore"); } }); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIBoosterCookie.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIBoosterCookie.java index a8fb5d9b3..fb629a030 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIBoosterCookie.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIBoosterCookie.java @@ -8,6 +8,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; @@ -25,8 +26,8 @@ public void onOpen(InventoryGUIOpenEvent e) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_misc.booster_cookie.cancel_button"), Material.RED_CONCRETE, 1, - I18n.lore("gui_misc.booster_cookie.cancel_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_misc.booster_cookie.cancel_button", Material.RED_CONCRETE, 1, + "gui_misc.booster_cookie.cancel_button.lore"); } @Override @@ -56,8 +57,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_misc.booster_cookie.consume_button"), Material.COOKIE, 1, - I18n.lore("gui_misc.booster_cookie.consume_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_misc.booster_cookie.consume_button", Material.COOKIE, 1, + "gui_misc.booster_cookie.consume_button.lore"); } }); updateItemStacks(getInventory(), getPlayer()); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIBrewingStand.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIBrewingStand.java index ab79836cb..5efc0a290 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIBrewingStand.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIBrewingStand.java @@ -11,6 +11,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; @@ -29,6 +30,7 @@ import net.swofty.commons.skyblock.item.Rarity; import net.swofty.commons.skyblock.item.attribute.attributes.ItemAttributePotionData; +import java.util.Locale; import java.util.Map; public class GUIBrewingStand extends HypixelInventoryGUI implements RefreshingGUI { @@ -69,7 +71,7 @@ public void onOpen(InventoryGUIOpenEvent e) { setupPotionSlots(); // Set initial animation panes - updateAnimationPanes(getBrewingData()); + updateAnimationPanes(getBrewingData(), e.player()); } private void setupIngredientSlot() { @@ -188,13 +190,14 @@ public void refreshItems(HypixelPlayer player) { } // Update animation panes - updateAnimationPanes(brewingData); + updateAnimationPanes(brewingData, player); // Toggle animation state animationToggle = !animationToggle; } - private void updateAnimationPanes(BlockAttributeBrewingData.BrewingData brewingData) { + private void updateAnimationPanes(BlockAttributeBrewingData.BrewingData brewingData, HypixelPlayer player) { + Locale l = player.getLocale(); Material paneMaterial; String paneName; String[] paneLore; @@ -202,12 +205,12 @@ private void updateAnimationPanes(BlockAttributeBrewingData.BrewingData brewingD if (brewingData.isBrewing()) { paneMaterial = animationToggle ? Material.RED_STAINED_GLASS_PANE : Material.ORANGE_STAINED_GLASS_PANE; long remainingSeconds = brewingData.getRemainingTimeMs() / 1000; - paneName = I18n.string("gui_misc.brewing_stand.remaining_time", Map.of("seconds", String.valueOf(remainingSeconds))); + paneName = I18n.string("gui_misc.brewing_stand.remaining_time", l, Map.of("seconds", String.valueOf(remainingSeconds))); paneLore = new String[0]; } else { paneMaterial = Material.LIGHT_BLUE_STAINED_GLASS_PANE; - paneName = I18n.string("gui_misc.brewing_stand.place_bottles"); - paneLore = new String[]{I18n.string("gui_misc.brewing_stand.place_bottles_below")}; + paneName = I18n.string("gui_misc.brewing_stand.place_bottles", l); + paneLore = new String[]{I18n.string("gui_misc.brewing_stand.place_bottles_below", l)}; } for (int slot : ANIMATION_SLOTS) { diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIConsumeSoulflow.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIConsumeSoulflow.java index 7c3c1ce75..6a1a080ee 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIConsumeSoulflow.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIConsumeSoulflow.java @@ -4,6 +4,7 @@ import net.minestom.server.item.ItemStack; import net.swofty.type.generic.data.datapoints.DatapointInteger; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -12,6 +13,7 @@ import net.swofty.type.skyblockgeneric.item.components.SoulflowComponent; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import java.util.Locale; import java.util.Map; public class GUIConsumeSoulflow implements View { @@ -26,7 +28,7 @@ public record State(SkyBlockItem item) { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_misc.consume_soulflow.title"), InventoryType.CHEST_4_ROW); + return ViewConfiguration.translatable("gui_misc.consume_soulflow.title", InventoryType.CHEST_4_ROW); } @Override @@ -40,14 +42,13 @@ public void layout(ViewLayout layout, State state, ViewContext ctx) { int itemSoulflow = s.item().getComponent(SoulflowComponent.class).getAmount(); int addition = s.item().getAmount() * itemSoulflow; - return ItemStackCreator.getStackHead( - I18n.string("gui_misc.consume_soulflow.confirm_button"), + return TranslatableItemStackCreator.getStackHead(player, "gui_misc.consume_soulflow.confirm_button", "94f0c693b85658b0bae792c9f9b717eb024ab8c4b349455648ea08358b50ddc4", 1, - I18n.lore("gui_misc.consume_soulflow.confirm_button.lore", Map.of( + "gui_misc.consume_soulflow.confirm_button.lore", Map.of( "soulflow", String.valueOf(soulflow), "addition", String.valueOf(addition) - ))); + )); }, (click, viewCtx) -> { SkyBlockPlayer player = (SkyBlockPlayer) viewCtx.player(); @@ -58,7 +59,8 @@ public void layout(ViewLayout layout, State state, ViewContext ctx) { int addition = click.state().item().getAmount() * itemSoulflow; data.get(SkyBlockDataHandler.Data.SOULFLOW, DatapointInteger.class).setValue(soulflow + addition); - player.sendMessage(I18n.string("gui_misc.consume_soulflow.consumed_message", Map.of( + Locale l = player.getLocale(); + player.sendMessage(I18n.string("gui_misc.consume_soulflow.consumed_message", l, Map.of( "addition", String.valueOf(addition), "total", String.valueOf(soulflow + addition) ))); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUICreative.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUICreative.java index 694e5dbe5..d2d1ab5b2 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUICreative.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUICreative.java @@ -9,6 +9,7 @@ import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.generic.gui.HypixelSignGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ClickContext; import net.swofty.type.generic.gui.v2.context.ViewContext; @@ -22,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUICreative extends PaginatedView { @@ -31,7 +33,8 @@ public ViewConfiguration configuration() { return ViewConfiguration.withString( (state, ctx) -> { int totalPages = Math.max(1, (int) Math.ceil((double) getFilteredItems(state).size() / DEFAULT_SLOTS.length)); - return I18n.string("gui_misc.creative.title", Map.of( + Locale l = ctx.player().getLocale(); + return I18n.string("gui_misc.creative.title", l, Map.of( "page", String.valueOf(state.page() + 1), "total_pages", String.valueOf(totalPages) )); @@ -76,11 +79,11 @@ protected void layoutBackground(ViewLayout layout, CreativeState @Override protected void layoutCustom(ViewLayout layout, CreativeState state, ViewContext ctx) { - layout.slot(49, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_misc.creative.close_button"), Material.BARRIER, 1), + layout.slot(49, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_misc.creative.close_button", Material.BARRIER, 1), (_, c) -> c.player().closeInventory()); - layout.slot(50, (_, _) -> ItemStackCreator.getStack(I18n.string("gui_misc.creative.search_button"), Material.OAK_SIGN, 1, - I18n.lore("gui_misc.creative.search_button.lore")), (_, c) -> { + layout.slot(50, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_misc.creative.search_button", Material.OAK_SIGN, 1, + "gui_misc.creative.search_button.lore"), (_, c) -> { new HypixelSignGUI(c.player()).open(new String[]{"Enter query", ""}).thenAccept(line -> { if (line == null) { return; @@ -103,10 +106,11 @@ protected ItemStack.Builder renderItem(SkyBlockItem skyBlockItem, int index, Hyp boolean stackable = !(displayItem.hasComponent(TrackedUniqueComponent.class)); + Locale l = player.getLocale(); ArrayList lore = new ArrayList<>(displayItem.getLore()); lore.add(" "); - lore.add(I18n.string("gui_misc.creative.click_to_retrieve")); - if (stackable) lore.add(I18n.string("gui_misc.creative.right_click_stack")); + lore.add(I18n.string("gui_misc.creative.click_to_retrieve", l)); + if (stackable) lore.add(I18n.string("gui_misc.creative.right_click_stack", l)); return ItemStackCreator.updateLore(itemStack, lore); } @@ -123,16 +127,17 @@ protected void onItemClick(ClickContext click, ViewContext ctx, S player.playSound(Sound.sound(Key.key("block.note_block.pling"), Sound.Source.PLAYER, 1.0f, 2.0f)); + Locale l = player.getLocale(); if (click.click() instanceof Click.Right && stackable) { toGive.setAmount(64); player.addAndUpdateItem(toGive); player.playSound(Sound.sound(Key.key("block.note_block.pling"), Sound.Source.PLAYER, 1.0f, 2.0f)); - player.sendMessage(I18n.string("gui_misc.creative.given_stack", Map.of("item_name", toGive.getDisplayName()))); + player.sendMessage(I18n.string("gui_misc.creative.given_stack", l, Map.of("item_name", toGive.getDisplayName()))); } else { toGive.setAmount(1); player.addAndUpdateItem(toGive); player.playSound(Sound.sound(Key.key("block.note_block.pling"), Sound.Source.PLAYER, 1.0f, 2.0f)); - player.sendMessage(I18n.string("gui_misc.creative.given_single", Map.of("item_name", toGive.getDisplayName()))); + player.sendMessage(I18n.string("gui_misc.creative.given_single", l, Map.of("item_name", toGive.getDisplayName()))); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIEnchantmentTable.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIEnchantmentTable.java index 49b9f4b2a..3e58b56a9 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIEnchantmentTable.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIEnchantmentTable.java @@ -15,6 +15,7 @@ import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -33,6 +34,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIEnchantmentTable extends HypixelInventoryGUI { @@ -63,11 +65,10 @@ public void onOpen(InventoryGUIOpenEvent e) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_enchantment.bookshelf_power"), Material.BOOKSHELF, 1, - I18n.lore("gui_enchantment.bookshelf_power.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_enchantment.bookshelf_power", Material.BOOKSHELF, 1, + "gui_enchantment.bookshelf_power.lore", Map.of( "power", String.valueOf(bookshelfPower) - ))); + )); } }); @@ -75,9 +76,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_enchantment.enchantments_guide"), Material.BOOK, 1, - I18n.lore("gui_enchantment.enchantments_guide.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_enchantment.enchantments_guide", Material.BOOK, 1, + "gui_enchantment.enchantments_guide.lore"); } }); @@ -85,9 +85,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_enchantment.enchant_item_label"), Material.ENCHANTING_TABLE, 1, - I18n.lore("gui_enchantment.enchant_item_label.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_enchantment.enchant_item_label", Material.ENCHANTING_TABLE, 1, + "gui_enchantment.enchant_item_label.lore"); } }); @@ -97,8 +96,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @SneakyThrows public void updateFromItem(SkyBlockItem item, EnchantmentType selected) { getInventory().setTitle(Component.text( - selected == null ? I18n.string("gui_enchantment.title") : - I18n.string("gui_enchantment.title_selected", Map.of( + selected == null ? I18n.string("gui_enchantment.title", getPlayer().getLocale()) : + I18n.string("gui_enchantment.title_selected", getPlayer().getLocale(), Map.of( "enchantment", StringUtility.toNormalCase(selected.name()) ))) ); @@ -113,9 +112,8 @@ public void updateFromItem(SkyBlockItem item, EnchantmentType selected) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_enchantment.place_item"), Material.GRAY_DYE, 1, - I18n.lore("gui_enchantment.place_item.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_enchantment.place_item", Material.GRAY_DYE, 1, + "gui_enchantment.place_item.lore"); } }); @@ -179,9 +177,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_enchantment.invalid_item"), Material.RED_DYE, 1, - I18n.lore("gui_enchantment.invalid_item.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_enchantment.invalid_item", Material.RED_DYE, 1, + "gui_enchantment.invalid_item.lore"); } }); @@ -200,9 +197,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_enchantment.cannot_enchant"), Material.RED_DYE, 1, - I18n.lore("gui_enchantment.cannot_enchant.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_enchantment.cannot_enchant", Material.RED_DYE, 1, + "gui_enchantment.cannot_enchant.lore"); } }); updateItemStacks(getInventory(), getPlayer()); @@ -220,7 +216,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; if (bookshelfPower < enchantmentType.getEnchFromTable().getRequiredBookshelfPower()) { - player.sendMessage(I18n.string("gui_enchantment.requires_bookshelf_message", Map.of( + player.sendMessage(I18n.string("gui_enchantment.requires_bookshelf_message", player.getLocale(), Map.of( "power", String.valueOf(enchantmentType.getEnchFromTable().getRequiredBookshelfPower()) ))); return; @@ -250,11 +246,11 @@ public ItemStack.Builder getItem(HypixelPlayer p) { lore.add("§a "); if (bookshelfPower < enchantmentType.getEnchFromTable().getRequiredBookshelfPower()) { - lore.add(I18n.string("gui_enchantment.requires_bookshelf", Map.of( + lore.add(I18n.string("gui_enchantment.requires_bookshelf", player.getLocale(), Map.of( "power", String.valueOf(enchantmentType.getEnchFromTable().getRequiredBookshelfPower()) ))); } else { - lore.add(I18n.string("gui_enchantment.click_to_view")); + lore.add(I18n.string("gui_enchantment.click_to_view", player.getLocale())); } return ItemStackCreator.getStack( @@ -300,7 +296,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { if (selected.getEnch() instanceof ConflictingEnch conflictingEnch) { for (EnchantmentType ench : conflictingEnch.getConflictingEnchantments()) { if (item.getAttributeHandler().hasEnchantment(ench)) { - lore.add(I18n.string("gui_enchantment.warning_remove_conflicting", Map.of( + lore.add(I18n.string("gui_enchantment.warning_remove_conflicting", player.getLocale(), Map.of( "enchantment", StringUtility.toNormalCase(ench.name()) ))); break; @@ -309,19 +305,19 @@ public ItemStack.Builder getItem(HypixelPlayer p) { } if (finalHasLevel == finalLevel) { - lore.addAll(I18n.lore("gui_enchantment.already_present")); + lore.addAll(I18n.lore("gui_enchantment.already_present", player.getLocale())); lore.add("§a "); } - lore.add(I18n.string("gui_enchantment.cost_label")); + lore.add(I18n.string("gui_enchantment.cost_label", player.getLocale())); if (finalHasLevel > finalLevel) { if (levelCost > player.getLevel()) - lore.add(I18n.string("gui_enchantment.cost_exp_levels_fail", Map.of("cost", String.valueOf(levelCost)))); - else lore.add(I18n.string("gui_enchantment.cost_exp_levels_pass", Map.of("cost", String.valueOf(levelCost)))); + lore.add(I18n.string("gui_enchantment.cost_exp_levels_fail", player.getLocale(), Map.of("cost", String.valueOf(levelCost)))); + else lore.add(I18n.string("gui_enchantment.cost_exp_levels_pass", player.getLocale(), Map.of("cost", String.valueOf(levelCost)))); lore.add("§a "); - lore.add(I18n.string("gui_enchantment.higher_level_present")); + lore.add(I18n.string("gui_enchantment.higher_level_present", player.getLocale())); return ItemStackCreator.getStack( "§9" + selected.getName() + " " + StringUtility.getAsRomanNumeral(finalLevel), Material.GRAY_DYE, 1, @@ -330,16 +326,16 @@ public ItemStack.Builder getItem(HypixelPlayer p) { } if (levelCost > player.getLevel()) { - lore.add(I18n.string("gui_enchantment.cost_exp_levels_fail", Map.of("cost", String.valueOf(levelCost)))); + lore.add(I18n.string("gui_enchantment.cost_exp_levels_fail", player.getLocale(), Map.of("cost", String.valueOf(levelCost)))); lore.add("§a "); - lore.add(I18n.string("gui_enchantment.insufficient_levels")); + lore.add(I18n.string("gui_enchantment.insufficient_levels", player.getLocale())); } else { - lore.add(I18n.string("gui_enchantment.cost_exp_levels_pass", Map.of("cost", String.valueOf(levelCost)))); + lore.add(I18n.string("gui_enchantment.cost_exp_levels_pass", player.getLocale(), Map.of("cost", String.valueOf(levelCost)))); lore.add("§a "); if (finalHasLevel >= finalLevel) { - lore.add(I18n.string("gui_enchantment.click_to_remove")); + lore.add(I18n.string("gui_enchantment.click_to_remove", player.getLocale())); } else { - lore.add(I18n.string("gui_enchantment.click_to_enchant")); + lore.add(I18n.string("gui_enchantment.click_to_enchant", player.getLocale())); } } @@ -362,7 +358,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { String itemName = StringUtility.toNormalCase(type.name()); if (player.getLevel() < selected.getEnchFromTable().getLevelsFromTableToApply(player).get(finalLevel)) { - player.sendMessage(I18n.string("gui_enchantment.insufficient_levels_message")); + player.sendMessage(I18n.string("gui_enchantment.insufficient_levels_message", player.getLocale())); return; } @@ -380,7 +376,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { } player.setLevel(player.getLevel() - selected.getEnchFromTable().getLevelsFromTableToApply(player).get(finalLevel)); - player.sendMessage(I18n.string("gui_enchantment.enchanted_message", Map.of( + player.sendMessage(I18n.string("gui_enchantment.enchanted_message", player.getLocale(), Map.of( "item_name", itemName, "enchantment", StringUtility.toNormalCase(selected.name()), "level", StringUtility.getAsRomanNumeral(finalLevel) @@ -395,7 +391,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { } player.setLevel(player.getLevel() - selected.getEnchFromTable().getLevelsFromTableToApply(player).get(finalLevel)); - player.sendMessage(I18n.string("gui_enchantment.removed_message", Map.of( + player.sendMessage(I18n.string("gui_enchantment.removed_message", player.getLocale(), Map.of( "enchantment", StringUtility.toNormalCase(selected.name()), "item_name", itemName ))); @@ -417,7 +413,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; return ItemStackCreator.createNamedItemStack( - Material.ARROW, I18n.string("gui_enchantment.go_back") + Material.ARROW, I18n.string("gui_enchantment.go_back", p.getLocale()) ); } }); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIMinion.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIMinion.java index 4f8747a32..c17b49cb4 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIMinion.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIMinion.java @@ -12,6 +12,7 @@ import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; @@ -39,6 +40,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIMinion extends HypixelInventoryGUI implements RefreshingGUI { @@ -68,7 +70,7 @@ public void onOpen(InventoryGUIOpenEvent e) { if (net.swofty.type.generic.gui.inventory.HypixelInventoryGUI.GUI_MAP.containsKey(member.getUuid())) { if (net.swofty.type.generic.gui.inventory.HypixelInventoryGUI.GUI_MAP.get(member.getUuid()) instanceof GUIMinion) { e.player().closeInventory(); - e.player().sendMessage(I18n.string("gui_minion.coop_member_open")); + e.player().sendMessage(I18n.string("gui_minion.coop_member_open", e.player().getLocale())); } } }); @@ -100,7 +102,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { minion.removeMinion(); player.getSkyBlockIsland().getMinionData().getMinions().remove(minion); - player.sendMessage(I18n.string("gui_minion.pickup_message", Map.of( + player.sendMessage(I18n.string("gui_minion.pickup_message", player.getLocale(), Map.of( "current", String.valueOf(player.getSkyBlockIsland().getMinionData().getMinions().size()), "max", String.valueOf(player.getSkyblockDataHandler().get( SkyBlockDataHandler.Data.MINION_DATA, @@ -111,8 +113,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_minion.pickup_button"), Material.BEDROCK, 1, - I18n.lore("gui_minion.pickup_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_minion.pickup_button", Material.BEDROCK, 1, + "gui_minion.pickup_button.lore"); } }); @@ -121,7 +123,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; if (minion.getItemsInMinion().isEmpty()) { - player.sendMessage(I18n.string("gui_minion.no_items_stored")); + player.sendMessage(I18n.string("gui_minion.no_items_stored", player.getLocale())); return; } @@ -139,8 +141,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_minion.collect_all_button"), Material.CHEST, 1, - I18n.lore("gui_minion.collect_all_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_minion.collect_all_button", Material.CHEST, 1, + "gui_minion.collect_all_button.lore"); } }); @@ -153,8 +155,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_minion.ideal_layout"), Material.REDSTONE_TORCH, 1, - I18n.lore("gui_minion.ideal_layout.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_minion.ideal_layout", Material.REDSTONE_TORCH, 1, + "gui_minion.ideal_layout.lore"); } }); @@ -188,13 +190,13 @@ public ItemStack.Builder getItem(HypixelPlayer p) { int speedPercentage = minion.getSpeedPercentage(); final DecimalFormat formatter = new DecimalFormat("#.##"); - return ItemStackCreator.getStack(I18n.string("gui_minion.next_tier"), Material.GOLD_INGOT, 1, - I18n.lore("gui_minion.next_tier.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_minion.next_tier", Material.GOLD_INGOT, 1, + "gui_minion.next_tier.lore", Map.of( "current_time", formatter.format(minionTiers.get(minion.getTier() - 1).timeBetweenActions() / (1. + speedPercentage / 100.)), "next_time", formatter.format(minionTiers.get(minion.getTier()).timeBetweenActions() / (1. + speedPercentage / 100.)), "current_storage", String.valueOf(minionTiers.get(minion.getTier() - 1).storage()), "next_storage", String.valueOf(minionTiers.get(minion.getTier()).storage()) - ))); + )); } }); @@ -257,7 +259,7 @@ public void refreshItems(HypixelPlayer p) { public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; if (!p.getInventory().getCursorItem().isAir()) { - player.sendMessage(I18n.string("gui_minion.cant_put_items")); + player.sendMessage(I18n.string("gui_minion.cant_put_items", p.getLocale())); e.setCancelled(true); return; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIReforge.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIReforge.java index 39cb574dc..312e1492f 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIReforge.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIReforge.java @@ -14,6 +14,7 @@ import net.swofty.commons.skyblock.item.reforge.ReforgeType; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -26,6 +27,7 @@ import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIReforge extends HypixelInventoryGUI { @@ -88,15 +90,14 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_reforge.place_item_message")); + player.sendMessage(I18n.string("gui_reforge.place_item_message", player.getLocale())); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_reforge.reforge_button_empty"), Material.ANVIL, 1, - I18n.lore("gui_reforge.reforge_button_empty.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_reforge.reforge_button_empty", Material.ANVIL, 1, + "gui_reforge.reforge_button_empty.lore"); } }); updateItemStacks(getInventory(), getPlayer()); @@ -133,9 +134,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_reforge.error_cannot_reforge"), Material.BARRIER, 1, - I18n.lore("gui_reforge.error_cannot_reforge.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_reforge.error_cannot_reforge", Material.BARRIER, 1, + "gui_reforge.error_cannot_reforge.lore"); } }); updateItemStacks(getInventory(), getPlayer()); @@ -151,9 +151,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_reforge.error_no_reforges"), Material.BARRIER, 1, - I18n.lore("gui_reforge.error_no_reforges.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_reforge.error_no_reforges", Material.BARRIER, 1, + "gui_reforge.error_no_reforges.lore"); } }); updateItemStacks(getInventory(), getPlayer()); @@ -168,7 +167,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { int cost = COST_MAP.get(item.getAttributeHandler().getRarity()); if (player.getCoins() - cost < 0) { - player.sendMessage(I18n.string("gui_reforge.not_enough_coins")); + player.sendMessage(I18n.string("gui_reforge.not_enough_coins", player.getLocale())); return; } @@ -178,7 +177,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { List availableReforges = ReforgeLoader.getReforgesForType(itemReforgeType); if (availableReforges.isEmpty()) { - player.sendMessage(I18n.string("gui_reforge.no_reforges_available")); + player.sendMessage(I18n.string("gui_reforge.no_reforges_available", player.getLocale())); return; } @@ -197,7 +196,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { String itemName = StringUtility.toNormalCase(item.getAttributeHandler().getTypeAsString()); - player.sendMessage(I18n.string("gui_reforge.success_message", Map.of( + player.sendMessage(I18n.string("gui_reforge.success_message", player.getLocale(), Map.of( "old_name", item.getAttributeHandler().getRarity().getColor() + oldPrefix, "item_name", itemName, "new_name", item.getAttributeHandler().getRarity().getColor() + " " + selectedReforge.getPrefix() @@ -209,11 +208,10 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_reforge.reforge_button"), Material.ANVIL, 1, - I18n.lore("gui_reforge.reforge_button.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_reforge.reforge_button", Material.ANVIL, 1, + "gui_reforge.reforge_button.lore", Map.of( "cost", String.valueOf(COST_MAP.get(item.getAttributeHandler().getRarity())) - ))); + )); } }); updateItemStacks(getInventory(), getPlayer()); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIViewPlayerProfile.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIViewPlayerProfile.java index a297794c1..2032bce4c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIViewPlayerProfile.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/GUIViewPlayerProfile.java @@ -12,6 +12,7 @@ import net.swofty.type.generic.data.datapoints.DatapointString; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -24,6 +25,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIViewPlayerProfile extends HypixelInventoryGUI { @@ -46,7 +48,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { if (!viewedPlayer.getItemInMainHand().isAir()) { return ItemStackCreator.getFromStack(viewedPlayer.getItemInMainHand()); } else { - return ItemStackCreator.getStack(I18n.string("gui_profile.empty_held_item"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return ItemStackCreator.getStack(I18n.string("gui_profile.empty_held_item", p.getLocale()), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } } }); @@ -57,7 +59,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { if (!viewedPlayer.getHelmet().isAir()) { return ItemStackCreator.getFromStack(viewedPlayer.getHelmet()); } else { - return ItemStackCreator.getStack(I18n.string("gui_profile.empty_helmet"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return ItemStackCreator.getStack(I18n.string("gui_profile.empty_helmet", p.getLocale()), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } } }); @@ -68,7 +70,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { if (!viewedPlayer.getChestplate().isAir()) { return ItemStackCreator.getFromStack(viewedPlayer.getChestplate()); } else { - return ItemStackCreator.getStack(I18n.string("gui_profile.empty_chestplate"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return ItemStackCreator.getStack(I18n.string("gui_profile.empty_chestplate", p.getLocale()), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } } }); @@ -79,7 +81,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { if (!viewedPlayer.getLeggings().isAir()) { return ItemStackCreator.getFromStack(viewedPlayer.getLeggings()); } else { - return ItemStackCreator.getStack(I18n.string("gui_profile.empty_leggings"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return ItemStackCreator.getStack(I18n.string("gui_profile.empty_leggings", p.getLocale()), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } } }); @@ -90,7 +92,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { if (!viewedPlayer.getBoots().isAir()) { return ItemStackCreator.getFromStack(viewedPlayer.getBoots()); } else { - return ItemStackCreator.getStack(I18n.string("gui_profile.empty_boots"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return ItemStackCreator.getStack(I18n.string("gui_profile.empty_boots", p.getLocale()), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } } }); @@ -101,7 +103,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockItem pet = viewedPlayer.getPetData().getEnabledPet(); return new NonPlayerItemUpdater(pet).getUpdatedItem(); } else { - return ItemStackCreator.getStack(I18n.string("gui_profile.empty_pet"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return ItemStackCreator.getStack(I18n.string("gui_profile.empty_pet", p.getLocale()), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } } }); @@ -113,9 +115,10 @@ public ItemStack.Builder getItem(HypixelPlayer p) { List lore = new ArrayList<>(List.of()); lore.add("§7 "); - lore.add(I18n.string("gui_profile.skyblock_level", Map.of("level", viewedPlayer.getSkyBlockExperience().getLevel().getColor() + viewedPlayer.getSkyBlockExperience().getLevel().toString()))); + Locale l = p.getLocale(); + lore.add(I18n.string("gui_profile.skyblock_level", l, Map.of("level", viewedPlayer.getSkyBlockExperience().getLevel().getColor() + viewedPlayer.getSkyBlockExperience().getLevel().toString()))); lore.add("§7 "); - lore.add(I18n.string("gui_profile.oldest_profile", Map.of("age", age))); + lore.add(I18n.string("gui_profile.oldest_profile", l, Map.of("age", age))); return ItemStackCreator.getStackHead(viewedPlayer.getShortenedDisplayName(), PlayerSkin.fromUuid(viewedPlayer.getUuid().toString()), 1, @@ -126,25 +129,26 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_profile.feature_not_added")); + player.sendMessage(I18n.string("gui_profile.feature_not_added", player.getLocale())); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { List lore = new ArrayList<>(List.of()); SkyBlockDataHandler dataHandler = viewedPlayer.getSkyblockDataHandler(); + Locale l = p.getLocale(); String name; Material material; if (dataHandler.get(SkyBlockDataHandler.Data.SKYBLOCK_EXPERIENCE, DatapointSkyBlockExperience.class).getValue().getCurrentEmblem() != null) { - name = I18n.string("gui_profile.emblem_selected", Map.of("emblem", dataHandler.get(SkyBlockDataHandler.Data.SKYBLOCK_EXPERIENCE, DatapointSkyBlockExperience.class).getValue().getCurrentEmblem().toString())); + name = I18n.string("gui_profile.emblem_selected", l, Map.of("emblem", dataHandler.get(SkyBlockDataHandler.Data.SKYBLOCK_EXPERIENCE, DatapointSkyBlockExperience.class).getValue().getCurrentEmblem().toString())); material = dataHandler.get(SkyBlockDataHandler.Data.SKYBLOCK_EXPERIENCE, DatapointSkyBlockExperience.class).getValue().getEmblem().displayMaterial(); } else { - name = I18n.string("gui_profile.no_emblem"); + name = I18n.string("gui_profile.no_emblem", l); material = Material.BARRIER; - lore.addAll(I18n.lore("gui_profile.no_emblem.lore")); + lore.addAll(I18n.lore("gui_profile.no_emblem.lore", l)); } lore.add(" "); - lore.add(I18n.string("gui_profile.click_view_emblems")); + lore.add(I18n.string("gui_profile.click_view_emblems", l)); return ItemStackCreator.getStack(name, material, 1, lore); } }); @@ -152,79 +156,79 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_profile.feature_not_added")); + player.sendMessage(I18n.string("gui_profile.feature_not_added", player.getLocale())); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_profile.visit_island"), Material.FEATHER, 1, - I18n.lore("gui_profile.visit_island.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_profile.visit_island", Material.FEATHER, 1, + "gui_profile.visit_island.lore"); } }); set(new GUIClickableItem(16) { //Trade Request @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_profile.feature_not_added")); + player.sendMessage(I18n.string("gui_profile.feature_not_added", player.getLocale())); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_profile.trade_request"), Material.EMERALD, 1, - I18n.lore("gui_profile.trade_request.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_profile.trade_request", Material.EMERALD, 1, + "gui_profile.trade_request.lore"); } }); set(new GUIClickableItem(24) { //Invite to Island @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_profile.feature_not_added")); + player.sendMessage(I18n.string("gui_profile.feature_not_added", player.getLocale())); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_profile.invite_to_island"), Material.POPPY, 1, - I18n.lore("gui_profile.invite_to_island.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_profile.invite_to_island", Material.POPPY, 1, + "gui_profile.invite_to_island.lore"); } }); set(new GUIClickableItem(25) { //Coop Request @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_profile.feature_not_added")); + player.sendMessage(I18n.string("gui_profile.feature_not_added", player.getLocale())); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_profile.coop_request"), Material.DIAMOND, 1, - I18n.lore("gui_profile.coop_request.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_profile.coop_request", Material.DIAMOND, 1, + "gui_profile.coop_request.lore"); } }); set(new GUIClickableItem(33) { //Personal Vault @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_profile.feature_not_added")); + player.sendMessage(I18n.string("gui_profile.feature_not_added", player.getLocale())); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_profile.personal_vault"), Material.ENDER_CHEST, 1, - I18n.lore("gui_profile.personal_vault.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_profile.personal_vault", Material.ENDER_CHEST, 1, + "gui_profile.personal_vault.lore"); } }); set(new GUIClickableItem(34) { //Museum @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_profile.feature_not_added")); + player.sendMessage(I18n.string("gui_profile.feature_not_added", player.getLocale())); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockDataHandler dataHandler = viewedPlayer.getSkyblockDataHandler(); String profileName = dataHandler.get(SkyBlockDataHandler.Data.PROFILE_NAME, DatapointString.class).getValue(); - List lore = new ArrayList<>(I18n.lore("gui_profile.museum.lore", Map.of("profile_name", profileName))); + List lore = new ArrayList<>(I18n.lore("gui_profile.museum.lore", p.getLocale(), Map.of("profile_name", profileName))); return ItemStackCreator.getStackHead(viewedPlayer.getUsername() + "'s Museum", PlayerSkin.fromUuid(viewedPlayer.getUuid().toString()), 1, lore); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIAbiphone.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIAbiphone.java index 418401e19..e89030566 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIAbiphone.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIAbiphone.java @@ -12,6 +12,7 @@ import net.minestom.server.timer.TaskSchedule; import net.swofty.type.generic.gui.inventory.HypixelPaginatedGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -22,6 +23,7 @@ import net.swofty.type.skyblockgeneric.item.SkyBlockItem; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIAbiphone extends HypixelPaginatedGUI { @@ -64,23 +66,16 @@ protected void performSearch(HypixelPlayer player, String query, int page, int m set(new GUIItem(50) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack( - I18n.string("gui_abiphone.sort_button"), - Material.HOPPER, - 1, - I18n.lore("gui_abiphone.sort_button.lore")); + return TranslatableItemStackCreator.getStack(player, "gui_abiphone.sort_button", Material.HOPPER, 1, "gui_abiphone.sort_button.lore"); } }); set(new GUIItem(51) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack( - I18n.string("gui_abiphone.contacts_directory"), - Material.BOOK, - 1, - I18n.lore("gui_abiphone.contacts_directory.lore", Map.of( + return TranslatableItemStackCreator.getStack(player, "gui_abiphone.contacts_directory", Material.BOOK, 1, + "gui_abiphone.contacts_directory.lore", Map.of( "contact_count", String.valueOf(contacts.size()), - "total_contacts", String.valueOf(AbiphoneRegistry.getRegisteredContactNPCs().size())))); + "total_contacts", String.valueOf(AbiphoneRegistry.getRegisteredContactNPCs().size()))); } }); @@ -102,14 +97,15 @@ protected GUIClickableItem createItemFor(AbiphoneNPC npc, int slot, HypixelPlaye return new GUIClickableItem(slot) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer player) { + Locale l = player.getLocale(); Click click = e.getClick(); if (click instanceof Click.Left) { player.closeInventory(); - player.sendMessage(Component.text(I18n.string("gui_abiphone.ring_1"))); + player.sendMessage(Component.text(I18n.string("gui_abiphone.ring_1", l))); MinecraftServer.getSchedulerManager().buildTask(() -> { - player.sendMessage(Component.text(I18n.string("gui_abiphone.ring_2"))); + player.sendMessage(Component.text(I18n.string("gui_abiphone.ring_2", l))); MinecraftServer.getSchedulerManager().buildTask(() -> { - player.sendMessage(Component.text(I18n.string("gui_abiphone.ring_3"))); + player.sendMessage(Component.text(I18n.string("gui_abiphone.ring_3", l))); MinecraftServer.getSchedulerManager().buildTask(() -> { npc.onCall(player); }).delay(TaskSchedule.seconds(1)).schedule(); @@ -122,13 +118,14 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { + Locale l = player.getLocale(); return ItemStackCreator.updateLore( npc.getIcon().set(DataComponents.CUSTOM_NAME, Component.text("§f" + npc.getName())), List.of( "§7" + npc.getDescription(), "", - I18n.string("gui_abiphone.contact_manage_hint"), - I18n.string("gui_abiphone.contact_call_hint") + I18n.string("gui_abiphone.contact_manage_hint", l), + I18n.string("gui_abiphone.contact_call_hint", l) ) ); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIConfirmAbiphone.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIConfirmAbiphone.java index 15c763b10..5cc2e1b5f 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIConfirmAbiphone.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIConfirmAbiphone.java @@ -6,11 +6,13 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.abiphone.AbiphoneNPC; +import java.util.Locale; import java.util.Map; public class GUIConfirmAbiphone extends HypixelInventoryGUI { @@ -34,8 +36,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack(I18n.string("gui_abiphone.confirm.confirm_button"), Material.GREEN_TERRACOTTA, 1, - I18n.lore("gui_abiphone.confirm.confirm_button.lore", Map.of("npc_name", npc.getName()))); + return TranslatableItemStackCreator.getStack(player, "gui_abiphone.confirm.confirm_button", Material.GREEN_TERRACOTTA, 1, + "gui_abiphone.confirm.confirm_button.lore", Map.of("npc_name", npc.getName())); } }); set(new GUIClickableItem(15) { @@ -46,7 +48,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.createNamedItemStack(Material.RED_TERRACOTTA, I18n.string("gui_abiphone.confirm.cancel_button")); + Locale l = player.getLocale(); + return ItemStackCreator.createNamedItemStack(Material.RED_TERRACOTTA, I18n.string("gui_abiphone.confirm.cancel_button", l)); } }); updateItemStacks(getInventory(), getPlayer()); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIContactManagement.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIContactManagement.java index e81d3cc50..8bed70ae5 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIContactManagement.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/abiphone/GUIContactManagement.java @@ -9,6 +9,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -17,6 +18,7 @@ import net.swofty.type.skyblockgeneric.item.SkyBlockItem; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIContactManagement extends HypixelInventoryGUI { @@ -47,18 +49,19 @@ public ItemStack.Builder getItem(HypixelPlayer player) { set(new GUIClickableItem(31) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer player) { + Locale l = player.getLocale(); new GUIConfirmAbiphone(npc, () -> { abiphone.getAttributeHandler().removeAbiphoneNPC(npc); player.closeInventory(); new GUIAbiphone(abiphone).open(player); - player.sendMessage(I18n.string("gui_abiphone.management.removed_message", Map.of("npc_name", npc.getName()))); + player.sendMessage(I18n.string("gui_abiphone.management.removed_message", l, Map.of("npc_name", npc.getName()))); }).open(player); } @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack(I18n.string("gui_abiphone.management.remove_contact"), Material.FEATHER, 1, - I18n.lore("gui_abiphone.management.remove_contact.lore")); + return TranslatableItemStackCreator.getStack(player, "gui_abiphone.management.remove_contact", Material.FEATHER, 1, + "gui_abiphone.management.remove_contact.lore"); } }); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionBrowser.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionBrowser.java index 57b42dfd5..572c7ae49 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionBrowser.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionBrowser.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; @Setter @@ -89,7 +90,7 @@ private void updateItemsCache() { private void setItems() { fill(ItemStackCreator.createNamedItemStack(category.getMaterial(), "")); set(GUIClickableItem.getGoBackItem(49, new GUIAuctionHouse())); - getInventory().setTitle(Component.text(I18n.string("gui_auction.browser.title_with_category", Map.of("category", StringUtility.toNormalCase(category.name()))))); + getInventory().setTitle(Component.text(I18n.string("gui_auction.browser.title_with_category", getPlayer().getLocale(), Map.of("category", StringUtility.toNormalCase(category.name()))))); set(new GUIClickableItem(50) { @Override @@ -111,10 +112,10 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(List.of(" ")); Arrays.stream(AuctionsSorting.values()).forEach(sort -> { - // Ensure to not display the MOST_BIDS sorting if the filter is BIN_ONLY if (filter.equals(AuctionsFilter.BIN_ONLY)) { if (sort.equals(AuctionsSorting.MOST_BIDS)) { return; @@ -122,16 +123,16 @@ public ItemStack.Builder getItem(HypixelPlayer p) { } if (sort == sorting) { - lore.add(I18n.string("gui_auction.browser.sort_selected_prefix") + StringUtility.toNormalCase(sort.name())); + lore.add(I18n.string("gui_auction.browser.sort_selected_prefix", l) + StringUtility.toNormalCase(sort.name())); } else { - lore.add(I18n.string("gui_auction.browser.sort_unselected_prefix") + StringUtility.toNormalCase(sort.name())); + lore.add(I18n.string("gui_auction.browser.sort_unselected_prefix", l) + StringUtility.toNormalCase(sort.name())); } }); lore.add(" "); - lore.add(I18n.string("gui_auction.browser.sort_click")); + lore.add(I18n.string("gui_auction.browser.sort_click", l)); - return ItemStackCreator.getStack(I18n.string("gui_auction.browser.sort_button"), Material.HOPPER, 1, + return ItemStackCreator.getStack(I18n.string("gui_auction.browser.sort_button", l), Material.HOPPER, 1, lore); } }); @@ -154,21 +155,22 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(List.of(" ")); Arrays.stream(AuctionsFilter.values()).forEach(filter -> { if (filter == GUIAuctionBrowser.this.filter) { - lore.add(I18n.string("gui_auction.browser.filter_selected_prefix") + StringUtility.toNormalCase(filter.name())); + lore.add(I18n.string("gui_auction.browser.filter_selected_prefix", l) + StringUtility.toNormalCase(filter.name())); } else { - lore.add(I18n.string("gui_auction.browser.filter_unselected_prefix") + StringUtility.toNormalCase(filter.name())); + lore.add(I18n.string("gui_auction.browser.filter_unselected_prefix", l) + StringUtility.toNormalCase(filter.name())); } }); lore.add(" "); - lore.add(I18n.string("gui_auction.browser.filter_right_click")); - lore.add(I18n.string("gui_auction.browser.filter_click")); + lore.add(I18n.string("gui_auction.browser.filter_right_click", l)); + lore.add(I18n.string("gui_auction.browser.filter_click", l)); - return ItemStackCreator.getStack(I18n.string("gui_auction.browser.filter_button"), Material.GOLD_BLOCK, 1, + return ItemStackCreator.getStack(I18n.string("gui_auction.browser.filter_button", l), Material.GOLD_BLOCK, 1, lore); } }); @@ -189,14 +191,15 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - List lore = new ArrayList<>(List.of(I18n.string("gui_auction.browser.category_subtitle"), " ", I18n.string("gui_auction.browser.category_examples"))); - category.getExamples().forEach(example -> lore.add(I18n.string("gui_auction.browser.category_example_prefix") + example)); + Locale l = p.getLocale(); + List lore = new ArrayList<>(List.of(I18n.string("gui_auction.browser.category_subtitle", l), " ", I18n.string("gui_auction.browser.category_examples", l))); + category.getExamples().forEach(example -> lore.add(I18n.string("gui_auction.browser.category_example_prefix", l) + example)); lore.add(" "); if (category.equals(getCategory())) { - lore.add(I18n.string("gui_auction.browser.category_browsing")); + lore.add(I18n.string("gui_auction.browser.category_browsing", l)); } else { - lore.add(I18n.string("gui_auction.browser.category_click")); + lore.add(I18n.string("gui_auction.browser.category_click", l)); } return ItemStackCreator.getStack(category.getColor() + StringUtility.toNormalCase(category.name()), category.getDisplayMaterial(), 1, lore); @@ -274,7 +277,7 @@ public void onBottomClick(InventoryPreClickEvent e) { @Override public void refreshItems(HypixelPlayer player) { if (!new ProxyService(ServiceType.AUCTION_HOUSE).isOnline().join()) { - player.sendMessage(I18n.string("gui_auction.browser.offline_message")); + player.sendMessage(I18n.string("gui_auction.browser.offline_message", player.getLocale())); player.closeInventory(); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionCreateItem.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionCreateItem.java index 564a2efbd..75f2999bc 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionCreateItem.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionCreateItem.java @@ -18,6 +18,7 @@ import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIQueryItem; import net.swofty.type.generic.i18n.I18n; @@ -31,6 +32,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -51,15 +53,16 @@ public void onOpen(InventoryGUIOpenEvent e) { DatapointAuctionEscrow.AuctionEscrow escrow = ((SkyBlockPlayer) getPlayer()).getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ESCROW, DatapointAuctionEscrow.class).getValue(); if (escrow.isBin()) - e.inventory().setTitle(Component.text(I18n.string("gui_auction.create.title_bin"))); + e.inventory().setTitle(Component.text(I18n.string("gui_auction.create.title_bin", getPlayer().getLocale()))); set(new GUIClickableItem(13) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); if (escrow.getItem() == null) - return ItemStackCreator.getStack(I18n.string("gui_auction.create.select_item"), Material.STONE_BUTTON, 1, - I18n.lore("gui_auction.create.select_item.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.create.select_item", Material.STONE_BUTTON, 1, + "gui_auction.create.select_item.lore"); SkyBlockItem item = escrow.getItem(); ItemStack itemStack = new NonPlayerItemUpdater(item).getUpdatedItem().build(); @@ -71,9 +74,9 @@ public ItemStack.Builder getItem(HypixelPlayer p) { lore.add(StringUtility.getTextFromComponent(loreEntry)); }); lore.add(" "); - lore.add(I18n.string("gui_auction.create.auction_for_item_pickup")); + lore.add(I18n.string("gui_auction.create.auction_for_item_pickup", l)); - return ItemStackCreator.getStack(I18n.string("gui_auction.create.auction_for_item"), itemStack.material(), itemStack.amount(), lore); + return ItemStackCreator.getStack(I18n.string("gui_auction.create.auction_for_item", l), itemStack.material(), itemStack.amount(), lore); } @Override @@ -97,18 +100,19 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); if (escrow.isBin()) { - lore.addAll(I18n.lore("gui_auction.create.duration_bin.lore")); + lore.addAll(I18n.lore("gui_auction.create.duration_bin.lore", l)); } else { - lore.addAll(I18n.lore("gui_auction.create.duration_normal.lore")); + lore.addAll(I18n.lore("gui_auction.create.duration_normal.lore", l)); } lore.add(" "); - lore.add(I18n.string("gui_auction.create.duration_extra_fee", Map.of("fee", String.valueOf(escrow.getDuration() / 180000)))); + lore.add(I18n.string("gui_auction.create.duration_extra_fee", l, Map.of("fee", String.valueOf(escrow.getDuration() / 180000)))); lore.add(" "); - lore.add(I18n.string("gui_auction.create.duration_click")); + lore.add(I18n.string("gui_auction.create.duration_click", l)); - return ItemStackCreator.getStack(I18n.string("gui_auction.create.duration_label", Map.of("duration", StringUtility.getAuctionSetupFormattedTime(escrow.getDuration()))), + return ItemStackCreator.getStack(I18n.string("gui_auction.create.duration_label", l, Map.of("duration", StringUtility.getAuctionSetupFormattedTime(escrow.getDuration()))), Material.CLOCK, 1, lore); } }); @@ -124,11 +128,11 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; if (escrow.isBin()) { - return ItemStackCreator.getStack(I18n.string("gui_auction.create.switch_to_auction"), Material.POWERED_RAIL, 1, - I18n.lore("gui_auction.create.switch_to_auction.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.create.switch_to_auction", Material.POWERED_RAIL, 1, + "gui_auction.create.switch_to_auction.lore"); } else { - return ItemStackCreator.getStack(I18n.string("gui_auction.create.switch_to_bin"), Material.GOLD_INGOT, 1, - I18n.lore("gui_auction.create.switch_to_bin.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.create.switch_to_bin", Material.GOLD_INGOT, 1, + "gui_auction.create.switch_to_bin.lore"); } } }); @@ -138,6 +142,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; ProxyService auctionService = new ProxyService(ServiceType.AUCTION_HOUSE); + Locale l = player.getLocale(); auctionService.isOnline().thenAccept((response) -> { if (escrow.getItem() == null || !response) return; @@ -145,14 +150,14 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { long fee = (long) ((escrow.getPrice() * 0.05) + ((double) escrow.getDuration() / 180000)); DatapointDouble coins = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class); if (coins.getValue() < fee) { - player.sendMessage(I18n.string("gui_auction.create.not_enough_coins")); + player.sendMessage(I18n.string("gui_auction.create.not_enough_coins", l)); return; } coins.setValue(coins.getValue() - fee); player.closeInventory(); - player.sendMessage(I18n.string("gui_auction.create.escrow_message")); + player.sendMessage(I18n.string("gui_auction.create.escrow_message", l)); ItemStack builtItem = new NonPlayerItemUpdater(escrow.getItem()).getUpdatedItem().build(); AuctionItem item = new AuctionItem(escrow.getItem().toUnderstandable(), player.getUuid(), escrow.getDuration() + System.currentTimeMillis(), @@ -166,7 +171,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ESCROW, DatapointAuctionEscrow.class).clearEscrow(); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ACTIVE_OWNED, DatapointUUIDList.class).getValue().add(item.getUuid()); - player.sendMessage(I18n.string("gui_auction.create.setup_message")); + player.sendMessage(I18n.string("gui_auction.create.setup_message", l)); AuctionAddItemProtocolObject.AuctionAddItemMessage message = new AuctionAddItemProtocolObject.AuctionAddItemMessage(item, category); @@ -174,27 +179,28 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { auctionService.handleRequest(message); UUID auctionUUID = future.join().uuid(); - player.sendMessage(I18n.string("gui_auction.create.started_message", Map.of("item_name", itemName))); - player.sendMessage(I18n.string("gui_auction.create.started_id", Map.of("uuid", auctionUUID.toString()))); + player.sendMessage(I18n.string("gui_auction.create.started_message", l, Map.of("item_name", itemName))); + player.sendMessage(I18n.string("gui_auction.create.started_id", l, Map.of("uuid", auctionUUID.toString()))); }); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); if (escrow.getItem() == null) { - return ItemStackCreator.getStack(I18n.string("gui_auction.create.submit_no_item"), Material.RED_TERRACOTTA, 1, - I18n.lore("gui_auction.create.submit_no_item.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.create.submit_no_item", Material.RED_TERRACOTTA, 1, + "gui_auction.create.submit_no_item.lore"); } else { ItemStack builtItem = new NonPlayerItemUpdater(escrow.getItem()).getUpdatedItem().build(); return ItemStackCreator.getStack( - I18n.string("gui_auction.create.submit_ready", Map.of("type", escrow.isBin() ? "Bin " : "")), + I18n.string("gui_auction.create.submit_ready", l, Map.of("type", escrow.isBin() ? "Bin " : "")), Material.GREEN_TERRACOTTA, 1, - I18n.lore("gui_auction.create.submit_ready.lore", Map.of( + I18n.lore("gui_auction.create.submit_ready.lore", l, Map.of( "item_name", StringUtility.getTextFromComponent(builtItem.get(DataComponents.CUSTOM_NAME)), "duration", StringUtility.getAuctionSetupFormattedTime(escrow.getDuration()), - "price_label", escrow.isBin() ? I18n.string("gui_auction.create.price_bin_label") : I18n.string("gui_auction.create.price_normal_label"), + "price_label", escrow.isBin() ? I18n.string("gui_auction.create.price_bin_label", l) : I18n.string("gui_auction.create.price_normal_label", l), "price", StringUtility.commaify(escrow.getPrice()), "fee", String.valueOf((escrow.getPrice() * 0.05) + (escrow.getDuration() / 180000)) ))); @@ -205,18 +211,18 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer player) { - long l; + long val; try { - l = Long.parseLong(query); + val = Long.parseLong(query); } catch (NumberFormatException ex) { - player.sendMessage(I18n.string("gui_auction.create.number_parse_error")); + player.sendMessage(I18n.string("gui_auction.create.number_parse_error", player.getLocale())); return GUIAuctionCreateItem.this; } - if (l <= 50) { - player.sendMessage(I18n.string("gui_auction.create.price_too_low")); + if (val <= 50) { + player.sendMessage(I18n.string("gui_auction.create.price_too_low", player.getLocale())); return GUIAuctionCreateItem.this; } - escrow.setPrice(l); + escrow.setPrice(val); return GUIAuctionCreateItem.this; } @@ -224,23 +230,24 @@ public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); Material material; List lore = new ArrayList<>(); if (escrow.isBin()) { material = Material.GOLD_INGOT; - lore.addAll(I18n.lore("gui_auction.create.price_bin.lore")); + lore.addAll(I18n.lore("gui_auction.create.price_bin.lore", l)); } else { material = Material.POWERED_RAIL; - lore.addAll(I18n.lore("gui_auction.create.price_normal.lore")); + lore.addAll(I18n.lore("gui_auction.create.price_normal.lore", l)); } lore.add(" "); - lore.add(I18n.string("gui_auction.create.price_extra_fee", Map.of("fee", String.valueOf(escrow.getPrice() * 0.05)))); + lore.add(I18n.string("gui_auction.create.price_extra_fee", l, Map.of("fee", String.valueOf(escrow.getPrice() * 0.05)))); lore.add(" "); - lore.add(I18n.string("gui_auction.create.price_click")); + lore.add(I18n.string("gui_auction.create.price_click", l)); String priceKey = escrow.isBin() ? "gui_auction.create.price_label_bin" : "gui_auction.create.price_label_normal"; return ItemStackCreator.getStack( - I18n.string(priceKey, Map.of("price", StringUtility.commaify(escrow.getPrice()))), + I18n.string(priceKey, l, Map.of("price", StringUtility.commaify(escrow.getPrice()))), material, 1, lore); } }); @@ -274,7 +281,7 @@ public void onBottomClick(InventoryPreClickEvent e) { DatapointAuctionEscrow.AuctionEscrow escrow = ((SkyBlockPlayer) getPlayer()).getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ESCROW, DatapointAuctionEscrow.class).getValue(); if (escrow.getItem() != null) { - e.getPlayer().sendMessage(I18n.string("gui_auction.create.already_have_item")); + e.getPlayer().sendMessage(I18n.string("gui_auction.create.already_have_item", getPlayer().getLocale())); return; } @@ -287,7 +294,7 @@ public void onBottomClick(InventoryPreClickEvent e) { @Override public void refreshItems(HypixelPlayer player) { if (!new ProxyService(ServiceType.AUCTION_HOUSE).isOnline().join()) { - player.sendMessage(I18n.string("gui_auction.create.offline_message")); + player.sendMessage(I18n.string("gui_auction.create.offline_message", player.getLocale())); player.closeInventory(); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionDuration.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionDuration.java index 9a412478c..08ebe9210 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionDuration.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionDuration.java @@ -9,6 +9,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIQueryItem; import net.swofty.type.generic.i18n.I18n; @@ -16,6 +17,7 @@ import net.swofty.type.skyblockgeneric.data.datapoints.DatapointAuctionEscrow; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import java.util.Locale; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; @@ -39,24 +41,25 @@ public void onOpen(InventoryGUIOpenEvent e) { set(new GUIQueryItem(16) { @Override public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer player) { - long l; + Locale loc = player.getLocale(); + long val; try { - l = Long.parseLong(query); + val = Long.parseLong(query); } catch (NumberFormatException ex) { - player.sendMessage(I18n.string("gui_auction.duration.number_parse_error")); + player.sendMessage(I18n.string("gui_auction.duration.number_parse_error", loc)); return null; } - if (l <= 1) { - player.sendMessage(I18n.string("gui_auction.duration.invalid_time")); + if (val <= 1) { + player.sendMessage(I18n.string("gui_auction.duration.invalid_time", loc)); return null; } - if (l >= 336 && !right.get()) { - player.sendMessage(I18n.string("gui_auction.duration.max_exceeded")); + if (val >= 336 && !right.get()) { + player.sendMessage(I18n.string("gui_auction.duration.max_exceeded", loc)); return null; } ((SkyBlockPlayer) player).getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ESCROW, DatapointAuctionEscrow.class).getValue().setDuration( - l * (right.get() ? 60000 : 3600000) + val * (right.get() ? 60000 : 3600000) ); return new GUIAuctionCreateItem(GUIAuctionDuration.this); @@ -70,8 +73,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.duration.custom"), Material.COMPASS, 1, - I18n.lore("gui_auction.duration.custom.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.duration.custom", Material.COMPASS, 1, + "gui_auction.duration.custom.lore"); } }); @@ -105,11 +108,12 @@ private static GUIClickableItem createTime(Material color, int hours, int slot, @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); ItemStack.Builder stack = ItemStackCreator.getStack( - I18n.string("gui_auction.duration.hours", Map.of("hours", String.valueOf(hours))), + I18n.string("gui_auction.duration.hours", l, Map.of("hours", String.valueOf(hours))), color, 1, " ", - I18n.string("gui_auction.duration.hours_click")); + I18n.string("gui_auction.duration.hours_click", l)); if (user.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ESCROW, DatapointAuctionEscrow.class).getValue().getDuration() == millis) { stack = ItemStackCreator.enchant(stack); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionHouse.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionHouse.java index 822bc3bf3..a84c66958 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionHouse.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionHouse.java @@ -11,6 +11,7 @@ import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; @@ -24,7 +25,7 @@ public GUIAuctionHouse() { super(I18n.string("gui_auction.house.title"), InventoryType.CHEST_4_ROW); if (!new ProxyService(ServiceType.AUCTION_HOUSE).isOnline().join()) - fill(Material.BLACK_STAINED_GLASS_PANE, I18n.string("gui_auction.house.offline_fill")); + fill(Material.BLACK_STAINED_GLASS_PANE, ""); } @Override @@ -41,8 +42,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.house.stats_button"), Material.PAPER, 1, - I18n.lore("gui_auction.house.stats_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.house.stats_button", Material.PAPER, 1, + "gui_auction.house.stats_button.lore"); } }); @@ -56,8 +57,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.house.browser_button"), Material.GOLD_BLOCK, 1, - I18n.lore("gui_auction.house.browser_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.house.browser_button", Material.GOLD_BLOCK, 1, + "gui_auction.house.browser_button.lore"); } }); @@ -72,8 +73,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.house.create_button"), Material.GOLDEN_HORSE_ARMOR, 1, - I18n.lore("gui_auction.house.create_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.house.create_button", Material.GOLDEN_HORSE_ARMOR, 1, + "gui_auction.house.create_button.lore"); } }); } else { @@ -87,10 +88,10 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.house.manage_button"), Material.GOLDEN_HORSE_ARMOR, 1, - I18n.lore("gui_auction.house.manage_button.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.house.manage_button", Material.GOLDEN_HORSE_ARMOR, 1, + "gui_auction.house.manage_button.lore", Map.of( "count", String.valueOf(player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ACTIVE_OWNED, DatapointUUIDList.class).getValue().size()) - ))); + )); } }); } @@ -106,8 +107,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.house.bids_button"), Material.GOLDEN_CARROT, 1, - I18n.lore("gui_auction.house.bids_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.house.bids_button", Material.GOLDEN_CARROT, 1, + "gui_auction.house.bids_button.lore"); } }); } @@ -136,7 +137,7 @@ public void onBottomClick(InventoryPreClickEvent e) { @Override public void refreshItems(HypixelPlayer player) { if (!new ProxyService(ServiceType.AUCTION_HOUSE).isOnline().join()) { - player.sendMessage(I18n.string("gui_auction.house.offline_message")); + player.sendMessage(I18n.string("gui_auction.house.offline_message", player.getLocale())); player.closeInventory(); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionHouseStats.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionHouseStats.java index 98f3b56b2..53a2368b1 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionHouseStats.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionHouseStats.java @@ -8,6 +8,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -35,8 +36,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { DatapointAuctionStatistics.class ).getValue(); - return ItemStackCreator.getStack(I18n.string("gui_auction.stats.seller_stats"), Material.PAPER, 1, - I18n.lore("gui_auction.stats.seller_stats.lore", Map.ofEntries( + return TranslatableItemStackCreator.getStack(p, "gui_auction.stats.seller_stats", Material.PAPER, 1, + "gui_auction.stats.seller_stats.lore", Map.ofEntries( entry("auctions_created", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.AUCTIONS_CREATED))), entry("completed_without_bids", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.AUCTIONS_COMPLETED_WITHOUT_BIDS))), entry("completed_with_bids", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.AUCTIONS_COMPLETED_WITH_BIDS))), @@ -51,7 +52,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { entry("mythic_sold", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.MYTHIC_SOLD))), entry("special_sold", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.SPECIAL_SOLD))), entry("ultimate_sold", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.ULTIMATE_SOLD))) - ))); + )); } }); set(new GUIItem(15) { @@ -63,8 +64,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { DatapointAuctionStatistics.class ).getValue(); - return ItemStackCreator.getStack(I18n.string("gui_auction.stats.buyer_stats"), Material.FILLED_MAP, 1, - I18n.lore("gui_auction.stats.buyer_stats.lore", Map.ofEntries( + return TranslatableItemStackCreator.getStack(p, "gui_auction.stats.buyer_stats", Material.FILLED_MAP, 1, + "gui_auction.stats.buyer_stats.lore", Map.ofEntries( entry("auctions_won", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.AUCTIONS_WON))), entry("total_bids", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.TOTAL_BIDS))), entry("highest_bid", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.HIGHEST_BID_MADE))), @@ -77,7 +78,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { entry("mythic_bought", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.MYTHIC_BOUGHT))), entry("special_bought", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.SPECIAL_BOUGHT))), entry("ultimate_bought", String.valueOf(stats.get(DatapointAuctionStatistics.AuctionStatistics.AuctionStat.ULTIMATE_BOUGHT))) - ))); + )); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionViewItem.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionViewItem.java index deec4d001..1dd2ce0ff 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionViewItem.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIAuctionViewItem.java @@ -89,7 +89,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public void refreshItems(HypixelPlayer player) { if (!new ProxyService(ServiceType.AUCTION_HOUSE).isOnline().join()) { - player.sendMessage(I18n.string("gui_auction.view.offline_message")); + player.sendMessage(I18n.string("gui_auction.view.offline_message", player.getLocale())); player.closeInventory(); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIManageAuctions.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIManageAuctions.java index 6237dc80e..3bac9938c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIManageAuctions.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIManageAuctions.java @@ -16,6 +16,7 @@ import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -47,8 +48,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.manage.create_button"), Material.GOLDEN_HORSE_ARMOR, 1, - I18n.lore("gui_auction.manage.create_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.manage.create_button", Material.GOLDEN_HORSE_ARMOR, 1, + "gui_auction.manage.create_button.lore"); } }); } @@ -146,7 +147,7 @@ public void onBottomClick(InventoryPreClickEvent e) { @Override public void refreshItems(HypixelPlayer player) { if (!new ProxyService(ServiceType.AUCTION_HOUSE).isOnline().join()) { - player.sendMessage(I18n.string("gui_auction.manage.offline_message")); + player.sendMessage(I18n.string("gui_auction.manage.offline_message", player.getLocale())); player.closeInventory(); return; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIViewBids.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIViewBids.java index 0a663312e..c591dd19a 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIViewBids.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/GUIViewBids.java @@ -132,7 +132,7 @@ public void onBottomClick(InventoryPreClickEvent e) { @Override public void refreshItems(HypixelPlayer player) { if (!new ProxyService(ServiceType.AUCTION_HOUSE).isOnline().join()) { - player.sendMessage(I18n.string("gui_auction.bids.offline_message")); + player.sendMessage(I18n.string("gui_auction.bids.offline_message", player.getLocale())); player.closeInventory(); return; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewSelfBIN.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewSelfBIN.java index e601e83e7..f1e88d108 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewSelfBIN.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewSelfBIN.java @@ -5,7 +5,7 @@ import net.minestom.server.item.Material; import net.swofty.commons.skyblock.auctions.AuctionItem; import net.swofty.type.generic.data.datapoints.DatapointDouble; -import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -15,6 +15,7 @@ import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -30,9 +31,10 @@ public void open(GUIAuctionViewItem gui, AuctionItem item, SkyBlockPlayer player @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); double coins = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class).getValue(); - player.sendMessage(I18n.string("gui_auction.view_self_bin.claiming_coins")); + player.sendMessage(I18n.string("gui_auction.view_self_bin.claiming_coins", l)); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class).setValue(coins + item.getBids().getFirst().value()); ownedActive.remove(item.getUuid()); @@ -40,18 +42,18 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { ownedInactive.add(item.getUuid()); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_INACTIVE_OWNED, DatapointUUIDList.class).setValue(ownedInactive); - player.sendMessage(I18n.string("gui_auction.view_self_bin.collected_coins", Map.of("amount", String.valueOf(item.getBids().getFirst().value())))); + player.sendMessage(I18n.string("gui_auction.view_self_bin.collected_coins", l, Map.of("amount", String.valueOf(item.getBids().getFirst().value())))); player.closeInventory(); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_bin.collect_auction"), Material.GOLD_BLOCK, 1, - I18n.lore("gui_auction.view_self_bin.collect_sold.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_bin.collect_auction", Material.GOLD_BLOCK, 1, + "gui_auction.view_self_bin.collect_sold.lore", Map.of( "buyer_name", SkyBlockPlayer.getDisplayName(item.getBids().getFirst().uuid()), "price", String.valueOf(item.getBids().getFirst().value()) - ))); + )); } }); } else { @@ -59,8 +61,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_bin.cannot_buy_own"), Material.BEDROCK, 1, - I18n.lore("gui_auction.view_self_bin.cannot_buy_own_claimed.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_bin.cannot_buy_own", Material.BEDROCK, 1, + "gui_auction.view_self_bin.cannot_buy_own_claimed.lore"); } }); } @@ -68,7 +70,6 @@ public ItemStack.Builder getItem(HypixelPlayer p) { } if (item.getEndTime() < System.currentTimeMillis()) { - // Noone bought the item, so give it back to the player if in active List ownedActive = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ACTIVE_OWNED, DatapointUUIDList.class).getValue(); List ownedInactive = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_INACTIVE_OWNED, DatapointUUIDList.class).getValue(); @@ -77,14 +78,15 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_bin.claim_item_back"), Material.GOLD_INGOT, 1, - I18n.lore("gui_auction.view_self_bin.claim_item_back.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_bin.claim_item_back", Material.GOLD_INGOT, 1, + "gui_auction.view_self_bin.claim_item_back.lore"); } @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_auction.view_self_bin.claiming_item")); + Locale l = p.getLocale(); + player.sendMessage(I18n.string("gui_auction.view_self_bin.claiming_item", l)); ownedActive.remove(item.getUuid()); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ACTIVE_OWNED, DatapointUUIDList.class).setValue(ownedActive); ownedInactive.add(item.getUuid()); @@ -92,7 +94,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { player.addAndUpdateItem(item.getItem()); - player.sendMessage(I18n.string("gui_auction.view_self_bin.claimed_item")); + player.sendMessage(I18n.string("gui_auction.view_self_bin.claimed_item", l)); player.closeInventory(); } }); @@ -101,8 +103,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_bin.cannot_buy_own"), Material.BEDROCK, 1, - I18n.lore("gui_auction.view_self_bin.cannot_buy_own_expired.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_bin.cannot_buy_own", Material.BEDROCK, 1, + "gui_auction.view_self_bin.cannot_buy_own_expired.lore"); } }); } @@ -113,8 +115,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_bin.cannot_buy_own"), Material.BEDROCK, 1, - I18n.lore("gui_auction.view_self_bin.cannot_buy_own_active.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_bin.cannot_buy_own", Material.BEDROCK, 1, + "gui_auction.view_self_bin.cannot_buy_own_active.lore"); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewSelfNormal.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewSelfNormal.java index b543784fa..c19513e70 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewSelfNormal.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewSelfNormal.java @@ -7,6 +7,7 @@ import net.swofty.commons.skyblock.auctions.AuctionItem; import net.swofty.type.generic.data.datapoints.DatapointDouble; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -18,6 +19,7 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -28,8 +30,9 @@ public void open(GUIAuctionViewItem gui, AuctionItem item, SkyBlockPlayer player @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_auction.view_self_normal.bid_history_total", Map.of("count", String.valueOf(item.getBids().size())))); + lore.add(I18n.string("gui_auction.view_self_normal.bid_history_total", l, Map.of("count", String.valueOf(item.getBids().size())))); List bids = new ArrayList<>(item.getBids()); bids.sort(Comparator.comparingLong(AuctionItem.Bid::value).reversed()); @@ -39,13 +42,13 @@ public ItemStack.Builder getItem(HypixelPlayer p) { break; AuctionItem.Bid bid = bids.get(i); - lore.add(I18n.string("gui_auction.view_self_normal.bid_separator")); - lore.add(I18n.string("gui_auction.view_self_normal.bid_value", Map.of("value", String.valueOf(bid.value())))); - lore.add(I18n.string("gui_auction.view_self_normal.bid_by", Map.of("player_name", SkyBlockPlayer.getDisplayName(bid.uuid())))); + lore.add(I18n.string("gui_auction.view_self_normal.bid_separator", l)); + lore.add(I18n.string("gui_auction.view_self_normal.bid_value", l, Map.of("value", String.valueOf(bid.value())))); + lore.add(I18n.string("gui_auction.view_self_normal.bid_by", l, Map.of("player_name", SkyBlockPlayer.getDisplayName(bid.uuid())))); lore.add("§b" + StringUtility.formatTimeAsAgo(bid.timestamp())); } - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_normal.bid_history"), Material.FILLED_MAP, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_normal.bid_history", l), Material.FILLED_MAP, 1, lore); } }); @@ -71,8 +74,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_normal.collect_auction"), Material.GOLD_BLOCK, 1, - I18n.lore("gui_auction.view_self_normal.collect_no_bids.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_normal.collect_auction", Material.GOLD_BLOCK, 1, + "gui_auction.view_self_normal.collect_no_bids.lore"); } }); } else { @@ -80,6 +83,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); double coins = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class).getValue(); long highestBid = item.getBids().stream().max(Comparator.comparingLong(AuctionItem.Bid::value)).map(AuctionItem.Bid::value).orElse(0L); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class).setValue(coins + highestBid); @@ -89,30 +93,29 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { ownedInactive.add(item.getUuid()); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_INACTIVE_OWNED, DatapointUUIDList.class).setValue(ownedInactive); - player.sendMessage(I18n.string("gui_auction.view_self_normal.collected_coins", Map.of("amount", String.valueOf(highestBid)))); + player.sendMessage(I18n.string("gui_auction.view_self_normal.collected_coins", l, Map.of("amount", String.valueOf(highestBid)))); player.closeInventory(); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_normal.collect_auction"), Material.GOLD_BLOCK, 1, - I18n.lore("gui_auction.view_self_normal.collect_with_bids.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_normal.collect_auction", Material.GOLD_BLOCK, 1, + "gui_auction.view_self_normal.collect_with_bids.lore", Map.of( "amount", String.valueOf(item.getBids().stream().max(Comparator.comparingLong(AuctionItem.Bid::value)).map(AuctionItem.Bid::value).orElse(0L)) - ))); + )); } }); } } else { - // Player has already claimed their coins gui.set(new GUIItem(29) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_normal.auction_ended"), Material.BARRIER, 1, - I18n.lore("gui_auction.view_self_normal.auction_ended_claimed.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_normal.auction_ended", Material.BARRIER, 1, + "gui_auction.view_self_normal.auction_ended_claimed.lore", Map.of( "amount", String.valueOf(item.getBids().stream().max(Comparator.comparingLong(AuctionItem.Bid::value)).map(AuctionItem.Bid::value).orElse(0L)) - ))); + )); } }); } @@ -123,8 +126,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_auction.view_self_normal.own_auction"), Material.BEDROCK, 1, - I18n.lore("gui_auction.view_self_normal.own_auction.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_self_normal.own_auction", Material.BEDROCK, 1, + "gui_auction.view_self_normal.own_auction.lore"); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewThirdBin.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewThirdBin.java index 547aaa10c..99e1e870d 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewThirdBin.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewThirdBin.java @@ -13,7 +13,7 @@ import net.swofty.proxyapi.ProxyPlayer; import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.data.datapoints.DatapointDouble; -import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -25,15 +25,14 @@ import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import java.util.ArrayList; +import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; public class AuctionViewThirdBin implements AuctionView { @Override public void open(GUIAuctionViewItem gui, AuctionItem item, SkyBlockPlayer player) { - // Check if the BIN item has already been bought if (!item.getBids().isEmpty()) { - // Check if the bidder is the player if (item.getBids().getFirst().uuid().equals(player.getUuid())) { DatapointUUIDList activeBids = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ACTIVE_BIDS, DatapointUUIDList.class); DatapointUUIDList inactiveBids = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_INACTIVE_BIDS, DatapointUUIDList.class); @@ -43,7 +42,8 @@ public void open(GUIAuctionViewItem gui, AuctionItem item, SkyBlockPlayer player @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_auction.view_third_bin.claiming_item")); + Locale l = p.getLocale(); + player.sendMessage(I18n.string("gui_auction.view_third_bin.claiming_item", l)); activeBids.setValue(new ArrayList<>(activeBids.getValue()) {{ remove(item.getUuid()); }}); @@ -53,28 +53,28 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { player.addAndUpdateItem(item.getItem()); - player.sendMessage(I18n.string("gui_auction.view_third_bin.claimed_item")); + player.sendMessage(I18n.string("gui_auction.view_third_bin.claimed_item", l)); player.closeInventory(); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_bin.claim_item"), Material.GOLD_BLOCK, 1, - I18n.lore("gui_auction.view_third_bin.claim_sold.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_bin.claim_item", Material.GOLD_BLOCK, 1, + "gui_auction.view_third_bin.claim_sold.lore", Map.of( "buyer_name", SkyBlockPlayer.getDisplayName(item.getBids().getFirst().uuid()), "price", String.valueOf(item.getBids().getFirst().value()) - ))); + )); } }); } else { gui.set(new GUIItem(31) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_bin.item_sold"), Material.BEDROCK, 1, - I18n.lore("gui_auction.view_third_bin.item_sold_claimed.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_bin.item_sold", Material.BEDROCK, 1, + "gui_auction.view_third_bin.item_sold_claimed.lore", Map.of( "buyer_name", SkyBlockPlayer.getDisplayName(item.getBids().getFirst().uuid()), "price", String.valueOf(item.getBids().getFirst().value()) - ))); + )); } }); } @@ -84,11 +84,11 @@ public ItemStack.Builder getItem(HypixelPlayer p) { gui.set(new GUIItem(31) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_bin.item_sold"), Material.BEDROCK, 1, - I18n.lore("gui_auction.view_third_bin.item_sold_other.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_bin.item_sold", Material.BEDROCK, 1, + "gui_auction.view_third_bin.item_sold_other.lore", Map.of( "buyer_name", SkyBlockPlayer.getDisplayName(item.getBids().getFirst().uuid()), "price", String.valueOf(item.getBids().getFirst().value()) - ))); + )); } }); return; @@ -98,26 +98,26 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); double coins = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class).getValue(); if (coins < item.getStartingPrice()) { - player.sendMessage(I18n.string("gui_auction.view_third_bin.not_enough_coins")); + player.sendMessage(I18n.string("gui_auction.view_third_bin.not_enough_coins", l)); return; } - player.sendMessage(I18n.string("gui_auction.view_third_bin.escrow_message")); + player.sendMessage(I18n.string("gui_auction.view_third_bin.escrow_message", l)); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class).setValue(coins - item.getStartingPrice()); - player.sendMessage(I18n.string("gui_auction.view_third_bin.processing")); + player.sendMessage(I18n.string("gui_auction.view_third_bin.processing", l)); - // Check that it is still available, by checking it has 0 bids CompletableFuture future = new ProxyService(ServiceType.AUCTION_HOUSE).handleRequest( new AuctionFetchItemProtocolObject.AuctionFetchItemMessage(item.getUuid()) ); AuctionItem item = future.join().item(); if (!item.getBids().isEmpty()) { - player.sendMessage(I18n.string("gui_auction.view_third_bin.already_sold")); - player.sendMessage(I18n.string("gui_auction.view_third_bin.returning_escrow")); + player.sendMessage(I18n.string("gui_auction.view_third_bin.already_sold", l)); + player.sendMessage(I18n.string("gui_auction.view_third_bin.returning_escrow", l)); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class).setValue(coins + item.getStartingPrice()); return; } @@ -125,8 +125,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { CoopDatabase.Coop originatorCoop = CoopDatabase.getFromMember(item.getOriginator()); CoopDatabase.Coop purchaserCoop = CoopDatabase.getFromMember(player.getUuid()); if (originatorCoop != null && purchaserCoop != null && originatorCoop.isSameAs(purchaserCoop)) { - player.sendMessage(I18n.string("gui_auction.view_third_bin.same_coop")); - player.sendMessage(I18n.string("gui_auction.view_third_bin.returning_escrow")); + player.sendMessage(I18n.string("gui_auction.view_third_bin.same_coop", l)); + player.sendMessage(I18n.string("gui_auction.view_third_bin.returning_escrow", l)); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class).setValue(coins + item.getStartingPrice()); return; } @@ -137,7 +137,6 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { }}); player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ACTIVE_BIDS, DatapointUUIDList.class).setValue(activeBids.getValue()); - // Add player bid to item and update it item.setBids(new ArrayList<>(item.getBids()) {{ add(new AuctionItem.Bid(System.currentTimeMillis(), player.getUuid(), item.getStartingPrice().longValue())); }}); @@ -149,14 +148,14 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { new ProxyService(ServiceType.AUCTION_HOUSE).handleRequest(message).join(); - player.sendMessage(I18n.string("gui_auction.view_third_bin.purchased", Map.of( + player.sendMessage(I18n.string("gui_auction.view_third_bin.purchased", l, Map.of( "item_name", new SkyBlockItem(item.getItem()).getDisplayName(), "price", String.valueOf(item.getStartingPrice()) ))); ProxyPlayer owner = new ProxyPlayer(item.getOriginator()); if (owner.isOnline().join()) { - owner.sendMessage(Component.text(I18n.string("gui_auction.view_third_bin.owner_notification", Map.of( + owner.sendMessage(Component.text(I18n.string("gui_auction.view_third_bin.owner_notification", l, Map.of( "buyer_name", player.getFullDisplayName(), "item_name", new SkyBlockItem(item.getItem()).getDisplayName() ))).clickEvent( @@ -167,10 +166,10 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_bin.buy_now"), Material.GOLD_NUGGET, 1, - I18n.lore("gui_auction.view_third_bin.buy_now.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_bin.buy_now", Material.GOLD_NUGGET, 1, + "gui_auction.view_third_bin.buy_now.lore", Map.of( "price", String.valueOf(item.getStartingPrice()) - ))); + )); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewThirdNormal.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewThirdNormal.java index a8ad8a2ef..4e7e28754 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewThirdNormal.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/auction/view/AuctionViewThirdNormal.java @@ -17,6 +17,7 @@ import net.swofty.type.generic.data.datapoints.DatapointDouble; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.gui.inventory.item.GUIQueryItem; @@ -32,6 +33,7 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -52,8 +54,9 @@ public void open(GUIAuctionViewItem gui, AuctionItem item, SkyBlockPlayer player gui.set(new GUIItem(33) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_auction.view_third_normal.bid_history_total", Map.of("count", String.valueOf(item.getBids().size())))); + lore.add(I18n.string("gui_auction.view_third_normal.bid_history_total", l, Map.of("count", String.valueOf(item.getBids().size())))); List bids = new ArrayList<>(item.getBids()); bids.sort(Comparator.comparingLong(AuctionItem.Bid::value).reversed()); @@ -63,13 +66,13 @@ public ItemStack.Builder getItem(HypixelPlayer p) { break; AuctionItem.Bid bid = bids.get(i); - lore.add(I18n.string("gui_auction.view_third_normal.bid_separator")); - lore.add(I18n.string("gui_auction.view_third_normal.bid_value", Map.of("value", String.valueOf(bid.value())))); - lore.add(I18n.string("gui_auction.view_third_normal.bid_by", Map.of("player_name", SkyBlockPlayer.getDisplayName(bid.uuid())))); + lore.add(I18n.string("gui_auction.view_third_normal.bid_separator", l)); + lore.add(I18n.string("gui_auction.view_third_normal.bid_value", l, Map.of("value", String.valueOf(bid.value())))); + lore.add(I18n.string("gui_auction.view_third_normal.bid_by", l, Map.of("player_name", SkyBlockPlayer.getDisplayName(bid.uuid())))); lore.add("§b" + StringUtility.formatTimeAsAgo(bid.timestamp())); } - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_normal.bid_history"), Material.FILLED_MAP, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_normal.bid_history", l), Material.FILLED_MAP, 1, lore); } }); @@ -77,10 +80,6 @@ public ItemStack.Builder getItem(HypixelPlayer p) { DatapointUUIDList activeBids = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ACTIVE_BIDS, DatapointUUIDList.class); DatapointUUIDList inactiveBids = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_INACTIVE_BIDS, DatapointUUIDList.class); - // If UUID is in here, it hasn't been claimed yet, if it's not, it has been claimed, - // goes for both coins and items - // Check that they won the auction in the first place - AuctionItem.Bid winningBid = item.getBids().stream().max(Comparator.comparingLong(AuctionItem.Bid::value)).orElse(null); AuctionItem.Bid highestBidMadeByPlayer = item.getBids().stream().filter(bid -> bid.uuid().equals(player.getUuid())).max(Comparator.comparingLong(AuctionItem.Bid::value)).orElse(null); if (winningBid == null || !winningBid.uuid().equals(player.getUuid())) { @@ -89,7 +88,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_auction.view_third_normal.claiming_bid_coins")); + Locale l = p.getLocale(); + player.sendMessage(I18n.string("gui_auction.view_third_normal.claiming_bid_coins", l)); DatapointDouble coins = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class); coins.setValue(coins.getValue() + highestBidMadeByPlayer.value()); activeBids.setValue(new ArrayList<>(activeBids.getValue()) {{ @@ -99,36 +99,35 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { add(item.getUuid()); }}); - player.sendMessage(I18n.string("gui_auction.view_third_normal.coins_returned", Map.of("amount", String.valueOf(highestBidMadeByPlayer.value())))); + player.sendMessage(I18n.string("gui_auction.view_third_normal.coins_returned", l, Map.of("amount", String.valueOf(highestBidMadeByPlayer.value())))); player.closeInventory(); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_normal.auction_ended_lost"), Material.BARRIER, 1, - I18n.lore("gui_auction.view_third_normal.auction_ended_lost_claim.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_normal.auction_ended_lost", Material.BARRIER, 1, + "gui_auction.view_third_normal.auction_ended_lost_claim.lore", Map.of( "amount", String.valueOf(highestBidMadeByPlayer.value()) - ))); + )); } }); } else { gui.set(new GUIItem(29) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_normal.auction_ended_lost"), Material.BARRIER, 1, - I18n.lore("gui_auction.view_third_normal.auction_ended_lost_no_claim.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_normal.auction_ended_lost", Material.BARRIER, 1, + "gui_auction.view_third_normal.auction_ended_lost_no_claim.lore"); } }); } } else { - // Player won auction, do similar checks as above to see - // if they have claimed their item if (activeBids.getValue().contains(item.getUuid())) { gui.set(new GUIClickableItem(29) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - player.sendMessage(I18n.string("gui_auction.view_third_normal.claiming_item")); + Locale l = p.getLocale(); + player.sendMessage(I18n.string("gui_auction.view_third_normal.claiming_item", l)); activeBids.setValue(new ArrayList<>(activeBids.getValue()) {{ remove(item.getUuid()); }}); @@ -138,22 +137,22 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { player.addAndUpdateItem(item.getItem()); - player.sendMessage(I18n.string("gui_auction.view_third_normal.claimed_item")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.claimed_item", l)); player.closeInventory(); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_normal.auction_ended_won"), Material.EMERALD, 1, - I18n.lore("gui_auction.view_third_normal.auction_ended_won_claim.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_normal.auction_ended_won", Material.EMERALD, 1, + "gui_auction.view_third_normal.auction_ended_won_claim.lore"); } }); } else { gui.set(new GUIItem(29) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_normal.auction_ended_won"), Material.EMERALD, 1, - I18n.lore("gui_auction.view_third_normal.auction_ended_won_claimed.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_normal.auction_ended_won", Material.EMERALD, 1, + "gui_auction.view_third_normal.auction_ended_won_claimed.lore"); } }); } @@ -164,19 +163,20 @@ public ItemStack.Builder getItem(HypixelPlayer p) { gui.set(new GUIQueryItem(31) { @Override public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer player) { - long l; + Locale l = player.getLocale(); + long val; try { - l = Long.parseLong(query); + val = Long.parseLong(query); } catch (NumberFormatException ex) { - player.sendMessage(I18n.string("gui_auction.view_third_normal.number_parse_error")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.number_parse_error", l)); return gui; } - if (l < gui.minimumBidAmount) { - player.sendMessage(I18n.string("gui_auction.view_third_normal.bid_too_low", Map.of("minimum", String.valueOf(gui.minimumBidAmount)))); + if (val < gui.minimumBidAmount) { + player.sendMessage(I18n.string("gui_auction.view_third_normal.bid_too_low", l, Map.of("minimum", String.valueOf(gui.minimumBidAmount)))); return gui; } - gui.bidAmount = l; + gui.bidAmount = val; return gui; } @@ -184,34 +184,34 @@ public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack( - I18n.string("gui_auction.view_third_normal.bid_amount", Map.of("amount", String.valueOf(gui.bidAmount))), - Material.GOLD_INGOT, 1, - I18n.lore("gui_auction.view_third_normal.bid_amount.lore", Map.of("minimum", String.valueOf(gui.minimumBidAmount)))); + return TranslatableItemStackCreator.getStack(p, + "gui_auction.view_third_normal.bid_amount", Material.GOLD_INGOT, 1, + "gui_auction.view_third_normal.bid_amount.lore", Map.of("minimum", String.valueOf(gui.minimumBidAmount), "amount", String.valueOf(gui.bidAmount))); } }); gui.set(new GUIClickableItem(29) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); if (gui.bidAmount < gui.minimumBidAmount) { - player.sendMessage(I18n.string("gui_auction.view_third_normal.bid_too_low", Map.of("minimum", String.valueOf(gui.minimumBidAmount)))); + player.sendMessage(I18n.string("gui_auction.view_third_normal.bid_too_low", l, Map.of("minimum", String.valueOf(gui.minimumBidAmount)))); return; } DatapointDouble coins = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.COINS, DatapointDouble.class); if (coins.getValue() < gui.bidAmount) { - player.sendMessage(I18n.string("gui_auction.view_third_normal.not_enough_coins")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.not_enough_coins", l)); return; } UUID topBidder = item.getBids().stream().max(Comparator.comparingLong(AuctionItem.Bid::value)).map(AuctionItem.Bid::uuid).orElse(null); if (topBidder != null && topBidder.equals(player.getUuid())) { - player.sendMessage(I18n.string("gui_auction.view_third_normal.already_top_bid")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.already_top_bid", l)); return; } - player.sendMessage(I18n.string("gui_auction.view_third_normal.escrow_message")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.escrow_message", l)); coins.setValue(coins.getValue() - gui.bidAmount); player.closeInventory(); @@ -225,13 +225,13 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { CoopDatabase.Coop originatorCoop = CoopDatabase.getFromMember(item.getOriginator()); CoopDatabase.Coop purchaserCoop = CoopDatabase.getFromMember(player.getUuid()); if (originatorCoop != null && purchaserCoop != null && originatorCoop.isSameAs(purchaserCoop)) { - player.sendMessage(I18n.string("gui_auction.view_third_normal.same_coop")); - player.sendMessage(I18n.string("gui_auction.view_third_normal.returning_escrow")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.same_coop", l)); + player.sendMessage(I18n.string("gui_auction.view_third_normal.returning_escrow", l)); coins.setValue(coins.getValue() + gui.bidAmount); return; } - player.sendMessage(I18n.string("gui_auction.view_third_normal.processing_bid")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.processing_bid", l)); Thread.startVirtualThread(() -> { AuctionFetchItemProtocolObject.AuctionFetchItemResponse itemResponse = (AuctionFetchItemProtocolObject.AuctionFetchItemResponse) new ProxyService(ServiceType.AUCTION_HOUSE).handleRequest( new AuctionFetchItemProtocolObject.AuctionFetchItemMessage(item.getUuid()) @@ -241,15 +241,15 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { AuctionItem.Bid highestBid = item.getBids().stream().max(Comparator.comparingLong(AuctionItem.Bid::value)).orElse(null); if (highestBid != null && highestBid.value() >= gui.bidAmount) { - player.sendMessage(I18n.string("gui_auction.view_third_normal.bid_changed")); - player.sendMessage(I18n.string("gui_auction.view_third_normal.returning_escrow")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.bid_changed", l)); + player.sendMessage(I18n.string("gui_auction.view_third_normal.returning_escrow", l)); coins.setValue(coins.getValue() + gui.bidAmount); return; } if (item.getEndTime() + 5000 < System.currentTimeMillis()) { - player.sendMessage(I18n.string("gui_auction.view_third_normal.auction_ended_error")); - player.sendMessage(I18n.string("gui_auction.view_third_normal.returning_escrow")); + player.sendMessage(I18n.string("gui_auction.view_third_normal.auction_ended_error", l)); + player.sendMessage(I18n.string("gui_auction.view_third_normal.returning_escrow", l)); coins.setValue(coins.getValue() + gui.bidAmount); return; } @@ -257,7 +257,6 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { item.setBids(new ArrayList<>(item.getBids()) {{ add(new AuctionItem.Bid(System.currentTimeMillis(), player.getUuid(), gui.bidAmount)); }}); - // Add two minutes on item.setEndTime(item.getEndTime() + 120000); AuctionAddItemProtocolObject.AuctionAddItemMessage message = @@ -265,10 +264,9 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { item, category); new ProxyService(ServiceType.AUCTION_HOUSE).handleRequest(message).join(); - player.sendMessage(I18n.string("gui_auction.view_third_normal.bid_placed", Map.of("amount", String.valueOf(gui.bidAmount)))); + player.sendMessage(I18n.string("gui_auction.view_third_normal.bid_placed", l, Map.of("amount", String.valueOf(gui.bidAmount)))); new GUIAuctionViewItem(gui.auctionID, gui.previousGUI).open(player); - // Add auction uuid to activebids DatapointUUIDList activeBids = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.AUCTION_ACTIVE_BIDS, DatapointUUIDList.class); activeBids.setValue(new ArrayList<>(activeBids.getValue()) {{ add(item.getUuid()); @@ -281,7 +279,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { if (playersBid < gui.bidAmount && !alertsSentOutTo.contains(proxyPlayer.getUuid())) { alertsSentOutTo.add(proxyPlayer.getUuid()); - proxyPlayer.sendMessage(Component.text(I18n.string("gui_auction.view_third_normal.outbid_notification", Map.of( + proxyPlayer.sendMessage(Component.text(I18n.string("gui_auction.view_third_normal.outbid_notification", l, Map.of( "bidder_name", player.getFullDisplayName(), "difference", String.valueOf(gui.bidAmount - playersBid), "item_name", new SkyBlockItem(item.getItem()).getDisplayName() @@ -294,7 +292,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { ProxyPlayer auctionOwner = new ProxyPlayer(item.getOriginator()); if (auctionOwner.isOnline().join()) { - auctionOwner.sendMessage(Component.text(I18n.string("gui_auction.view_third_normal.owner_bid_notification", Map.of( + auctionOwner.sendMessage(Component.text(I18n.string("gui_auction.view_third_normal.owner_bid_notification", l, Map.of( "bidder_name", player.getFullDisplayName(), "amount", String.valueOf(gui.bidAmount), "item_name", new SkyBlockItem(item.getItem()).getDisplayName() @@ -307,8 +305,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_auction.view_third_normal.submit_bid"), Material.GOLD_NUGGET, 1, - I18n.lore("gui_auction.view_third_normal.submit_bid.lore", Map.of("amount", String.valueOf(gui.bidAmount)))); + return TranslatableItemStackCreator.getStack(p, "gui_auction.view_third_normal.submit_bid", Material.GOLD_NUGGET, 1, + "gui_auction.view_third_normal.submit_bid.lore", Map.of("amount", String.valueOf(gui.bidAmount))); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBanker.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBanker.java index 3b76bc91f..bd6dc7271 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBanker.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBanker.java @@ -9,6 +9,7 @@ import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -20,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIBanker extends HypixelInventoryGUI implements RefreshingGUI { @@ -29,17 +31,18 @@ public GUIBanker() { @Override public void setItems(InventoryGUIOpenEvent e) { + Locale l = e.player().getLocale(); if (((SkyBlockPlayer) e.player()).isBankDelayed) { - e.player().sendMessage(I18n.string("gui_banker.main.processing_transactions")); - e.player().sendMessage(I18n.string("gui_banker.main.processing_wait")); + e.player().sendMessage(I18n.string("gui_banker.main.processing_transactions", l)); + e.player().sendMessage(I18n.string("gui_banker.main.processing_wait", l)); e.player().closeInventory(); return; } e.inventory().setTitle(Component.text( ((SkyBlockPlayer) e.player()).isCoop() - ? I18n.string("gui_banker.main.title_coop") - : I18n.string("gui_banker.main.title_personal") + ? I18n.string("gui_banker.main.title_coop", l) + : I18n.string("gui_banker.main.title_personal", l) )); refreshItems(e.player()); @@ -57,12 +60,11 @@ public void refreshItems(HypixelPlayer player) { set(new GUIItem(32) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.main.information"), Material.REDSTONE_TORCH, 1, - I18n.lore("gui_banker.main.information.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_banker.main.information", Material.REDSTONE_TORCH, 1, + "gui_banker.main.information.lore", Map.of( "limit", StringUtility.commaify(bankData.getBalanceLimit()), "hours", String.valueOf(SkyBlockCalendar.getHoursUntilNextInterest()) - ))); + )); } }); @@ -75,12 +77,11 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.main.deposit"), Material.CHEST, 1, - I18n.lore("gui_banker.main.deposit.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_banker.main.deposit", Material.CHEST, 1, + "gui_banker.main.deposit.lore", Map.of( "balance", StringUtility.decimalify(bankData.getAmount(), 1), "hours", String.valueOf(SkyBlockCalendar.getHoursUntilNextInterest()) - ))); + )); } }); @@ -93,22 +94,21 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.main.withdraw"), Material.DISPENSER, 1, - I18n.lore("gui_banker.main.withdraw.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_banker.main.withdraw", Material.DISPENSER, 1, + "gui_banker.main.withdraw.lore", Map.of( "balance", StringUtility.decimalify(bankData.getAmount(), 1) - ))); + )); } }); set(new GUIItem(15) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); List transactions = bankData.getTransactions(); - if (transactions.isEmpty()) lore.add(I18n.string("gui_banker.main.no_transactions")); + if (transactions.isEmpty()) lore.add(I18n.string("gui_banker.main.no_transactions", l)); else { for (int i = Math.min(transactions.size() - 1, 10); i >= 0; i--) { DatapointBankData.Transaction transaction = transactions.get(i); @@ -116,7 +116,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { boolean isNegative = transaction.amount < 0; String amount = StringUtility.decimalify(Math.abs(transaction.amount), 1); - lore.add(I18n.string("gui_banker.main.transaction_entry", Map.of( + lore.add(I18n.string("gui_banker.main.transaction_entry", l, Map.of( "sign", isNegative ? "§c-" : "§a+", "amount", amount, "time_ago", StringUtility.formatTimeAsAgo(transaction.timestamp), @@ -125,9 +125,8 @@ public ItemStack.Builder getItem(HypixelPlayer p) { } } - return ItemStackCreator.getStack(I18n.string("gui_banker.main.recent_transactions"), - Material.FILLED_MAP, 1, lore - ); + return TranslatableItemStackCreator.getStack(p, "gui_banker.main.recent_transactions", + Material.FILLED_MAP, 1, lore); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBankerDeposit.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBankerDeposit.java index 6b5325907..3d4617051 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBankerDeposit.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBankerDeposit.java @@ -9,6 +9,7 @@ import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIQueryItem; import net.swofty.type.generic.i18n.I18n; @@ -21,6 +22,7 @@ import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIBankerDeposit extends HypixelInventoryGUI { @@ -38,19 +40,20 @@ public void setItems(InventoryGUIOpenEvent e) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.deposit.whole_purse"), Material.CHEST, 64, + Locale l = p.getLocale(); + return TranslatableItemStackCreator.getStack(p, "gui_banker.deposit.whole_purse", Material.CHEST, 64, List.of( - I18n.string("gui_banker.deposit.whole_purse_subtitle"), + I18n.string("gui_banker.deposit.whole_purse_subtitle", l), " ", - I18n.string("gui_banker.deposit.current_balance", Map.of( + I18n.string("gui_banker.deposit.current_balance", l, Map.of( "balance", StringUtility.decimalify( player.getSkyblockDataHandler().get(SkyBlockDataHandler.Data.BANK_DATA, DatapointBankData.class).getValue().getAmount(), 1) )), - I18n.string("gui_banker.deposit.amount_to_deposit", Map.of( + I18n.string("gui_banker.deposit.amount_to_deposit", l, Map.of( "amount", StringUtility.decimalify(player.getCoins(), 1) )), " ", - I18n.string("gui_banker.deposit.click") + I18n.string("gui_banker.deposit.click", l) )); } @@ -66,19 +69,20 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.deposit.half_purse"), Material.CHEST, 32, + Locale l = p.getLocale(); + return TranslatableItemStackCreator.getStack(p, "gui_banker.deposit.half_purse", Material.CHEST, 32, List.of( - I18n.string("gui_banker.deposit.whole_purse_subtitle"), + I18n.string("gui_banker.deposit.whole_purse_subtitle", l), " ", - I18n.string("gui_banker.deposit.current_balance", Map.of( + I18n.string("gui_banker.deposit.current_balance", l, Map.of( "balance", StringUtility.decimalify( player.getSkyblockDataHandler().get(SkyBlockDataHandler.Data.BANK_DATA, DatapointBankData.class).getValue().getAmount(), 1) )), - I18n.string("gui_banker.deposit.amount_to_deposit", Map.of( + I18n.string("gui_banker.deposit.amount_to_deposit", l, Map.of( "amount", StringUtility.decimalify(player.getCoins() / 2, 1) )), " ", - I18n.string("gui_banker.deposit.click") + I18n.string("gui_banker.deposit.click", l) )); } @@ -94,21 +98,22 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); try { double amount = Double.parseDouble(query); if (amount > player.getCoins()) { - player.sendMessage(I18n.string("gui_banker.deposit.not_enough_coins")); + player.sendMessage(I18n.string("gui_banker.deposit.not_enough_coins", l)); return null; } if (amount <= 0) { - player.sendMessage(I18n.string("gui_banker.deposit.invalid_amount")); + player.sendMessage(I18n.string("gui_banker.deposit.invalid_amount", l)); return null; } player.closeInventory(); attemptDeposit(player, amount); } catch (NumberFormatException ex) { - player.sendMessage(I18n.string("gui_banker.deposit.invalid_number")); + player.sendMessage(I18n.string("gui_banker.deposit.invalid_number", l)); } return null; } @@ -116,17 +121,18 @@ public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.deposit.custom_amount"), Material.OAK_SIGN, 1, + Locale l = p.getLocale(); + return TranslatableItemStackCreator.getStack(p, "gui_banker.deposit.custom_amount", Material.OAK_SIGN, 1, List.of( - I18n.string("gui_banker.deposit.whole_purse_subtitle"), + I18n.string("gui_banker.deposit.whole_purse_subtitle", l), " ", - I18n.string("gui_banker.deposit.current_balance", Map.of( + I18n.string("gui_banker.deposit.current_balance", l, Map.of( "balance", StringUtility.decimalify( player.getSkyblockDataHandler().get(SkyBlockDataHandler.Data.BANK_DATA, DatapointBankData.class).getValue().getAmount(), 1) )), - I18n.string("gui_banker.deposit.custom_amount_label"), + I18n.string("gui_banker.deposit.custom_amount_label", l), " ", - I18n.string("gui_banker.deposit.click") + I18n.string("gui_banker.deposit.click", l) )); } }); @@ -145,18 +151,19 @@ public void suddenlyQuit(Inventory inventory, HypixelPlayer player) { } private void attemptDeposit(SkyBlockPlayer player, double amount) { + Locale l = player.getLocale(); if (player.getMissionData().isCurrentlyActive(MissionDepositCoinsInBank.class)) { player.getMissionData().endMission(MissionDepositCoinsInBank.class); } DatapointBankData.BankData bankData = player.getSkyblockDataHandler().get(net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler.Data.BANK_DATA, DatapointBankData.class).getValue(); if (bankData.getAmount() + amount > bankData.getBalanceLimit()) { - player.sendMessage(I18n.string("gui_banker.deposit.exceed_limit", Map.of( + player.sendMessage(I18n.string("gui_banker.deposit.exceed_limit", l, Map.of( "limit", StringUtility.commaify(bankData.getBalanceLimit()) ))); return; } - player.sendMessage(I18n.string("gui_banker.deposit.depositing")); + player.sendMessage(I18n.string("gui_banker.deposit.depositing", l)); player.removeCoins(amount); if (!player.isCoop()) { bankData.addAmount(amount); @@ -166,7 +173,7 @@ private void attemptDeposit(SkyBlockPlayer player, double amount) { player.getUsername() )); - player.sendMessage(I18n.string("gui_banker.deposit.success", Map.of( + player.sendMessage(I18n.string("gui_banker.deposit.success", l, Map.of( "amount", StringUtility.decimalify(amount, 1), "balance", StringUtility.decimalify(bankData.getAmount(), 1) ))); @@ -184,7 +191,7 @@ private void attemptDeposit(SkyBlockPlayer player, double amount) { SkyBlockDataHandler.Data.BANK_DATA, (DatapointBankData.BankData latestBankData) -> { if (latestBankData.getAmount() + amount > latestBankData.getBalanceLimit()) { - player.sendMessage(I18n.string("gui_banker.deposit.exceed_limit", Map.of( + player.sendMessage(I18n.string("gui_banker.deposit.exceed_limit", l, Map.of( "limit", StringUtility.commaify(latestBankData.getBalanceLimit()) ))); return null; @@ -195,7 +202,7 @@ private void attemptDeposit(SkyBlockPlayer player, double amount) { latestBankData.addTransaction(new DatapointBankData.Transaction( System.currentTimeMillis(), amount, player.getUsername())); - player.sendMessage(I18n.string("gui_banker.deposit.success", Map.of( + player.sendMessage(I18n.string("gui_banker.deposit.success", l, Map.of( "amount", StringUtility.decimalify(amount, 1), "balance", StringUtility.decimalify(latestBankData.getAmount(), 1) ))); @@ -203,7 +210,7 @@ private void attemptDeposit(SkyBlockPlayer player, double amount) { return latestBankData; }, () -> { - player.sendMessage(I18n.string("gui_banker.deposit.coop_busy")); + player.sendMessage(I18n.string("gui_banker.deposit.coop_busy", l)); } ); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBankerWithdraw.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBankerWithdraw.java index 3fc09e4fa..aae235909 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBankerWithdraw.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/banker/GUIBankerWithdraw.java @@ -9,6 +9,7 @@ import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIQueryItem; import net.swofty.type.generic.i18n.I18n; @@ -20,6 +21,7 @@ import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIBankerWithdraw extends HypixelInventoryGUI { @@ -38,19 +40,19 @@ public void setItems(InventoryGUIOpenEvent e) { set(new GUIClickableItem(10) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.withdraw.everything"), Material.DISPENSER, 64, + Locale l = p.getLocale(); + return TranslatableItemStackCreator.getStack(p, "gui_banker.withdraw.everything", Material.DISPENSER, 64, List.of( - I18n.string("gui_banker.withdraw.everything_subtitle"), + I18n.string("gui_banker.withdraw.everything_subtitle", l), " ", - I18n.string("gui_banker.withdraw.current_balance", Map.of( + I18n.string("gui_banker.withdraw.current_balance", l, Map.of( "balance", StringUtility.decimalify(bankBalance, 1) )), - I18n.string("gui_banker.withdraw.amount_to_withdraw", Map.of( + I18n.string("gui_banker.withdraw.amount_to_withdraw", l, Map.of( "amount", StringUtility.decimalify(bankBalance, 1) )), " ", - I18n.string("gui_banker.withdraw.click") + I18n.string("gui_banker.withdraw.click", l) )); } @@ -65,19 +67,19 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { set(new GUIClickableItem(12) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.withdraw.half_account"), Material.DISPENSER, 32, + Locale l = p.getLocale(); + return TranslatableItemStackCreator.getStack(p, "gui_banker.withdraw.half_account", Material.DISPENSER, 32, List.of( - I18n.string("gui_banker.withdraw.everything_subtitle"), + I18n.string("gui_banker.withdraw.everything_subtitle", l), " ", - I18n.string("gui_banker.withdraw.current_balance", Map.of( + I18n.string("gui_banker.withdraw.current_balance", l, Map.of( "balance", StringUtility.decimalify(bankBalance, 1) )), - I18n.string("gui_banker.withdraw.amount_to_withdraw", Map.of( + I18n.string("gui_banker.withdraw.amount_to_withdraw", l, Map.of( "amount", StringUtility.decimalify(bankBalance / 2, 1) )), " ", - I18n.string("gui_banker.withdraw.click") + I18n.string("gui_banker.withdraw.click", l) )); } @@ -99,19 +101,19 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.withdraw.twenty_percent"), Material.DISPENSER, 1, + Locale l = p.getLocale(); + return TranslatableItemStackCreator.getStack(p, "gui_banker.withdraw.twenty_percent", Material.DISPENSER, 1, List.of( - I18n.string("gui_banker.withdraw.everything_subtitle"), + I18n.string("gui_banker.withdraw.everything_subtitle", l), " ", - I18n.string("gui_banker.withdraw.current_balance", Map.of( + I18n.string("gui_banker.withdraw.current_balance", l, Map.of( "balance", StringUtility.decimalify(bankBalance, 1) )), - I18n.string("gui_banker.withdraw.amount_to_withdraw", Map.of( + I18n.string("gui_banker.withdraw.amount_to_withdraw", l, Map.of( "amount", StringUtility.decimalify(bankBalance / 5, 1) )), " ", - I18n.string("gui_banker.withdraw.click") + I18n.string("gui_banker.withdraw.click", l) )); } }); @@ -120,21 +122,22 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); try { double amount = Double.parseDouble(query); if (amount > bankBalance) { - player.sendMessage(I18n.string("gui_banker.withdraw.not_enough_coins")); + player.sendMessage(I18n.string("gui_banker.withdraw.not_enough_coins", l)); return null; } if (amount <= 0) { - player.sendMessage(I18n.string("gui_banker.withdraw.invalid_amount")); + player.sendMessage(I18n.string("gui_banker.withdraw.invalid_amount", l)); return null; } player.closeInventory(); attemptWithdrawal(player, amount); } catch (NumberFormatException ex) { - player.sendMessage(I18n.string("gui_banker.withdraw.invalid_number")); + player.sendMessage(I18n.string("gui_banker.withdraw.invalid_number", l)); } return null; } @@ -142,16 +145,17 @@ public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_banker.withdraw.custom_amount"), Material.OAK_SIGN, 1, + Locale l = p.getLocale(); + return TranslatableItemStackCreator.getStack(p, "gui_banker.withdraw.custom_amount", Material.OAK_SIGN, 1, List.of( - I18n.string("gui_banker.withdraw.everything_subtitle"), + I18n.string("gui_banker.withdraw.everything_subtitle", l), " ", - I18n.string("gui_banker.withdraw.current_balance", Map.of( + I18n.string("gui_banker.withdraw.current_balance", l, Map.of( "balance", StringUtility.decimalify( player.getSkyblockDataHandler().get(SkyBlockDataHandler.Data.BANK_DATA, DatapointBankData.class).getValue().getAmount(), 1) )), " ", - I18n.string("gui_banker.withdraw.click") + I18n.string("gui_banker.withdraw.click", l) )); } }); @@ -170,12 +174,13 @@ public void suddenlyQuit(Inventory inventory, HypixelPlayer player) { } private void attemptWithdrawal(SkyBlockPlayer player, double amount) { - player.sendMessage(I18n.string("gui_banker.withdraw.withdrawing")); + Locale l = player.getLocale(); + player.sendMessage(I18n.string("gui_banker.withdraw.withdrawing", l)); if (!player.isCoop()) { DatapointBankData.BankData bankData = player.getSkyblockDataHandler().get(SkyBlockDataHandler.Data.BANK_DATA, DatapointBankData.class).getValue(); if (amount > bankData.getAmount()) { - player.sendMessage(I18n.string("gui_banker.withdraw.not_enough_coins")); + player.sendMessage(I18n.string("gui_banker.withdraw.not_enough_coins", l)); return; } @@ -184,14 +189,13 @@ private void attemptWithdrawal(SkyBlockPlayer player, double amount) { System.currentTimeMillis(), -amount, player.getUsername())); player.addCoins(amount); - player.sendMessage(I18n.string("gui_banker.withdraw.success", Map.of( + player.sendMessage(I18n.string("gui_banker.withdraw.success", l, Map.of( "amount", StringUtility.decimalify(amount, 1), "balance", StringUtility.decimalify(bankData.getAmount(), 1) ))); return; } - // Coop scenario - use mutex service CoopDatabase.Coop coop = player.getCoop(); String lockKey = "bank_data:" + player.getSkyBlockIsland().getIslandID().toString(); @@ -204,7 +208,7 @@ private void attemptWithdrawal(SkyBlockPlayer player, double amount) { (DatapointBankData.BankData latestBankData) -> { if (amount > latestBankData.getAmount()) { - player.sendMessage(I18n.string("gui_banker.withdraw.not_enough_coins")); + player.sendMessage(I18n.string("gui_banker.withdraw.not_enough_coins", l)); return null; } @@ -213,7 +217,7 @@ private void attemptWithdrawal(SkyBlockPlayer player, double amount) { System.currentTimeMillis(), -amount, player.getUsername())); player.addCoins(amount); - player.sendMessage(I18n.string("gui_banker.withdraw.success", Map.of( + player.sendMessage(I18n.string("gui_banker.withdraw.success", l, Map.of( "amount", StringUtility.decimalify(amount, 1), "balance", StringUtility.decimalify(latestBankData.getAmount(), 1) ))); @@ -221,7 +225,7 @@ private void attemptWithdrawal(SkyBlockPlayer player, double amount) { return latestBankData; }, () -> { - player.sendMessage(I18n.string("gui_banker.withdraw.coop_busy")); + player.sendMessage(I18n.string("gui_banker.withdraw.coop_busy", l)); } ); } @@ -235,4 +239,4 @@ public boolean allowHotkeying() { public void onBottomClick(InventoryPreClickEvent e) { e.setCancelled(true); } -} \ No newline at end of file +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaar.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaar.java index 81ff3d6e5..de9eaf27c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaar.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaar.java @@ -10,6 +10,7 @@ import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -21,6 +22,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; @@ -57,9 +59,9 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.main.manage_orders_button"), + return TranslatableItemStackCreator.getStack(p, "gui_bazaar.main.manage_orders_button", Material.BOOK, 1, - I18n.lore("gui_bazaar.main.manage_orders_button.lore")); + "gui_bazaar.main.manage_orders_button.lore"); } }); } @@ -98,13 +100,14 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); var b = ItemStackCreator.getStack( cat.getColor() + StringUtility.toNormalCase(cat.name()), cat.getDisplayItem(), 1, - I18n.string("gui_bazaar.main.category_subtitle"), " ", + I18n.string("gui_bazaar.main.category_subtitle", l), " ", category == cat - ? I18n.string("gui_bazaar.main.category_viewing") - : I18n.string("gui_bazaar.main.category_click") + ? I18n.string("gui_bazaar.main.category_viewing", l) + : I18n.string("gui_bazaar.main.category_click", l) ); if (category == cat) b = ItemStackCreator.enchant(b); return b; @@ -121,7 +124,7 @@ private void renderPlaceholders() { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.main.loading"), Material.GRAY_STAINED_GLASS_PANE, 1); + return TranslatableItemStackCreator.getStack(p, "gui_bazaar.main.loading", Material.GRAY_STAINED_GLASS_PANE, 1); } }); } @@ -166,16 +169,15 @@ private void rebuildCacheAndRender(SkyBlockPlayer player) { // When all price data is collected, build the cache entry CompletableFuture.allOf(allFutures.toArray(new CompletableFuture[0])) .thenRun(() -> { + Locale l = player.getLocale(); List slotData = new ArrayList<>(); - // Build slot records for (int i = 0; i < sets.size() && i < SLOTS.length; i++) { int slot = SLOTS[i]; BazaarItemSet set = sets.get(i); - // Build lore safely List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.main.item_set_products", Map.of("count", String.valueOf(set.items.size())))); + lore.add(I18n.string("gui_bazaar.main.item_set_products", l, Map.of("count", String.valueOf(set.items.size())))); lore.add(" "); // Add price data for each item in the set @@ -191,7 +193,7 @@ private void rebuildCacheAndRender(SkyBlockPlayer player) { } lore.add(" "); - lore.add(I18n.string("gui_bazaar.main.item_set_click")); + lore.add(I18n.string("gui_bazaar.main.item_set_click", l)); slotData.add(new CacheEntry.CachedSlot(slot, set, lore)); } @@ -213,8 +215,8 @@ private void rebuildCacheAndRender(SkyBlockPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.main.error_loading"), Material.BARRIER, 1, - I18n.lore("gui_bazaar.main.error_loading.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_bazaar.main.error_loading", Material.BARRIER, 1, + "gui_bazaar.main.error_loading.lore"); } }); } @@ -286,7 +288,7 @@ public void refreshItems(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; player.getBazaarConnector().isOnline().thenAccept(online -> { if (!online) { - player.sendMessage(I18n.string("gui_bazaar.main.offline_message")); + player.sendMessage(I18n.string("gui_bazaar.main.offline_message", player.getLocale())); player.closeInventory(); } else { player.getBazaarConnector().processAllPendingTransactions(); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarItem.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarItem.java index e9300b1ce..9b349aea9 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarItem.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarItem.java @@ -8,6 +8,7 @@ import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -24,6 +25,7 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIBazaarItem extends HypixelInventoryGUI implements RefreshingGUI { @@ -50,8 +52,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.manage_orders_button"), Material.BOOK, 1, - I18n.lore("gui_bazaar.item.manage_orders_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_bazaar.item.manage_orders_button", Material.BOOK, 1, + "gui_bazaar.item.manage_orders_button.lore"); } }); @@ -65,8 +67,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStackHead(I18n.string("gui_bazaar.item.go_back_bazaar"), "c232e3820897429157619b0ee099fec0628f602fff12b695de54aef11d923ad7", 1, - I18n.lore("gui_bazaar.item.go_back_bazaar.lore")); + return TranslatableItemStackCreator.getStackHead(p, "gui_bazaar.item.go_back_bazaar", "c232e3820897429157619b0ee099fec0628f602fff12b695de54aef11d923ad7", 1, + "gui_bazaar.item.go_back_bazaar.lore"); } }); @@ -95,13 +97,13 @@ private void updateItems(BazaarConnector.BazaarStatistics stats) { public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; if (stats.bestAsk() <= 0) { - p.sendMessage(I18n.string("gui_bazaar.item.buy_no_offers_message")); + p.sendMessage(I18n.string("gui_bazaar.item.buy_no_offers_message", p.getLocale())); return; } int maxSpace = player.maxItemFit(itemType); if (maxSpace <= 0) { - p.sendMessage(I18n.string("gui_bazaar.item.buy_inventory_full")); + p.sendMessage(I18n.string("gui_bazaar.item.buy_inventory_full", p.getLocale())); return; } @@ -114,13 +116,13 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { double totalCost = priceWithFee * amount; if (totalCost > player.getCoins()) { - p.sendMessage(I18n.string("gui_bazaar.item.buy_need_coins", Map.of("amount", FORMATTER.format(totalCost)))); + p.sendMessage(I18n.string("gui_bazaar.item.buy_need_coins", p.getLocale(), Map.of("amount", FORMATTER.format(totalCost)))); return; } player.getBazaarConnector().instantBuy(itemType, amount) .thenAccept(result -> { - player.sendMessage(I18n.string("gui_bazaar.item.bazaar_result_prefix") + " " + (result.success() ? "§a" : "§c") + result.message()); + player.sendMessage(I18n.string("gui_bazaar.item.bazaar_result_prefix", player.getLocale()) + " " + (result.success() ? "§a" : "§c") + result.message()); if (result.success()) p.closeInventory(); }); }); @@ -129,21 +131,22 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.item.buy_instantly_subtitle")); + lore.add(I18n.string("gui_bazaar.item.buy_instantly_subtitle", l)); lore.add(" "); if (stats.bestAsk() <= 0) { - lore.add(I18n.string("gui_bazaar.item.buy_no_offers")); + lore.add(I18n.string("gui_bazaar.item.buy_no_offers", l)); } else { double priceWithFee = stats.bestAsk() * 1.04; - lore.add(I18n.string("gui_bazaar.item.buy_price", Map.of("price", FORMATTER.format(priceWithFee)))); - lore.add(I18n.string("gui_bazaar.item.buy_max_space", Map.of("amount", String.valueOf(player.maxItemFit(itemType))))); + lore.add(I18n.string("gui_bazaar.item.buy_price", l, Map.of("price", FORMATTER.format(priceWithFee)))); + lore.add(I18n.string("gui_bazaar.item.buy_max_space", l, Map.of("amount", String.valueOf(player.maxItemFit(itemType))))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.item.buy_click")); + lore.add(I18n.string("gui_bazaar.item.buy_click", l)); } - return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.buy_instantly"), Material.GOLDEN_HORSE_ARMOR, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.buy_instantly", l), Material.GOLDEN_HORSE_ARMOR, 1, lore); } }); @@ -153,12 +156,12 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; int have = player.getAmountInInventory(itemType); if (have <= 0) { - p.sendMessage(I18n.string("gui_bazaar.item.sell_no_items", Map.of("item_name", itemType.getDisplayName()))); + p.sendMessage(I18n.string("gui_bazaar.item.sell_no_items", p.getLocale(), Map.of("item_name", itemType.getDisplayName()))); return; } if (stats.bestBid() <= 0) { - p.sendMessage(I18n.string("gui_bazaar.item.sell_no_orders_message")); + p.sendMessage(I18n.string("gui_bazaar.item.sell_no_orders_message", p.getLocale())); return; } @@ -169,7 +172,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { player.getBazaarConnector().instantSell(itemType) .thenAccept(result -> { - p.sendMessage(I18n.string("gui_bazaar.item.bazaar_result_prefix") + " " + (result.success() ? "§a" : "§c") + result.message()); + p.sendMessage(I18n.string("gui_bazaar.item.bazaar_result_prefix", p.getLocale()) + " " + (result.success() ? "§a" : "§c") + result.message()); if (result.success()) p.closeInventory(); }); }); @@ -178,24 +181,25 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.item.sell_instantly_subtitle")); + lore.add(I18n.string("gui_bazaar.item.sell_instantly_subtitle", l)); lore.add(" "); int have = player.getAmountInInventory(itemType); if (have <= 0) { - lore.add(I18n.string("gui_bazaar.item.sell_have_zero")); + lore.add(I18n.string("gui_bazaar.item.sell_have_zero", l)); } else if (stats.bestBid() <= 0) { - lore.add(I18n.string("gui_bazaar.item.sell_have", Map.of("amount", String.valueOf(have)))); - lore.add(I18n.string("gui_bazaar.item.sell_no_orders")); + lore.add(I18n.string("gui_bazaar.item.sell_have", l, Map.of("amount", String.valueOf(have)))); + lore.add(I18n.string("gui_bazaar.item.sell_no_orders", l)); } else { - lore.add(I18n.string("gui_bazaar.item.sell_have", Map.of("amount", String.valueOf(have)))); - lore.add(I18n.string("gui_bazaar.item.sell_price", Map.of("price", FORMATTER.format(stats.bestBid())))); + lore.add(I18n.string("gui_bazaar.item.sell_have", l, Map.of("amount", String.valueOf(have)))); + lore.add(I18n.string("gui_bazaar.item.sell_price", l, Map.of("price", FORMATTER.format(stats.bestBid())))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.item.sell_click")); + lore.add(I18n.string("gui_bazaar.item.sell_click", l)); } - return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.sell_instantly"), Material.HOPPER, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.sell_instantly", l), Material.HOPPER, 1, lore); } }); @@ -215,23 +219,24 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { if (price <= 0) return; double totalCost = price * amount; + Locale l = p.getLocale(); if (totalCost > player.getCoins()) { - p.sendMessage(I18n.string("gui_bazaar.item.buy_order_need_coins", Map.of("amount", FORMATTER.format(totalCost)))); + p.sendMessage(I18n.string("gui_bazaar.item.buy_order_need_coins", l, Map.of("amount", FORMATTER.format(totalCost)))); new GUIBazaarItem(itemType).open(p); return; } player.removeCoins(totalCost); - p.sendMessage(I18n.string("gui_bazaar.item.buy_order_escrow", Map.of("amount", FORMATTER.format(totalCost)))); + p.sendMessage(I18n.string("gui_bazaar.item.buy_order_escrow", l, Map.of("amount", FORMATTER.format(totalCost)))); player.getBazaarConnector().createBuyOrder(itemType, price, amount) .thenAccept(result -> { if (result.success()) { - p.sendMessage(I18n.string("gui_bazaar.item.buy_order_created", Map.of("amount", String.valueOf(amount), "price", FORMATTER.format(price)))); + p.sendMessage(I18n.string("gui_bazaar.item.buy_order_created", l, Map.of("amount", String.valueOf(amount), "price", FORMATTER.format(price)))); p.closeInventory(); } else { player.addCoins(totalCost); - p.sendMessage(I18n.string("gui_bazaar.item.buy_order_failed", Map.of("amount", FORMATTER.format(totalCost)))); + p.sendMessage(I18n.string("gui_bazaar.item.buy_order_failed", l, Map.of("amount", FORMATTER.format(totalCost)))); new GUIBazaarItem(itemType).open(p); } }); @@ -242,17 +247,18 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.item.create_buy_order_subtitle")); + lore.add(I18n.string("gui_bazaar.item.create_buy_order_subtitle", l)); lore.add(" "); - lore.add(I18n.string("gui_bazaar.item.create_buy_order_max")); + lore.add(I18n.string("gui_bazaar.item.create_buy_order_max", l)); if (stats.bestAsk() > 0) { - lore.add(I18n.string("gui_bazaar.item.create_buy_order_best_ask", Map.of("price", FORMATTER.format(stats.bestAsk())))); + lore.add(I18n.string("gui_bazaar.item.create_buy_order_best_ask", l, Map.of("price", FORMATTER.format(stats.bestAsk())))); } lore.add(" "); - lore.add(I18n.string("gui_bazaar.item.create_buy_order_click")); + lore.add(I18n.string("gui_bazaar.item.create_buy_order_click", l)); - return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.create_buy_order"), Material.FILLED_MAP, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.create_buy_order", l), Material.FILLED_MAP, 1, lore); } }); @@ -262,7 +268,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; int have = player.getAmountInInventory(itemType); if (have <= 0) { - p.sendMessage(I18n.string("gui_bazaar.item.sell_order_no_items", Map.of("item_name", itemType.getDisplayName()))); + p.sendMessage(I18n.string("gui_bazaar.item.sell_order_no_items", p.getLocale(), Map.of("item_name", itemType.getDisplayName()))); return; } @@ -277,22 +283,23 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { if (price <= 0) return; var items = player.takeItem(itemType, amount); + Locale l = p.getLocale(); if (items == null) { - p.sendMessage(I18n.string("gui_bazaar.item.sell_order_remove_fail")); + p.sendMessage(I18n.string("gui_bazaar.item.sell_order_remove_fail", l)); new GUIBazaarItem(itemType).open(p); return; } - p.sendMessage(I18n.string("gui_bazaar.item.sell_order_escrow", Map.of("amount", String.valueOf(amount), "item_name", itemType.getDisplayName()))); + p.sendMessage(I18n.string("gui_bazaar.item.sell_order_escrow", l, Map.of("amount", String.valueOf(amount), "item_name", itemType.getDisplayName()))); player.getBazaarConnector().createSellOrder(itemType, price, amount) .thenAccept(result -> { if (result.success()) { - p.sendMessage(I18n.string("gui_bazaar.item.sell_order_created", Map.of("amount", String.valueOf(amount), "price", FORMATTER.format(price)))); + p.sendMessage(I18n.string("gui_bazaar.item.sell_order_created", l, Map.of("amount", String.valueOf(amount), "price", FORMATTER.format(price)))); p.closeInventory(); } else { player.addAndUpdateItem(items); - p.sendMessage(I18n.string("gui_bazaar.item.sell_order_failed")); + p.sendMessage(I18n.string("gui_bazaar.item.sell_order_failed", l)); new GUIBazaarItem(itemType).open(p); } }); @@ -303,18 +310,19 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.item.create_sell_order_subtitle")); + lore.add(I18n.string("gui_bazaar.item.create_sell_order_subtitle", l)); lore.add(" "); int have = player.getAmountInInventory(itemType); - lore.add(I18n.string("gui_bazaar.item.create_sell_order_have", Map.of("amount", String.valueOf(have)))); + lore.add(I18n.string("gui_bazaar.item.create_sell_order_have", l, Map.of("amount", String.valueOf(have)))); if (stats.bestBid() > 0) { - lore.add(I18n.string("gui_bazaar.item.create_sell_order_best_bid", Map.of("price", FORMATTER.format(stats.bestBid())))); + lore.add(I18n.string("gui_bazaar.item.create_sell_order_best_bid", l, Map.of("price", FORMATTER.format(stats.bestBid())))); } lore.add(" "); - lore.add(I18n.string("gui_bazaar.item.create_sell_order_click")); + lore.add(I18n.string("gui_bazaar.item.create_sell_order_click", l)); - return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.create_sell_order"), Material.MAP, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.item.create_sell_order", l), Material.MAP, 1, lore); } }); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarItemSet.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarItemSet.java index 174cb369e..9fa4b0a6c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarItemSet.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarItemSet.java @@ -11,6 +11,7 @@ import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; @@ -24,6 +25,7 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -63,8 +65,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return getStack(I18n.string("gui_bazaar.item_set.manage_orders_button"), Material.BOOK, 1, - I18n.lore("gui_bazaar.item_set.manage_orders_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_bazaar.item_set.manage_orders_button", Material.BOOK, 1, + "gui_bazaar.item_set.manage_orders_button.lore"); } }); } @@ -89,30 +91,31 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.item_set.commodity_label", Map.of("rarity", StringUtility.toNormalCase(itemType.rarity.name())))); + lore.add(I18n.string("gui_bazaar.item_set.commodity_label", l, Map.of("rarity", StringUtility.toNormalCase(itemType.rarity.name())))); lore.add(" "); if (stats.bestAsk() > 0) { - lore.add(I18n.string("gui_bazaar.item_set.buy_price", Map.of("price", new DecimalFormat("#,###").format(stats.bestAsk())))); - lore.add(I18n.string("gui_bazaar.item_set.buy_price_best", Map.of("price", StringUtility.shortenNumber(stats.bestAsk())))); + lore.add(I18n.string("gui_bazaar.item_set.buy_price", l, Map.of("price", new DecimalFormat("#,###").format(stats.bestAsk())))); + lore.add(I18n.string("gui_bazaar.item_set.buy_price_best", l, Map.of("price", StringUtility.shortenNumber(stats.bestAsk())))); } else { - lore.add(I18n.string("gui_bazaar.item_set.buy_price_none")); - lore.add(I18n.string("gui_bazaar.item_set.buy_price_none_desc")); + lore.add(I18n.string("gui_bazaar.item_set.buy_price_none", l)); + lore.add(I18n.string("gui_bazaar.item_set.buy_price_none_desc", l)); } lore.add(" "); if (stats.bestBid() > 0) { - lore.add(I18n.string("gui_bazaar.item_set.sell_price", Map.of("price", new DecimalFormat("#,###").format(stats.bestBid())))); - lore.add(I18n.string("gui_bazaar.item_set.sell_price_best", Map.of("price", StringUtility.shortenNumber(stats.bestBid())))); + lore.add(I18n.string("gui_bazaar.item_set.sell_price", l, Map.of("price", new DecimalFormat("#,###").format(stats.bestBid())))); + lore.add(I18n.string("gui_bazaar.item_set.sell_price_best", l, Map.of("price", StringUtility.shortenNumber(stats.bestBid())))); } else { - lore.add(I18n.string("gui_bazaar.item_set.sell_price_none")); - lore.add(I18n.string("gui_bazaar.item_set.sell_price_none_desc")); + lore.add(I18n.string("gui_bazaar.item_set.sell_price_none", l)); + lore.add(I18n.string("gui_bazaar.item_set.sell_price_none_desc", l)); } lore.add(" "); - lore.add(I18n.string("gui_bazaar.item_set.click_to_view")); + lore.add(I18n.string("gui_bazaar.item_set.click_to_view", l)); SkyBlockItem item = new SkyBlockItem(itemType); @@ -132,13 +135,14 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.item_set.commodity_label", Map.of("rarity", StringUtility.toNormalCase(itemType.rarity.name())))); + lore.add(I18n.string("gui_bazaar.item_set.commodity_label", l, Map.of("rarity", StringUtility.toNormalCase(itemType.rarity.name())))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.item_set.error_loading")); - lore.add(I18n.string("gui_bazaar.item_set.error_try_again")); + lore.add(I18n.string("gui_bazaar.item_set.error_loading", l)); + lore.add(I18n.string("gui_bazaar.item_set.error_try_again", l)); lore.add(" "); - lore.add(I18n.string("gui_bazaar.item_set.click_to_view")); + lore.add(I18n.string("gui_bazaar.item_set.click_to_view", l)); return getStack( itemType.rarity.getColor() + itemType.getDisplayName(), @@ -203,7 +207,7 @@ public void refreshItems(HypixelPlayer p) { } player.getBazaarConnector().isOnline().thenAccept(online -> { if (!online) { - player.sendMessage(I18n.string("gui_bazaar.item_set.offline_message")); + player.sendMessage(I18n.string("gui_bazaar.item_set.offline_message", player.getLocale())); player.closeInventory(); } }); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrderCompletedOptions.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrderCompletedOptions.java index fb316983f..7b98fd05d 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrderCompletedOptions.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrderCompletedOptions.java @@ -7,6 +7,7 @@ import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -22,6 +23,7 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIBazaarOrderCompletedOptions extends HypixelInventoryGUI { @@ -105,28 +107,29 @@ private void setupItems() { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.order_completed.order_completed_label")); + lore.add(I18n.string("gui_bazaar.order_completed.order_completed_label", l)); lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_completed.completed_count", Map.of("amount", String.valueOf((int) summary.totalQuantity), "item_name", finalItemType.getDisplayName()))); - lore.add(I18n.string("gui_bazaar.order_completed.transactions_count", Map.of("count", String.valueOf(summary.transactionCount)))); + lore.add(I18n.string("gui_bazaar.order_completed.completed_count", l, Map.of("amount", String.valueOf((int) summary.totalQuantity), "item_name", finalItemType.getDisplayName()))); + lore.add(I18n.string("gui_bazaar.order_completed.transactions_count", l, Map.of("count", String.valueOf(summary.transactionCount)))); lore.add(" "); if (isSell) { - lore.add(I18n.string("gui_bazaar.order_completed.gross_earnings", Map.of("amount", FORMATTER.format(summary.totalSpent)))); - lore.add(I18n.string("gui_bazaar.order_completed.tax_paid", Map.of("amount", FORMATTER.format(summary.totalSecondaryAmount)))); - lore.add(I18n.string("gui_bazaar.order_completed.net_earnings", Map.of("amount", FORMATTER.format(Math.abs(summary.totalValue))))); + lore.add(I18n.string("gui_bazaar.order_completed.gross_earnings", l, Map.of("amount", FORMATTER.format(summary.totalSpent)))); + lore.add(I18n.string("gui_bazaar.order_completed.tax_paid", l, Map.of("amount", FORMATTER.format(summary.totalSecondaryAmount)))); + lore.add(I18n.string("gui_bazaar.order_completed.net_earnings", l, Map.of("amount", FORMATTER.format(Math.abs(summary.totalValue))))); } else { - lore.add(I18n.string("gui_bazaar.order_completed.total_spent", Map.of("amount", FORMATTER.format(summary.totalSpent)))); + lore.add(I18n.string("gui_bazaar.order_completed.total_spent", l, Map.of("amount", FORMATTER.format(summary.totalSpent)))); if (summary.totalSecondaryAmount > 0) { - lore.add(I18n.string("gui_bazaar.order_completed.total_saved", Map.of("amount", FORMATTER.format(summary.totalSecondaryAmount)))); - lore.add(I18n.string("gui_bazaar.order_completed.refund_ready", Map.of("amount", FORMATTER.format(summary.totalSecondaryAmount)))); + lore.add(I18n.string("gui_bazaar.order_completed.total_saved", l, Map.of("amount", FORMATTER.format(summary.totalSecondaryAmount)))); + lore.add(I18n.string("gui_bazaar.order_completed.refund_ready", l, Map.of("amount", FORMATTER.format(summary.totalSecondaryAmount)))); } } return ItemStackCreator.getStack( - I18n.string("gui_bazaar.order_completed.order_name", Map.of("item_name", finalItemType.getDisplayName())), + I18n.string("gui_bazaar.order_completed.order_name", l, Map.of("item_name", finalItemType.getDisplayName())), finalItemType.material, Math.max(1, (int) summary.totalQuantity), lore @@ -144,14 +147,15 @@ private void setupTransactionHistory() { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.order_completed.transaction_subtitle")); + lore.add(I18n.string("gui_bazaar.order_completed.transaction_subtitle", l)); lore.add(" "); int count = 0; for (var tx : completions) { if (count >= 10) { - lore.add(I18n.string("gui_bazaar.order_completed.transaction_more", Map.of("count", String.valueOf(completions.size() - 10)))); + lore.add(I18n.string("gui_bazaar.order_completed.transaction_more", l, Map.of("count", String.valueOf(completions.size() - 10)))); break; } @@ -161,19 +165,19 @@ public ItemStack.Builder getItem(HypixelPlayer p) { lore.add("§a▲ " + (int) tx.getQuantity() + "x at §6" + FORMATTER.format(tx.getPricePerUnit()) + " §8(" + timeStr + ")"); if (tx.getSecondaryAmount() > 0) { - lore.add(" " + I18n.string("gui_bazaar.order_completed.transaction_saved", Map.of("amount", FORMATTER.format(tx.getSecondaryAmount())))); + lore.add(" " + I18n.string("gui_bazaar.order_completed.transaction_saved", l, Map.of("amount", FORMATTER.format(tx.getSecondaryAmount())))); } } else if (tx.getType() == DatapointCompletedBazaarTransactions.TransactionType.SELL_COMPLETED) { lore.add("§6▼ " + (int) tx.getQuantity() + "x at §6" + FORMATTER.format(tx.getPricePerUnit()) + " §8(" + timeStr + ")"); - lore.add(" " + I18n.string("gui_bazaar.order_completed.transaction_tax", Map.of("amount", FORMATTER.format(tx.getSecondaryAmount())))); + lore.add(" " + I18n.string("gui_bazaar.order_completed.transaction_tax", l, Map.of("amount", FORMATTER.format(tx.getSecondaryAmount())))); } else if (tx.getType() == DatapointCompletedBazaarTransactions.TransactionType.REFUND) { - lore.add(I18n.string("gui_bazaar.order_completed.refund_label", Map.of("amount", FORMATTER.format(tx.getSecondaryAmount()))) + " §8(" + timeStr + ")"); + lore.add(I18n.string("gui_bazaar.order_completed.refund_label", l, Map.of("amount", FORMATTER.format(tx.getSecondaryAmount()))) + " §8(" + timeStr + ")"); } count++; } - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_completed.transaction_history"), Material.BOOK, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_completed.transaction_history", l), Material.BOOK, 1, lore); } }); } @@ -189,7 +193,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - List lore = new ArrayList<>(I18n.lore("gui_bazaar.order_completed.claim_rewards_header")); + Locale l = p.getLocale(); + List lore = new ArrayList<>(I18n.lore("gui_bazaar.order_completed.claim_rewards_header", l)); lore.add(" "); boolean isSell = isSellOrder(); @@ -203,9 +208,9 @@ public ItemStack.Builder getItem(HypixelPlayer p) { } lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_completed.claim_click")); + lore.add(I18n.string("gui_bazaar.order_completed.claim_click", l)); - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_completed.claim_rewards"), Material.CHEST, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_completed.claim_rewards", l), Material.CHEST, 1, lore); } }); } @@ -223,15 +228,16 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_completed.view_unfilled"), Material.COMPASS, 1, - I18n.lore("gui_bazaar.order_completed.view_unfilled.lore", Map.of("amount", String.valueOf((int) activeOrder.amount()), "price", FORMATTER.format(activeOrder.price())))); + return TranslatableItemStackCreator.getStack(p, "gui_bazaar.order_completed.view_unfilled", Material.COMPASS, 1, + "gui_bazaar.order_completed.view_unfilled.lore", Map.of("amount", String.valueOf((int) activeOrder.amount()), "price", FORMATTER.format(activeOrder.price()))); } }); } private void claimRewards(SkyBlockPlayer player) { + Locale l = player.getLocale(); if (completions == null || completions.isEmpty()) { - player.sendMessage(I18n.string("gui_bazaar.order_completed.no_rewards")); + player.sendMessage(I18n.string("gui_bazaar.order_completed.no_rewards", l)); return; } @@ -241,16 +247,16 @@ private void claimRewards(SkyBlockPlayer player) { try { if (isSell) { player.addCoins(Math.abs(summary.totalValue)); - player.sendMessage(I18n.string("gui_bazaar.order_completed.received_coins", Map.of("amount", FORMATTER.format(Math.abs(summary.totalValue))))); + player.sendMessage(I18n.string("gui_bazaar.order_completed.received_coins", l, Map.of("amount", FORMATTER.format(Math.abs(summary.totalValue))))); } else { SkyBlockItem item = new SkyBlockItem(itemType); item.setAmount((int) summary.totalQuantity); player.addAndUpdateItem(item); - player.sendMessage(I18n.string("gui_bazaar.order_completed.received_items", Map.of("amount", String.valueOf((int) summary.totalQuantity), "item_name", itemType.getDisplayName()))); + player.sendMessage(I18n.string("gui_bazaar.order_completed.received_items", l, Map.of("amount", String.valueOf((int) summary.totalQuantity), "item_name", itemType.getDisplayName()))); if (summary.totalSecondaryAmount > 0) { player.addCoins(summary.totalSecondaryAmount); - player.sendMessage(I18n.string("gui_bazaar.order_completed.received_refund", Map.of("amount", FORMATTER.format(summary.totalSecondaryAmount)))); + player.sendMessage(I18n.string("gui_bazaar.order_completed.received_refund", l, Map.of("amount", FORMATTER.format(summary.totalSecondaryAmount)))); } } @@ -265,13 +271,13 @@ private void claimRewards(SkyBlockPlayer player) { completedTransactions.claimTransactions(transactionIds); - player.sendMessage(I18n.string("gui_bazaar.order_completed.all_claimed")); + player.sendMessage(I18n.string("gui_bazaar.order_completed.all_claimed", l)); player.playSuccessSound(); new GUIBazaarOrders().open(player); } catch (Exception e) { - player.sendMessage(I18n.string("gui_bazaar.order_completed.claim_failed", Map.of("error", e.getMessage()))); + player.sendMessage(I18n.string("gui_bazaar.order_completed.claim_failed", l, Map.of("error", e.getMessage()))); System.err.println("Failed to claim bazaar rewards: " + e.getMessage()); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrderOptions.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrderOptions.java index e7d2fe650..0b29cb9db 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrderOptions.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrderOptions.java @@ -7,6 +7,7 @@ import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -22,6 +23,7 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIBazaarOrderOptions extends HypixelInventoryGUI { @@ -51,29 +53,30 @@ private void setupItems() { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); var relatedTransactions = getRelatedTransactions(player); double originalQuantity = getOriginalQuantity(player); double filledQuantity = getFilledQuantity(relatedTransactions); - lore.add(isSell ? I18n.string("gui_bazaar.order_options.order_type_sell") : I18n.string("gui_bazaar.order_options.order_type_buy")); + lore.add(isSell ? I18n.string("gui_bazaar.order_options.order_type_sell", l) : I18n.string("gui_bazaar.order_options.order_type_buy", l)); lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_options.original_amount", Map.of("amount", String.valueOf((int) originalQuantity)))); - lore.add(I18n.string("gui_bazaar.order_options.remaining_amount", Map.of("amount", String.valueOf((int) order.amount())))); - lore.add(I18n.string("gui_bazaar.order_options.price_per_unit", Map.of("price", FORMATTER.format(order.price())))); + lore.add(I18n.string("gui_bazaar.order_options.original_amount", l, Map.of("amount", String.valueOf((int) originalQuantity)))); + lore.add(I18n.string("gui_bazaar.order_options.remaining_amount", l, Map.of("amount", String.valueOf((int) order.amount())))); + lore.add(I18n.string("gui_bazaar.order_options.price_per_unit", l, Map.of("price", FORMATTER.format(order.price())))); lore.add(" "); if (filledQuantity > 0) { - lore.add(I18n.string("gui_bazaar.order_options.filled_items", Map.of("count", String.valueOf((int) filledQuantity)))); - lore.add(I18n.string("gui_bazaar.order_options.filled_progress", Map.of("percent", String.format("%.1f%%", (filledQuantity / originalQuantity) * 100)))); + lore.add(I18n.string("gui_bazaar.order_options.filled_items", l, Map.of("count", String.valueOf((int) filledQuantity)))); + lore.add(I18n.string("gui_bazaar.order_options.filled_progress", l, Map.of("percent", String.format("%.1f%%", (filledQuantity / originalQuantity) * 100)))); } else { - lore.add(I18n.string("gui_bazaar.order_options.no_fills")); - lore.add(I18n.string("gui_bazaar.order_options.no_fills_progress")); + lore.add(I18n.string("gui_bazaar.order_options.no_fills", l)); + lore.add(I18n.string("gui_bazaar.order_options.no_fills_progress", l)); } lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_options.order_id", Map.of("id", order.orderId().toString().substring(0, 8)))); + lore.add(I18n.string("gui_bazaar.order_options.order_id", l, Map.of("id", order.orderId().toString().substring(0, 8)))); return ItemStackCreator.getStack( (isSell ? "§6" : "§a") + itemType.getDisplayName() + " Order", @@ -95,22 +98,23 @@ private void setupTransactionHistory() { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.order_options.transaction_history_subtitle")); + lore.add(I18n.string("gui_bazaar.order_options.transaction_history_subtitle", l)); lore.add(" "); var transactions = getRelatedTransactions(player); if (transactions.isEmpty()) { - lore.add(I18n.string("gui_bazaar.order_options.no_transactions")); - lore.add(I18n.string("gui_bazaar.order_options.no_transactions_pending")); + lore.add(I18n.string("gui_bazaar.order_options.no_transactions", l)); + lore.add(I18n.string("gui_bazaar.order_options.no_transactions_pending", l)); } else { - lore.add(I18n.string("gui_bazaar.order_options.transaction_count", Map.of("count", String.valueOf(transactions.size()), "suffix", transactions.size() == 1 ? "" : "s"))); + lore.add(I18n.string("gui_bazaar.order_options.transaction_count", l, Map.of("count", String.valueOf(transactions.size()), "suffix", transactions.size() == 1 ? "" : "s"))); lore.add(" "); int count = 0; for (var tx : transactions) { if (count >= 5) { - lore.add(I18n.string("gui_bazaar.order_options.transaction_more", Map.of("count", String.valueOf(transactions.size() - 5)))); + lore.add(I18n.string("gui_bazaar.order_options.transaction_more", l, Map.of("count", String.valueOf(transactions.size() - 5)))); break; } @@ -119,18 +123,18 @@ public ItemStack.Builder getItem(HypixelPlayer p) { lore.add("§a▲ " + (int) tx.getQuantity() + "x at §6" + FORMATTER.format(tx.getPricePerUnit()) + " §8(" + timeStr + ")"); if (tx.getSecondaryAmount() > 0) { - lore.add(" " + I18n.string("gui_bazaar.order_options.transaction_saved", Map.of("amount", FORMATTER.format(tx.getSecondaryAmount())))); + lore.add(" " + I18n.string("gui_bazaar.order_options.transaction_saved", l, Map.of("amount", FORMATTER.format(tx.getSecondaryAmount())))); } } else if (tx.getType() == DatapointCompletedBazaarTransactions.TransactionType.SELL_COMPLETED) { lore.add("§6▼ " + (int) tx.getQuantity() + "x at §6" + FORMATTER.format(tx.getPricePerUnit()) + " §8(" + timeStr + ")"); - lore.add(" " + I18n.string("gui_bazaar.order_options.transaction_tax", Map.of("amount", FORMATTER.format(tx.getSecondaryAmount())))); + lore.add(" " + I18n.string("gui_bazaar.order_options.transaction_tax", l, Map.of("amount", FORMATTER.format(tx.getSecondaryAmount())))); } count++; } } - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.transaction_history"), Material.BOOK, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.transaction_history", l), Material.BOOK, 1, lore); } }); } @@ -142,18 +146,19 @@ private void setupFinancialSummary() { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.order_options.financial_subtitle")); + lore.add(I18n.string("gui_bazaar.order_options.financial_subtitle", l)); lore.add(" "); var transactions = getRelatedTransactions(player); double originalValue = getOriginalQuantity(player) * order.price(); double currentValue = order.amount() * order.price(); - lore.add(I18n.string("gui_bazaar.order_options.original_order_value")); + lore.add(I18n.string("gui_bazaar.order_options.original_order_value", l)); lore.add(" §6" + FORMATTER.format(originalValue) + " coins"); lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_options.remaining_order_value")); + lore.add(I18n.string("gui_bazaar.order_options.remaining_order_value", l)); lore.add(" §6" + FORMATTER.format(currentValue) + " coins"); lore.add(" "); @@ -167,12 +172,12 @@ public ItemStack.Builder getItem(HypixelPlayer p) { .sum(); double netEarned = totalEarned - totalTax; - lore.add(I18n.string("gui_bazaar.order_options.transactions_completed")); - lore.add(" " + I18n.string("gui_bazaar.order_options.gross_prefix") + FORMATTER.format(totalEarned) + " coins"); - lore.add(" " + I18n.string("gui_bazaar.order_options.tax_prefix") + FORMATTER.format(totalTax) + " coins"); - lore.add(" " + I18n.string("gui_bazaar.order_options.net_prefix") + FORMATTER.format(netEarned) + " coins"); + lore.add(I18n.string("gui_bazaar.order_options.transactions_completed", l)); + lore.add(" " + I18n.string("gui_bazaar.order_options.gross_prefix", l) + FORMATTER.format(totalEarned) + " coins"); + lore.add(" " + I18n.string("gui_bazaar.order_options.tax_prefix", l) + FORMATTER.format(totalTax) + " coins"); + lore.add(" " + I18n.string("gui_bazaar.order_options.net_prefix", l) + FORMATTER.format(netEarned) + " coins"); lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_options.avg_sell_price")); + lore.add(I18n.string("gui_bazaar.order_options.avg_sell_price", l)); lore.add(" §6" + FORMATTER.format(totalEarned / getFilledQuantity(transactions)) + " coins/item"); } else { double totalSpent = transactions.stream() @@ -182,17 +187,17 @@ public ItemStack.Builder getItem(HypixelPlayer p) { .mapToDouble(DatapointCompletedBazaarTransactions.CompletedBazaarTransaction::getSecondaryAmount) .sum(); - lore.add(I18n.string("gui_bazaar.order_options.transactions_completed")); - lore.add(" " + I18n.string("gui_bazaar.order_options.spent_prefix") + FORMATTER.format(totalSpent) + " coins"); - lore.add(" " + I18n.string("gui_bazaar.order_options.saved_prefix") + FORMATTER.format(totalSaved) + " coins"); + lore.add(I18n.string("gui_bazaar.order_options.transactions_completed", l)); + lore.add(" " + I18n.string("gui_bazaar.order_options.spent_prefix", l) + FORMATTER.format(totalSpent) + " coins"); + lore.add(" " + I18n.string("gui_bazaar.order_options.saved_prefix", l) + FORMATTER.format(totalSaved) + " coins"); lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_options.avg_buy_price")); + lore.add(I18n.string("gui_bazaar.order_options.avg_buy_price", l)); lore.add(" §6" + FORMATTER.format(totalSpent / getFilledQuantity(transactions)) + " coins/item"); - lore.add(I18n.string("gui_bazaar.order_options.vs_your_bid", Map.of("price", FORMATTER.format(order.price())))); + lore.add(I18n.string("gui_bazaar.order_options.vs_your_bid", l, Map.of("price", FORMATTER.format(order.price())))); } } - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.financial_summary"), Material.GOLD_INGOT, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.financial_summary", l), Material.GOLD_INGOT, 1, lore); } }); } @@ -205,27 +210,28 @@ private void setupActionButtons() { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_message")); + Locale l = p.getLocale(); + p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_message", l)); player.getBazaarConnector().cancelOrder(order.orderId()) .thenAccept(success -> { if (success) { - p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_success")); + p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_success", l)); if (isSell) { SkyBlockItem item = new SkyBlockItem(order.getItemType()); item.setAmount((int) order.amount()); player.addAndUpdateItem(item); - p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_return_items", Map.of("amount", String.valueOf((int) order.amount()), "item_name", itemType.getDisplayName()))); + p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_return_items", l, Map.of("amount", String.valueOf((int) order.amount()), "item_name", itemType.getDisplayName()))); } else { double refund = order.price() * order.amount(); player.addCoins(refund); - p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_refund_coins", Map.of("amount", FORMATTER.format(refund)))); + p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_refund_coins", l, Map.of("amount", FORMATTER.format(refund)))); } new GUIBazaarOrders().open(p); } else { - p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_failed")); + p.sendMessage(I18n.string("gui_bazaar.order_options.cancel_failed", l)); } }); } @@ -233,7 +239,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - List lore = new ArrayList<>(I18n.lore("gui_bazaar.order_options.cancel_order.lore_header")); + Locale l = p.getLocale(); + List lore = new ArrayList<>(I18n.lore("gui_bazaar.order_options.cancel_order.lore_header", l)); lore.add(" "); if (isSell) { @@ -243,12 +250,12 @@ public ItemStack.Builder getItem(HypixelPlayer p) { } lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_options.cancel_undone")); - lore.addAll(I18n.lore("gui_bazaar.order_options.cancel_completed_remain")); + lore.add(I18n.string("gui_bazaar.order_options.cancel_undone", l)); + lore.addAll(I18n.lore("gui_bazaar.order_options.cancel_completed_remain", l)); lore.add(" "); - lore.add(I18n.string("gui_bazaar.order_options.cancel_click")); + lore.add(I18n.string("gui_bazaar.order_options.cancel_click", l)); - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.cancel_order"), Material.RED_DYE, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.cancel_order", l), Material.RED_DYE, 1, lore); } }); @@ -262,8 +269,9 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.view_market"), Material.EMERALD, 1, - I18n.lore("gui_bazaar.order_options.view_market.lore", Map.of("item_name", itemType.getDisplayName()))); + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.view_market", l), Material.EMERALD, 1, + I18n.lore("gui_bazaar.order_options.view_market.lore", l, Map.of("item_name", itemType.getDisplayName()))); } }); } @@ -285,13 +293,14 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { if (!unclaimedForThisOrder.isEmpty()) { new GUIBazaarOrderCompletedOptions(unclaimedForThisOrder, order).open(p); } else { - p.sendMessage(I18n.string("gui_bazaar.order_options.no_completed_message")); + p.sendMessage(I18n.string("gui_bazaar.order_options.no_completed_message", p.getLocale())); } } @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); var completedTransactions = player.getSkyblockDataHandler().get( SkyBlockDataHandler.Data.COMPLETED_BAZAAR_TRANSACTIONS, DatapointCompletedBazaarTransactions.class @@ -302,15 +311,15 @@ public ItemStack.Builder getItem(HypixelPlayer p) { .toList(); if (unclaimedForThisOrder.isEmpty()) { - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.no_completed"), Material.GRAY_DYE, 1, - I18n.lore("gui_bazaar.order_options.no_completed.lore")); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.no_completed", l), Material.GRAY_DYE, 1, + I18n.lore("gui_bazaar.order_options.no_completed.lore", l)); } else { double totalValue = unclaimedForThisOrder.stream() .mapToDouble(DatapointCompletedBazaarTransactions.CompletedBazaarTransaction::getTotalValue) .sum(); - return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.view_completed"), Material.CHEST, 1, - I18n.lore("gui_bazaar.order_options.view_completed.lore", Map.of( + return ItemStackCreator.getStack(I18n.string("gui_bazaar.order_options.view_completed", l), Material.CHEST, 1, + I18n.lore("gui_bazaar.order_options.view_completed.lore", l, Map.of( "count", String.valueOf(unclaimedForThisOrder.size()), "suffix", unclaimedForThisOrder.size() == 1 ? "" : "s", "amount", FORMATTER.format(Math.abs(totalValue)) diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrders.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrders.java index 43a76129a..6599b2800 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrders.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/GUIBazaarOrders.java @@ -19,6 +19,7 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; @@ -36,8 +37,9 @@ public GUIBazaarOrders() { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.orders.sell_orders_header"), Material.GOLD_INGOT, 1, - I18n.lore("gui_bazaar.orders.sell_orders_header.lore")); + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.orders.sell_orders_header", l), Material.GOLD_INGOT, 1, + I18n.lore("gui_bazaar.orders.sell_orders_header.lore", l)); } }); @@ -45,8 +47,9 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.orders.buy_orders_header"), Material.EMERALD, 1, - I18n.lore("gui_bazaar.orders.buy_orders_header.lore")); + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.orders.buy_orders_header", l), Material.EMERALD, 1, + I18n.lore("gui_bazaar.orders.buy_orders_header.lore", l)); } }); } @@ -118,8 +121,9 @@ private void updateOrderDisplay(List items) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.orders.no_sell_orders"), Material.BARRIER, 1, - I18n.lore("gui_bazaar.orders.no_sell_orders.lore")); + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.orders.no_sell_orders", l), Material.BARRIER, 1, + I18n.lore("gui_bazaar.orders.no_sell_orders.lore", l)); } }); } @@ -129,8 +133,9 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.orders.no_buy_orders"), Material.BARRIER, 1, - I18n.lore("gui_bazaar.orders.no_buy_orders.lore")); + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.orders.no_buy_orders", l), Material.BARRIER, 1, + I18n.lore("gui_bazaar.orders.no_buy_orders.lore", l)); } }); } @@ -153,7 +158,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return item.createDisplayItem(); + return item.createDisplayItem(p.getLocale()); } }; } @@ -215,16 +220,16 @@ public List get return completions; } - public ItemStack.Builder createDisplayItem() { + public ItemStack.Builder createDisplayItem(Locale l) { if (isCompleted && completions != null && !completions.isEmpty()) { - return createCompletedOrderDisplay(); + return createCompletedOrderDisplay(l); } else if (activeOrder != null) { - return createActiveOrderDisplay(); + return createActiveOrderDisplay(l); } return ItemStack.builder(Material.AIR); } - private ItemStack.Builder createCompletedOrderDisplay() { + private ItemStack.Builder createCompletedOrderDisplay(Locale l) { var firstCompletion = completions.getFirst(); String itemName = firstCompletion.getItemName(); ItemType itemType; @@ -238,7 +243,6 @@ private ItemStack.Builder createCompletedOrderDisplay() { List lore = new ArrayList<>(); boolean isSell = isSellOrder(); - // Single-pass calculation for better performance double totalQuantity = 0; double totalValue = 0; double totalRefund = 0; @@ -248,25 +252,25 @@ private ItemStack.Builder createCompletedOrderDisplay() { totalRefund += completion.getSecondaryAmount(); } - lore.add(I18n.string("gui_bazaar.orders.completed_label")); - lore.add(I18n.string("gui_bazaar.orders.completed_ready")); + lore.add(I18n.string("gui_bazaar.orders.completed_label", l)); + lore.add(I18n.string("gui_bazaar.orders.completed_ready", l)); lore.add(" "); - lore.add(I18n.string("gui_bazaar.orders.completed_amount", Map.of("amount", String.valueOf((int)totalQuantity)))); - lore.add(I18n.string("gui_bazaar.orders.completed_value", Map.of("amount", FORMATTER.format(Math.abs(totalValue))))); + lore.add(I18n.string("gui_bazaar.orders.completed_amount", l, Map.of("amount", String.valueOf((int)totalQuantity)))); + lore.add(I18n.string("gui_bazaar.orders.completed_value", l, Map.of("amount", FORMATTER.format(Math.abs(totalValue))))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.orders.completed_receive")); + lore.add(I18n.string("gui_bazaar.orders.completed_receive", l)); if (isSell) { - lore.add(" " + I18n.string("gui_bazaar.orders.completed_receive_coins", Map.of("amount", FORMATTER.format(Math.abs(totalValue))))); + lore.add(" " + I18n.string("gui_bazaar.orders.completed_receive_coins", l, Map.of("amount", FORMATTER.format(Math.abs(totalValue))))); } else { - lore.add(" " + I18n.string("gui_bazaar.orders.completed_receive_items", Map.of("amount", String.valueOf((int)totalQuantity), "item_name", itemType.getDisplayName()))); + lore.add(" " + I18n.string("gui_bazaar.orders.completed_receive_items", l, Map.of("amount", String.valueOf((int)totalQuantity), "item_name", itemType.getDisplayName()))); if (totalValue > 0) { - lore.add(" " + I18n.string("gui_bazaar.orders.completed_receive_refund", Map.of("amount", FORMATTER.format(totalRefund)))); + lore.add(" " + I18n.string("gui_bazaar.orders.completed_receive_refund", l, Map.of("amount", FORMATTER.format(totalRefund)))); } } lore.add(" "); - lore.add(I18n.string("gui_bazaar.orders.completed_click")); + lore.add(I18n.string("gui_bazaar.orders.completed_click", l)); return ItemStackCreator.getStack( "§a§l" + (isSell ? "SELL" : "BUY") + " §f" + itemType.getDisplayName(), @@ -276,18 +280,18 @@ private ItemStack.Builder createCompletedOrderDisplay() { ); } - private ItemStack.Builder createActiveOrderDisplay() { + private ItemStack.Builder createActiveOrderDisplay(Locale l) { List lore = new ArrayList<>(); boolean isSell = activeOrder.side() == BazaarConnector.OrderSide.SELL; ItemType itemType = activeOrder.getItemType(); - lore.add(I18n.string("gui_bazaar.orders.active_worth", Map.of("amount", FORMATTER.format(activeOrder.getTotalValue())))); + lore.add(I18n.string("gui_bazaar.orders.active_worth", l, Map.of("amount", FORMATTER.format(activeOrder.getTotalValue())))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.orders.active_order_amount", Map.of("amount", String.valueOf((int)activeOrder.amount())))); + lore.add(I18n.string("gui_bazaar.orders.active_order_amount", l, Map.of("amount", String.valueOf((int)activeOrder.amount())))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.orders.active_price_per_unit", Map.of("price", FORMATTER.format(activeOrder.price())))); + lore.add(I18n.string("gui_bazaar.orders.active_price_per_unit", l, Map.of("price", FORMATTER.format(activeOrder.price())))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.orders.active_click")); + lore.add(I18n.string("gui_bazaar.orders.active_click", l)); return ItemStackCreator.getStack( (isSell ? "§6§l" : "§a§l") + activeOrder.side() + " §f" + itemType.getDisplayName(), diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/selections/GUIBazaarOrderAmountSelection.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/selections/GUIBazaarOrderAmountSelection.java index 9b67e4527..03d21fc30 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/selections/GUIBazaarOrderAmountSelection.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/selections/GUIBazaarOrderAmountSelection.java @@ -17,6 +17,7 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -100,16 +101,17 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); lore.add("§7" + subtitle); - lore.add(I18n.string("gui_bazaar.amount_selection.per_unit", Map.of("price", F.format(unitPrice)))); + lore.add(I18n.string("gui_bazaar.amount_selection.per_unit", l, Map.of("price", F.format(unitPrice)))); lore.add(isBuy - ? I18n.string("gui_bazaar.amount_selection.total_cost", Map.of("amount", F.format(unitPrice * qty))) - : I18n.string("gui_bazaar.amount_selection.total_rev", Map.of("amount", F.format(unitPrice * qty)))); + ? I18n.string("gui_bazaar.amount_selection.total_cost", l, Map.of("amount", F.format(unitPrice * qty))) + : I18n.string("gui_bazaar.amount_selection.total_rev", l, Map.of("amount", F.format(unitPrice * qty)))); lore.add(" "); lore.add(isBuy - ? I18n.string("gui_bazaar.amount_selection.click_buy") - : I18n.string("gui_bazaar.amount_selection.click_sell")); + ? I18n.string("gui_bazaar.amount_selection.click_buy", l) + : I18n.string("gui_bazaar.amount_selection.click_sell", l)); return ItemStackCreator.getStack( (isBuy ? "§a" : "§6") + title, itemType.material, qty, lore @@ -130,12 +132,13 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_bazaar.amount_selection.limit_subtitle")); + lore.add(I18n.string("gui_bazaar.amount_selection.limit_subtitle", l)); lore.add("§7" + amountLine); - lore.add(I18n.string("gui_bazaar.amount_selection.per_unit", Map.of("price", F.format(unitPrice)))); + lore.add(I18n.string("gui_bazaar.amount_selection.per_unit", l, Map.of("price", F.format(unitPrice)))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.amount_selection.limit_click")); + lore.add(I18n.string("gui_bazaar.amount_selection.limit_click", l)); return ItemStackCreator.getStack( "§b" + title, slot == 13 ? Material.CHEST : itemType.material, @@ -149,15 +152,16 @@ private void addCustom(int slot, SkyBlockPlayer p) { set(new GUIQueryItem(slot) { @Override public HypixelInventoryGUI onQueryFinish(String q, HypixelPlayer pl) { + Locale l = pl.getLocale(); try { int v = Integer.parseInt(q); if (v < 1 || v > maxAmount) { - pl.sendMessage(I18n.string("gui_bazaar.amount_selection.invalid_range", Map.of("max", String.valueOf(maxAmount)))); + pl.sendMessage(I18n.string("gui_bazaar.amount_selection.invalid_range", l, Map.of("max", String.valueOf(maxAmount)))); return null; } future.complete(v); } catch (NumberFormatException ex) { - pl.sendMessage(I18n.string("gui_bazaar.amount_selection.invalid_number")); + pl.sendMessage(I18n.string("gui_bazaar.amount_selection.invalid_number", l)); } return null; } @@ -165,15 +169,16 @@ public HypixelInventoryGUI onQueryFinish(String q, HypixelPlayer pl) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new ArrayList<>(); lore.add(isInstant - ? I18n.string("gui_bazaar.amount_selection.custom_instant") - : I18n.string("gui_bazaar.amount_selection.custom_limit")); - lore.add(I18n.string("gui_bazaar.amount_selection.custom_max", Map.of("max", String.valueOf(maxAmount)))); + ? I18n.string("gui_bazaar.amount_selection.custom_instant", l) + : I18n.string("gui_bazaar.amount_selection.custom_limit", l)); + lore.add(I18n.string("gui_bazaar.amount_selection.custom_max", l, Map.of("max", String.valueOf(maxAmount)))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.amount_selection.custom_click")); + lore.add(I18n.string("gui_bazaar.amount_selection.custom_click", l)); return ItemStackCreator.getStack( - I18n.string("gui_bazaar.amount_selection.custom_amount"), + I18n.string("gui_bazaar.amount_selection.custom_amount", l), Material.OAK_SIGN, 1, lore ); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/selections/GUIBazaarPriceSelection.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/selections/GUIBazaarPriceSelection.java index 2bc82f17a..8dbb73ddd 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/selections/GUIBazaarPriceSelection.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/bazaar/selections/GUIBazaarPriceSelection.java @@ -19,7 +19,7 @@ import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import java.util.List; - +import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -64,20 +64,21 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_bazaar.price_selection.spread_10pct"), + Locale l = p.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.price_selection.spread_10pct", l), Material.GOLDEN_HORSE_ARMOR, 1, - isSellOrder ? I18n.string("gui_bazaar.price_selection.offer_setup_sell") : I18n.string("gui_bazaar.price_selection.offer_setup_buy"), + isSellOrder ? I18n.string("gui_bazaar.price_selection.offer_setup_sell", l) : I18n.string("gui_bazaar.price_selection.offer_setup_buy", l), " ", - I18n.string("gui_bazaar.price_selection.lowest_price", Map.of("price", String.valueOf(lowestPrice))), - I18n.string("gui_bazaar.price_selection.highest_price", Map.of("price", String.valueOf(highestPrice))), - I18n.string("gui_bazaar.price_selection.spread", Map.of("high", String.valueOf(highestPrice), "low", String.valueOf(lowestPrice), "spread", String.valueOf(spread))), + I18n.string("gui_bazaar.price_selection.lowest_price", l, Map.of("price", String.valueOf(lowestPrice))), + I18n.string("gui_bazaar.price_selection.highest_price", l, Map.of("price", String.valueOf(highestPrice))), + I18n.string("gui_bazaar.price_selection.spread", l, Map.of("high", String.valueOf(highestPrice), "low", String.valueOf(lowestPrice), "spread", String.valueOf(spread))), " ", - isSellOrder ? I18n.string("gui_bazaar.price_selection.selling_amount", Map.of("amount", String.valueOf(amount))) : I18n.string("gui_bazaar.price_selection.buying_amount", Map.of("amount", String.valueOf(amount))), - I18n.string("gui_bazaar.price_selection.unit_price", Map.of("price", String.valueOf(spreadPrice))), + isSellOrder ? I18n.string("gui_bazaar.price_selection.selling_amount", l, Map.of("amount", String.valueOf(amount))) : I18n.string("gui_bazaar.price_selection.buying_amount", l, Map.of("amount", String.valueOf(amount))), + I18n.string("gui_bazaar.price_selection.unit_price", l, Map.of("price", String.valueOf(spreadPrice))), " ", - I18n.string("gui_bazaar.price_selection.total", Map.of("amount", String.valueOf(spreadPrice * amount))), + I18n.string("gui_bazaar.price_selection.total", l, Map.of("amount", String.valueOf(spreadPrice * amount))), " ", - I18n.string("gui_bazaar.price_selection.click_to_use")); + I18n.string("gui_bazaar.price_selection.click_to_use", l)); } }); @@ -93,18 +94,19 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new java.util.ArrayList<>(); - lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.offer_setup_sell") : I18n.string("gui_bazaar.price_selection.offer_setup_buy")); + lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.offer_setup_sell", l) : I18n.string("gui_bazaar.price_selection.offer_setup_buy", l)); lore.add(" "); - lore.addAll(I18n.lore("gui_bazaar.price_selection.best_offer_beat")); + lore.addAll(I18n.lore("gui_bazaar.price_selection.best_offer_beat", l)); lore.add(" "); - lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.selling_amount", Map.of("amount", String.valueOf(amount))) : I18n.string("gui_bazaar.price_selection.buying_amount", Map.of("amount", String.valueOf(amount)))); - lore.add(I18n.string("gui_bazaar.price_selection.unit_price", Map.of("price", String.valueOf(incrementedOffer)))); + lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.selling_amount", l, Map.of("amount", String.valueOf(amount))) : I18n.string("gui_bazaar.price_selection.buying_amount", l, Map.of("amount", String.valueOf(amount)))); + lore.add(I18n.string("gui_bazaar.price_selection.unit_price", l, Map.of("price", String.valueOf(incrementedOffer)))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.price_selection.total", Map.of("amount", String.valueOf(incrementedOffer * amount)))); + lore.add(I18n.string("gui_bazaar.price_selection.total", l, Map.of("amount", String.valueOf(incrementedOffer * amount)))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.price_selection.click_to_use")); - return ItemStackCreator.getStack(isSellOrder ? I18n.string("gui_bazaar.price_selection.best_offer_minus") : I18n.string("gui_bazaar.price_selection.best_offer_plus"), + lore.add(I18n.string("gui_bazaar.price_selection.click_to_use", l)); + return ItemStackCreator.getStack(isSellOrder ? I18n.string("gui_bazaar.price_selection.best_offer_minus", l) : I18n.string("gui_bazaar.price_selection.best_offer_plus", l), Material.GOLD_NUGGET, 1, lore); } }); @@ -120,18 +122,19 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new java.util.ArrayList<>(); - lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.offer_setup_sell") : I18n.string("gui_bazaar.price_selection.offer_setup_buy")); + lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.offer_setup_sell", l) : I18n.string("gui_bazaar.price_selection.offer_setup_buy", l)); lore.add(" "); - lore.addAll(I18n.lore("gui_bazaar.price_selection.same_as_best.lore")); + lore.addAll(I18n.lore("gui_bazaar.price_selection.same_as_best.lore", l)); lore.add(" "); - lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.selling_amount", Map.of("amount", String.valueOf(amount))) : I18n.string("gui_bazaar.price_selection.buying_amount", Map.of("amount", String.valueOf(amount)))); - lore.add(I18n.string("gui_bazaar.price_selection.unit_price", Map.of("price", String.valueOf(bestOffer)))); + lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.selling_amount", l, Map.of("amount", String.valueOf(amount))) : I18n.string("gui_bazaar.price_selection.buying_amount", l, Map.of("amount", String.valueOf(amount)))); + lore.add(I18n.string("gui_bazaar.price_selection.unit_price", l, Map.of("price", String.valueOf(bestOffer)))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.price_selection.total", Map.of("amount", String.valueOf(bestOffer * amount)))); + lore.add(I18n.string("gui_bazaar.price_selection.total", l, Map.of("amount", String.valueOf(bestOffer * amount)))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.price_selection.click_to_use")); - return ItemStackCreator.getStack(I18n.string("gui_bazaar.price_selection.same_as_best"), + lore.add(I18n.string("gui_bazaar.price_selection.click_to_use", l)); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.price_selection.same_as_best", l), itemTypeLinker.material, 1, lore); } }); @@ -146,7 +149,7 @@ public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer player) { future.complete(price); return null; } catch (NumberFormatException e) { - player.sendMessage(I18n.string("gui_bazaar.price_selection.invalid_price")); + player.sendMessage(I18n.string("gui_bazaar.price_selection.invalid_price", player.getLocale())); return null; } } @@ -154,15 +157,16 @@ public HypixelInventoryGUI onQueryFinish(String query, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); List lore = new java.util.ArrayList<>(); - lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.offer_setup_sell") : I18n.string("gui_bazaar.price_selection.offer_setup_buy")); + lore.add(isSellOrder ? I18n.string("gui_bazaar.price_selection.offer_setup_sell", l) : I18n.string("gui_bazaar.price_selection.offer_setup_buy", l)); lore.add(" "); - lore.addAll(I18n.lore("gui_bazaar.price_selection.custom_price.lore")); + lore.addAll(I18n.lore("gui_bazaar.price_selection.custom_price.lore", l)); lore.add(" "); - lore.add(I18n.string("gui_bazaar.price_selection.ordering_amount", Map.of("amount", String.valueOf(amount)))); + lore.add(I18n.string("gui_bazaar.price_selection.ordering_amount", l, Map.of("amount", String.valueOf(amount)))); lore.add(" "); - lore.add(I18n.string("gui_bazaar.price_selection.custom_click")); - return ItemStackCreator.getStack(I18n.string("gui_bazaar.price_selection.custom_price"), + lore.add(I18n.string("gui_bazaar.price_selection.custom_click", l)); + return ItemStackCreator.getStack(I18n.string("gui_bazaar.price_selection.custom_price", l), Material.OAK_SIGN, 1, lore); } }); @@ -197,7 +201,7 @@ public void onBottomClick(InventoryPreClickEvent e) { @Override public void refreshItems(HypixelPlayer player) { if (!new ProxyService(ServiceType.BAZAAR).isOnline().join()) { - player.sendMessage(I18n.string("gui_bazaar.price_selection.offline_message")); + player.sendMessage(I18n.string("gui_bazaar.price_selection.offline_message", player.getLocale())); player.closeInventory(); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/builder/GUIBuilder.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/builder/GUIBuilder.java index 2bc3b5d18..b5081d859 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/builder/GUIBuilder.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/builder/GUIBuilder.java @@ -8,6 +8,7 @@ import net.swofty.type.generic.user.HypixelPlayer; import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; @@ -29,9 +30,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_builder.woodworking_button"), Material.OAK_PLANKS, 1, - I18n.lore("gui_builder.woodworking_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_builder.woodworking_button", Material.OAK_PLANKS, 1, + "gui_builder.woodworking_button.lore"); } }); set(new GUIClickableItem(12) { @@ -43,9 +43,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_builder.rocks_bricks_button"), Material.STONE, 1, - I18n.lore("gui_builder.rocks_bricks_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_builder.rocks_bricks_button", Material.STONE, 1, + "gui_builder.rocks_bricks_button.lore"); } }); set(new GUIClickableItem(14) { @@ -57,9 +56,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_builder.green_thumb_button"), Material.ROSE_BUSH, 1, - I18n.lore("gui_builder.green_thumb_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_builder.green_thumb_button", Material.ROSE_BUSH, 1, + "gui_builder.green_thumb_button.lore"); } }); set(new GUIClickableItem(16) { @@ -71,9 +69,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStackHead(I18n.string("gui_builder.variety_button"), "3c2d8e8ec2737b599a48fc07ea58b806969e6021802019992dda32a653794df6", 1, - I18n.lore("gui_builder.variety_button.lore")); + return TranslatableItemStackCreator.getStackHead(p, "gui_builder.variety_button", "3c2d8e8ec2737b599a48fc07ea58b806969e6021802019992dda32a653794df6", 1, + "gui_builder.variety_button.lore"); } }); updateItemStacks(getInventory(), getPlayer()); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/coop/GUICoopInviteSender.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/coop/GUICoopInviteSender.java index a8cbcf118..c76470f14 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/coop/GUICoopInviteSender.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/coop/GUICoopInviteSender.java @@ -17,6 +17,7 @@ import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.RefreshingGUI; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -29,6 +30,7 @@ import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -91,7 +93,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { } } - player.kick(I18n.string("gui_coop.sender.reconnect_kick")); + player.kick(I18n.string("gui_coop.sender.reconnect_kick", player.getLocale())); // Fixed: Use the updated method signature ProfilesDatabase.collection.insertOne(handler.toProfileDocument()); @@ -108,28 +110,27 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_coop.sender.confirm_button"), Material.GREEN_TERRACOTTA, 1, - I18n.lore("gui_coop.sender.confirm_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_coop.sender.confirm_button", Material.GREEN_TERRACOTTA, 1, + "gui_coop.sender.confirm_button.lore"); } }); set(new GUIClickableItem(33) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); coop = CoopDatabase.getFromMember(player.getUuid()); coop.removeInvite(player.getUuid()); coop.save(); player.closeInventory(); - player.sendMessage(I18n.string("gui_coop.sender.cancelled_message")); + player.sendMessage(I18n.string("gui_coop.sender.cancelled_message", l)); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { - SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_coop.sender.cancel_button"), Material.RED_TERRACOTTA, 1, - I18n.lore("gui_coop.sender.cancel_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_coop.sender.cancel_button", Material.RED_TERRACOTTA, 1, + "gui_coop.sender.cancel_button.lore"); } }); } @@ -143,9 +144,10 @@ public void refreshItems(HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); return ItemStackCreator.getStackHead( player.getFullDisplayName(), PlayerSkin.fromUuid(String.valueOf(player.getUuid())), 1, - I18n.lore("gui_coop.sender.player_head_self.lore")); + I18n.lore("gui_coop.sender.player_head_self.lore", l)); } }); @@ -166,10 +168,11 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - String status = accepted ? I18n.string("gui_coop.sender.accepted_yes") : I18n.string("gui_coop.sender.accepted_no"); + Locale l = p.getLocale(); + String status = accepted ? I18n.string("gui_coop.sender.accepted_yes", l) : I18n.string("gui_coop.sender.accepted_no", l); return ItemStackCreator.getStackHead( displayName, PlayerSkin.fromUuid(String.valueOf(target)), 1, - List.of(" ", I18n.string("gui_coop.sender.player_accepted", Map.of("status", status)))); + List.of(" ", I18n.string("gui_coop.sender.player_accepted", l, Map.of("status", status)))); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/coop/GUICoopInviteTarget.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/coop/GUICoopInviteTarget.java index 49140a294..826190b51 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/coop/GUICoopInviteTarget.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/coop/GUICoopInviteTarget.java @@ -16,6 +16,7 @@ import net.swofty.type.generic.data.mongodb.UserDatabase; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -28,6 +29,7 @@ import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -62,9 +64,10 @@ public GUICoopInviteTarget(CoopDatabase.Coop coop) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = p.getLocale(); return ItemStackCreator.getStackHead( SkyBlockPlayer.getDisplayName(coop.originator()), PlayerSkin.fromUuid(String.valueOf(coop.originator())), 1, - I18n.lore("gui_coop.target.originator_head.lore")); + I18n.lore("gui_coop.target.originator_head.lore", l)); } }); @@ -77,10 +80,11 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - String status = accepted ? I18n.string("gui_coop.sender.accepted_yes") : I18n.string("gui_coop.sender.accepted_no"); + Locale l = p.getLocale(); + String status = accepted ? I18n.string("gui_coop.sender.accepted_yes", l) : I18n.string("gui_coop.sender.accepted_no", l); return ItemStackCreator.getStackHead( displayName, PlayerSkin.fromUuid(String.valueOf(target)), 1, - List.of(" ", I18n.string("gui_coop.sender.player_accepted", Map.of("status", status)))); + List.of(" ", I18n.string("gui_coop.sender.player_accepted", l, Map.of("status", status)))); } }); } @@ -91,19 +95,20 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; coop.removeInvite(player.getUuid()); coop.save(); - player.sendMessage(I18n.string("gui_coop.target.denied_message")); + Locale l = p.getLocale(); + player.sendMessage(I18n.string("gui_coop.target.denied_message", l)); player.closeInventory(); SkyBlockPlayer target = SkyBlockGenericLoader.getLoadedPlayers().stream().filter(player1 -> player1.getUuid().equals(coop.originator())).findFirst().orElse(null); if (target != null && (coop.memberInvites().contains(target.getUuid()) || coop.members().contains(target.getUuid()))) - target.sendMessage(I18n.string("gui_coop.target.denied_notify", Map.of("player_name", player.getUsername()))); + target.sendMessage(I18n.string("gui_coop.target.denied_notify", target.getLocale(), Map.of("player_name", player.getUsername()))); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_coop.target.deny_button"), Material.BARRIER, 1); + return TranslatableItemStackCreator.getStack(p, "gui_coop.target.deny_button", Material.BARRIER, 1); } }); @@ -142,7 +147,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { } } - player.kick(I18n.string("gui_coop.target.reconnect_kick")); + player.kick(I18n.string("gui_coop.target.reconnect_kick", player.getLocale())); ProfilesDatabase.collection.insertOne(handler.toProfileDocument()); coop.memberProfiles().add(profileId); @@ -158,15 +163,15 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer target = SkyBlockGenericLoader.getLoadedPlayers().stream().filter(player1 -> player1.getUuid().equals(coop.originator())).findFirst().orElse(null); if (target != null && (coop.memberInvites().contains(target.getUuid()) || coop.members().contains(target.getUuid()))) - target.sendMessage(I18n.string("gui_coop.target.accepted_notify", Map.of("player_name", player.getUsername()))); + target.sendMessage(I18n.string("gui_coop.target.accepted_notify", target.getLocale(), Map.of("player_name", player.getUsername()))); } @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_coop.target.accept_button"), Material.GREEN_TERRACOTTA, 1, - I18n.lore("gui_coop.target.accept_button.lore", Map.of( - "profile_count", String.valueOf(player.getProfiles().getProfiles().size())))); + return TranslatableItemStackCreator.getStack(p, "gui_coop.target.accept_button", Material.GREEN_TERRACOTTA, 1, + "gui_coop.target.accept_button.lore", Map.of( + "profile_count", String.valueOf(player.getProfiles().getProfiles().size()))); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumArmorCategory.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumArmorCategory.java index b6ccf3b6b..263e38278 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumArmorCategory.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumArmorCategory.java @@ -16,6 +16,7 @@ import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.gui.inventory.HypixelPaginatedGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; @@ -32,6 +33,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -60,7 +62,7 @@ public void onBottomClick(InventoryPreClickEvent e) { DatapointMuseum.MuseumData data = player.getMuseumData(); if (data.getItemInMuseum(skyBlockItem.getAttributeHandler().getPotentialType()) != null) { - player.sendMessage(I18n.string("gui_museum.armor_category.already_in_museum", Map.of("item_name", skyBlockItem.getAttributeHandler().getPotentialType().getDisplayName()))); + player.sendMessage(I18n.string("gui_museum.armor_category.already_in_museum", player.getLocale(), Map.of("item_name", skyBlockItem.getAttributeHandler().getPotentialType().getDisplayName()))); return; } @@ -77,7 +79,7 @@ public void onBottomClick(InventoryPreClickEvent e) { UUID uuidOfNew = UUID.fromString(skyBlockItem.getAttributeHandler().getUniqueTrackedID()); if (!uuidOfAlreadyInMuseum.equals(uuidOfNew)) { - player.sendMessage(I18n.string("gui_museum.armor_category.can_only_readd")); + player.sendMessage(I18n.string("gui_museum.armor_category.can_only_readd", player.getLocale())); return; } } @@ -128,7 +130,7 @@ public void onBottomClick(InventoryPreClickEvent e) { } if (missing != 0) { - player.sendMessage(I18n.string("gui_museum.armor_category.missing_items", Map.of("set_name", armorSetRegistry.getDisplayName(), "count", String.valueOf(4 - missing)))); + player.sendMessage(I18n.string("gui_museum.armor_category.missing_items", player.getLocale(), Map.of("set_name", armorSetRegistry.getDisplayName(), "count", String.valueOf(4 - missing)))); return; } @@ -143,7 +145,7 @@ public void onBottomClick(InventoryPreClickEvent e) { MuseumDisplays.updateDisplay(player); new GUIMuseumArmorCategory().open(player); - player.sendMessage(I18n.string("gui_museum.armor_category.donated", Map.of("set_name", armorSetRegistry.getDisplayName()))); + player.sendMessage(I18n.string("gui_museum.armor_category.donated", player.getLocale(), Map.of("set_name", armorSetRegistry.getDisplayName()))); } } @@ -217,10 +219,10 @@ public void performSearch(HypixelPlayer player, String query, int page, int maxP List lore = new ArrayList<>(item.getLore()); lore.add("§8§m---------------------"); - lore.add(I18n.string("gui_museum.category.item_created_label")); + lore.add(I18n.string("gui_museum.category.item_created_label", player.getLocale())); lore.add("§a" + StringUtility.formatAsDate(trackedItem.getCreated())); lore.add(" "); - lore.add(I18n.string("gui_museum.armor_category.click_to_donate_armor")); + lore.add(I18n.string("gui_museum.armor_category.click_to_donate_armor", player.getLocale())); player.getInventory().setItemStack(i, ItemStackCreator.updateLore(toReturn, lore) .set(DataComponents.CUSTOM_NAME, Component.text(item.getDisplayName()).decoration( @@ -232,7 +234,7 @@ public void performSearch(HypixelPlayer player, String query, int page, int maxP @Override public String getTitle(HypixelPlayer player, String query, int page, PaginationList paged) { - return I18n.string("gui_museum.armor_category.title"); + return I18n.string("gui_museum.armor_category.title", player.getLocale()); } @Override @@ -257,12 +259,12 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { } if (!player.hasEmptySlots(4)) { - player.sendMessage(I18n.string("gui_museum.armor_category.need_empty_slots")); + player.sendMessage(I18n.string("gui_museum.armor_category.need_empty_slots", player.getLocale())); return; } - player.sendMessage(I18n.string("gui_museum.armor_category.retrieved_message", Map.of("set_name", armorSet.getDisplayName()))); - player.sendMessage(I18n.string("gui_museum.armor_category.retrieved_return_message")); + player.sendMessage(I18n.string("gui_museum.armor_category.retrieved_message", player.getLocale(), Map.of("set_name", armorSet.getDisplayName()))); + player.sendMessage(I18n.string("gui_museum.armor_category.retrieved_return_message", player.getLocale())); List set = List.of(helmet, chestplate, leggings, boots); set.forEach(item -> { @@ -281,11 +283,13 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; if (!inMuseum) { - return ItemStackCreator.getStack(I18n.string("gui_museum.armor_category.not_in_museum", Map.of("set_name", armorSet.getDisplayName())), + Locale l = player.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_museum.armor_category.not_in_museum", l, Map.of("set_name", armorSet.getDisplayName())), Material.GRAY_DYE, 1, - I18n.lore("gui_museum.armor_category.not_in_museum.lore")); + I18n.lore("gui_museum.armor_category.not_in_museum.lore", l)); } + Locale l = player.getLocale(); ProxyService itemTracker = new ProxyService(ServiceType.ITEM_TRACKER); UUID helmetUUID = UUID.fromString(helmet.getAttributeHandler().getUniqueTrackedID()); UUID chestplateUUID = UUID.fromString(chestplate.getAttributeHandler().getUniqueTrackedID()); @@ -308,42 +312,42 @@ public ItemStack.Builder getItem(HypixelPlayer p) { List lore = new ArrayList<>(); lore.add("§8§m---------------------"); - lore.add(I18n.string("gui_museum.armor_category.set_donated_label")); + lore.add(I18n.string("gui_museum.armor_category.set_donated_label", l)); lore.add("§b" + StringUtility.formatAsDate(data.getInsertionTimes().get(helmetUUID))); lore.add(" "); - lore.add(I18n.string("gui_museum.armor_category.helmet_data")); + lore.add(I18n.string("gui_museum.armor_category.helmet_data", l)); lore.add("§a" + StringUtility.formatAsDate(trackedHelmet.getCreated())); lore.add("§6 " + StringUtility.commaifyAndTh(trackedHelmet.getNumberMade()) + " §7created"); lore.add(" "); - lore.add(I18n.string("gui_museum.armor_category.chestplate_data")); + lore.add(I18n.string("gui_museum.armor_category.chestplate_data", l)); lore.add("§a" + StringUtility.formatAsDate(trackedChestplate.getCreated())); lore.add("§6 " + StringUtility.commaifyAndTh(trackedChestplate.getNumberMade()) + " §7created"); lore.add(" "); - lore.add(I18n.string("gui_museum.armor_category.leggings_data")); + lore.add(I18n.string("gui_museum.armor_category.leggings_data", l)); lore.add("§a" + StringUtility.formatAsDate(trackedLeggings.getCreated())); lore.add("§6 " + StringUtility.commaifyAndTh(trackedLeggings.getNumberMade()) + " §7created"); lore.add(" "); - lore.add(I18n.string("gui_museum.armor_category.boots_data")); + lore.add(I18n.string("gui_museum.armor_category.boots_data", l)); lore.add("§a" + StringUtility.formatAsDate(trackedBoots.getCreated())); lore.add("§6 " + StringUtility.commaifyAndTh(trackedBoots.getNumberMade()) + " §7created"); lore.add(" "); - lore.add(I18n.string("gui_museum.armor_category.set_clean_value_label")); + lore.add(I18n.string("gui_museum.armor_category.set_clean_value_label", l)); lore.add("§6" + StringUtility.commaify(helmetValue + chestplateValue + leggingsValue + bootsValue) + " Coins"); lore.add(" "); - lore.add(I18n.string("gui_museum.armor_category.set_value_label")); + lore.add(I18n.string("gui_museum.armor_category.set_value_label", l)); if (data.getCalculatedPrices().containsKey(helmetUUID)) { lore.add("§6" + StringUtility.commaify(data.getCalculatedPrices().get(helmetUUID)) + " Coins"); } else { - lore.add(I18n.string("gui_museum.category.uncalculated")); + lore.add(I18n.string("gui_museum.category.uncalculated", l)); } if (hasTakenItOut) { lore.add("§8§m---------------------"); - lore.addAll(I18n.lore("gui_museum.armor_category.retrieved_from_museum.lore")); + lore.addAll(I18n.lore("gui_museum.armor_category.retrieved_from_museum.lore", l)); } else { lore.add(" "); - lore.add(I18n.string("gui_museum.armor_category.click_to_retrieve")); + lore.add(I18n.string("gui_museum.armor_category.click_to_retrieve", l)); } return ItemStackCreator.getStack("§a" + armorSet.getDisplayName(), diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumCategory.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumCategory.java index a4c53750a..e0de41d13 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumCategory.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumCategory.java @@ -16,6 +16,7 @@ import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.gui.inventory.HypixelPaginatedGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; @@ -30,6 +31,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -62,7 +64,7 @@ public void onBottomClick(InventoryPreClickEvent e) { DatapointMuseum.MuseumData data = player.getMuseumData(); if (data.getItemInMuseum(skyBlockItem.getAttributeHandler().getPotentialType()) != null) { - player.sendMessage(I18n.string("gui_museum.category.already_in_museum", Map.of("item_name", skyBlockItem.getDisplayName()))); + player.sendMessage(I18n.string("gui_museum.category.already_in_museum", player.getLocale(), Map.of("item_name", skyBlockItem.getDisplayName()))); return; } @@ -74,7 +76,7 @@ public void onBottomClick(InventoryPreClickEvent e) { ); if (!trackedItemUUID.equals(previouslyInMuseumUUID)) { - player.sendMessage(I18n.string("gui_museum.category.can_only_readd")); + player.sendMessage(I18n.string("gui_museum.category.can_only_readd", player.getLocale())); return; } } @@ -88,7 +90,7 @@ public void onBottomClick(InventoryPreClickEvent e) { MuseumDisplays.updateDisplay(player); new GUIMuseumCategory(category).open(player); - player.sendMessage(I18n.string("gui_museum.category.donated", Map.of("item_name", skyBlockItem.getDisplayName()))); + player.sendMessage(I18n.string("gui_museum.category.donated", player.getLocale(), Map.of("item_name", skyBlockItem.getDisplayName()))); } } @@ -143,10 +145,10 @@ public void performSearch(HypixelPlayer p, String query, int page, int maxPage) ItemStack.Builder toReturn = item.getItemStackBuilder(); List lore = new ArrayList<>(item.getLore(player)); lore.add("§8§m---------------------"); - lore.add(I18n.string("gui_museum.category.item_created_label")); + lore.add(I18n.string("gui_museum.category.item_created_label", player.getLocale())); lore.add("§a" + StringUtility.formatAsDate(trackedItem.getCreated())); lore.add(" "); - lore.add(I18n.string("gui_museum.category.click_to_donate")); + lore.add(I18n.string("gui_museum.category.click_to_donate", player.getLocale())); player.getInventory().setItemStack(i, ItemStackCreator.updateLore(toReturn, lore) .set(DataComponents.CUSTOM_NAME, Component.text(item.getDisplayName()).decoration( @@ -159,7 +161,7 @@ public void performSearch(HypixelPlayer p, String query, int page, int maxPage) @Override public String getTitle(HypixelPlayer player, String query, int page, PaginationList paged) { - return I18n.string("gui_museum.category.title", Map.of("category", category.toString())); + return I18n.string("gui_museum.category.title", player.getLocale(), Map.of("category", category.toString())); } @Override @@ -178,8 +180,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { return; } - player.sendMessage(I18n.string("gui_museum.category.retrieved_message", Map.of("item_name", item.getDisplayName()))); - player.sendMessage(I18n.string("gui_museum.category.retrieved_return_message")); + player.sendMessage(I18n.string("gui_museum.category.retrieved_message", player.getLocale(), Map.of("item_name", item.getDisplayName()))); + player.sendMessage(I18n.string("gui_museum.category.retrieved_return_message", player.getLocale())); data.moveToRetrieved(skyBlockItem); player.setMuseumData(data); @@ -194,9 +196,10 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; if (!inMuseum) { - return ItemStackCreator.getStack(I18n.string("gui_museum.category.item_not_in_museum", Map.of("item_name", item.getDisplayName())), + Locale l = player.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_museum.category.item_not_in_museum", l, Map.of("item_name", item.getDisplayName())), Material.GRAY_DYE, 1, - I18n.lore("gui_museum.category.item_not_in_museum.lore")); + I18n.lore("gui_museum.category.item_not_in_museum.lore", l)); } UUID trackedItemUUID = UUID.fromString(skyBlockItem.getAttributeHandler().getUniqueTrackedID()); @@ -204,39 +207,40 @@ public ItemStack.Builder getItem(HypixelPlayer p) { TrackedItem trackedItem = ((TrackedItemRetrieveProtocolObject.TrackedItemResponse) new ProxyService(ServiceType.ITEM_TRACKER) .handleRequest(message).join()).trackedItem(); + Locale l = player.getLocale(); List lore = new ArrayList<>(skyBlockItem.getLore()); lore.add("§8§m---------------------"); - lore.add(I18n.string("gui_museum.category.item_donated_label")); + lore.add(I18n.string("gui_museum.category.item_donated_label", l)); lore.add("§b" + StringUtility.formatAsDate(data.getInsertionTimes().get(trackedItemUUID))); lore.add(" "); - lore.add(I18n.string("gui_museum.category.item_created_label")); + lore.add(I18n.string("gui_museum.category.item_created_label", player.getLocale())); lore.add("§a" + StringUtility.formatAsDate(trackedItem.getCreated())); lore.add("§6 " + StringUtility.commaifyAndTh(trackedItem.getNumberMade()) + " §7created"); lore.add(" "); - lore.add(I18n.string("gui_museum.category.item_clean_value_label")); + lore.add(I18n.string("gui_museum.category.item_clean_value_label", l)); lore.add("§6" + StringUtility.commaify(new ItemPriceCalculator(skyBlockItem).calculateCleanPrice()) + " Coins"); lore.add(" "); - lore.add(I18n.string("gui_museum.category.item_value_label")); + lore.add(I18n.string("gui_museum.category.item_value_label", l)); if (data.getCalculatedPrices().containsKey(trackedItemUUID)) { lore.add("§6" + StringUtility.commaify(data.getCalculatedPrices().get(trackedItemUUID)) + " Coins"); } else { - lore.add(I18n.string("gui_museum.category.uncalculated")); + lore.add(I18n.string("gui_museum.category.uncalculated", l)); } lore.add(" "); - lore.add(I18n.string("gui_museum.category.display_slot_label")); + lore.add(I18n.string("gui_museum.category.display_slot_label", l)); DatapointMuseum.DisplayPlacement placement = data.getDisplayHandler().getItemDisplayPlacement(skyBlockItem); if (data.getCurrentlyInMuseum().contains(skyBlockItem) && placement != null) { lore.add("§9" + placement.display() + " Slot #" + (placement.slot() + 1)); } else { - lore.add(I18n.string("gui_museum.category.not_in_display")); + lore.add(I18n.string("gui_museum.category.not_in_display", l)); } if (hasTakenItOut) { lore.add("§8§m---------------------"); - lore.addAll(I18n.lore("gui_museum.category.retrieved_from_museum.lore")); + lore.addAll(I18n.lore("gui_museum.category.retrieved_from_museum.lore", l)); } else { lore.add(" "); - lore.add(I18n.string("gui_museum.category.click_to_retrieve")); + lore.add(I18n.string("gui_museum.category.click_to_retrieve", l)); } return ItemStackCreator.getStack("§a" + item.getDisplayName(), diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumEmptyDisplay.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumEmptyDisplay.java index c63b42c7e..dd5d8ee97 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumEmptyDisplay.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumEmptyDisplay.java @@ -11,6 +11,7 @@ import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.gui.inventory.HypixelPaginatedGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -28,6 +29,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; @@ -104,7 +106,7 @@ public boolean shouldFilterFromSearch(String query, Object item) { @Override public void performSearch(HypixelPlayer player, String query, int page, int maxPage) { if (!new ProxyService(ServiceType.ITEM_TRACKER).isOnline().join()) { - player.sendMessage(I18n.string("gui_museum.empty_display.item_tracker_offline")); + player.sendMessage(I18n.string("gui_museum.empty_display.item_tracker_offline", player.getLocale())); player.closeInventory(); return; } @@ -126,9 +128,10 @@ public void performSearch(HypixelPlayer player, String query, int page, int maxP @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_museum.empty_display.no_items", Map.of("display", display.toString(), "position", String.valueOf(position + 1))), + Locale l = player.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_museum.empty_display.no_items", l, Map.of("display", display.toString(), "position", String.valueOf(position + 1))), Material.BARRIER, 1, - I18n.lore("gui_museum.empty_display.no_items.lore")); + I18n.lore("gui_museum.empty_display.no_items.lore", l)); } }); } @@ -136,7 +139,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public String getTitle(HypixelPlayer player, String query, int page, PaginationList paged) { - return I18n.string("gui_museum.empty_display.title", Map.of("display", display.toString(), "position", String.valueOf(position + 1), "page", String.valueOf(page), "max_page", String.valueOf(paged.getPageCount()))); + return I18n.string("gui_museum.empty_display.title", player.getLocale(), Map.of("display", display.toString(), "position", String.valueOf(position + 1), "page", String.valueOf(page), "max_page", String.valueOf(paged.getPageCount()))); } @Override @@ -160,8 +163,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_museum.empty_display.error"), Material.BARRIER, 1, - I18n.lore("gui_museum.empty_display.error.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_museum.empty_display.error", Material.BARRIER, 1, + "gui_museum.empty_display.error.lore"); } }; } @@ -179,7 +182,7 @@ private GUIClickableItem createIndividualItemDisplay(SkyBlockItem item, int slot public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; player.closeInventory(); - player.sendMessage(I18n.string("gui_museum.empty_display.set_display_single", Map.of("display", display.toString(), "position", String.valueOf(position + 1), "item_name", item.getDisplayName()))); + player.sendMessage(I18n.string("gui_museum.empty_display.set_display_single", player.getLocale(), Map.of("display", display.toString(), "position", String.valueOf(position + 1), "item_name", item.getDisplayName()))); DatapointMuseum.MuseumData data = player.getMuseumData(); data.getDisplayHandler().addToDisplay(item, display, position); player.setMuseumData(data); @@ -193,23 +196,24 @@ public ItemStack.Builder getItem(HypixelPlayer p) { ItemStack.Builder stack = new NonPlayerItemUpdater(item).getUpdatedItem(); ArrayList lore = new ArrayList<>(item.getLore()); + Locale l = player.getLocale(); lore.add("§8§m---------------------"); - lore.add(I18n.string("gui_museum.empty_display.item_created_label")); + lore.add(I18n.string("gui_museum.empty_display.item_created_label", l)); lore.add("§a" + StringUtility.formatAsDate(trackedItem.getCreated())); lore.add("§6 " + StringUtility.commaifyAndTh(trackedItem.getNumberMade()) + " §7created"); lore.add(" "); - lore.add(I18n.string("gui_museum.empty_display.item_clean_value_label")); + lore.add(I18n.string("gui_museum.empty_display.item_clean_value_label", l)); lore.add("§6" + StringUtility.commaify(new ItemPriceCalculator(item).calculateCleanPrice()) + " Coins"); lore.add(" "); - lore.add(I18n.string("gui_museum.empty_display.item_value_label")); + lore.add(I18n.string("gui_museum.empty_display.item_value_label", l)); UUID itemUuid = UUID.fromString(item.getAttributeHandler().getUniqueTrackedID()); if (data.getCalculatedPrices().containsKey(itemUuid)) { lore.add("§6" + StringUtility.commaify(data.getCalculatedPrices().get(itemUuid)) + " Coins"); } else { - lore.add(I18n.string("gui_museum.category.uncalculated")); + lore.add(I18n.string("gui_museum.category.uncalculated", l)); } lore.add(" "); - lore.add(I18n.string("gui_museum.empty_display.click_to_display")); + lore.add(I18n.string("gui_museum.empty_display.click_to_display", l)); return ItemStackCreator.updateLore(stack, lore); } @@ -231,7 +235,7 @@ private GUIClickableItem createArmorSetDisplay(Map.Entry lore = new ArrayList<>(); - lore.add(I18n.string("gui_museum.empty_display.armor_set_lore_prefix")); + Locale l = player.getLocale(); + lore.add(I18n.string("gui_museum.empty_display.armor_set_lore_prefix", l)); for (SkyBlockItem piece : armorPieces) { lore.add("§8• " + piece.getDisplayName()); } @@ -258,10 +263,10 @@ public ItemStack.Builder getItem(HypixelPlayer p) { .mapToInt(piece -> new ItemPriceCalculator(piece).calculateCleanPrice().intValue()) .sum(); - lore.add(I18n.string("gui_museum.empty_display.set_clean_value_label")); + lore.add(I18n.string("gui_museum.empty_display.set_clean_value_label", l)); lore.add("§6" + StringUtility.commaify(totalCleanValue) + " Coins"); lore.add(" "); - lore.add(I18n.string("gui_museum.empty_display.click_to_display_armor")); + lore.add(I18n.string("gui_museum.empty_display.click_to_display_armor", l)); return ItemStackCreator.getStack("§a" + armorSet.getDisplayName() + " Set", displayItem.getMaterial(), 1, lore); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumNonEmptyDisplay.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumNonEmptyDisplay.java index 4473adada..030298765 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumNonEmptyDisplay.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIMuseumNonEmptyDisplay.java @@ -12,6 +12,7 @@ import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -26,6 +27,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -67,7 +69,7 @@ public void onOpen(InventoryGUIOpenEvent e) { items = data.getDisplayHandler().getItemsAtSlot(display, position); if (items.isEmpty()) { - player.sendMessage(I18n.string("gui_museum.display.no_items")); + player.sendMessage(I18n.string("gui_museum.display.no_items", player.getLocale())); player.closeInventory(); return; } @@ -76,11 +78,11 @@ public void onOpen(InventoryGUIOpenEvent e) { if (items.size() == 1) { setTitle(items.getFirst().getAttributeHandler().getPotentialType().getDisplayName()); } else { - setTitle(I18n.string("gui_museum.display.title_with_count", Map.of("count", String.valueOf(items.size())))); + setTitle(I18n.string("gui_museum.display.title_with_count", player.getLocale(), Map.of("count", String.valueOf(items.size())))); } if (!new ProxyService(ServiceType.ITEM_TRACKER).isOnline().join()) { - player.sendMessage(I18n.string("gui_museum.display.item_tracker_offline")); + player.sendMessage(I18n.string("gui_museum.display.item_tracker_offline", player.getLocale())); player.closeInventory(); return; } @@ -98,11 +100,12 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_museum.display.remove_button"), + Locale l = player.getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_museum.display.remove_button", l), Material.BEDROCK, 1, items.size() == 1 - ? I18n.lore("gui_museum.display.remove_single.lore") - : I18n.lore("gui_museum.display.remove_multiple.lore", Map.of("count", String.valueOf(items.size())))); + ? I18n.lore("gui_museum.display.remove_single.lore", l) + : I18n.lore("gui_museum.display.remove_multiple.lore", l, Map.of("count", String.valueOf(items.size())))); } }); @@ -148,26 +151,27 @@ private ItemStack.Builder createItemDisplay(SkyBlockItem item, SkyBlockPlayer pl ArrayList lore = new ArrayList<>(item.getLore()); UUID trackedItemUUID = UUID.fromString(item.getAttributeHandler().getUniqueTrackedID()); + Locale l = player.getLocale(); lore.add("§8§m---------------------"); - lore.add(I18n.string("gui_museum.display.item_donated_label")); + lore.add(I18n.string("gui_museum.display.item_donated_label", l)); lore.add("§b" + StringUtility.formatAsDate(data.getInsertionTimes().get(trackedItemUUID))); lore.add(" "); if (trackedItem != null) { - lore.add(I18n.string("gui_museum.display.item_created_label")); + lore.add(I18n.string("gui_museum.display.item_created_label", l)); lore.add("§a" + StringUtility.formatAsDate(trackedItem.getCreated())); lore.add("§6 " + StringUtility.commaifyAndTh(trackedItem.getNumberMade()) + " §7created"); lore.add(" "); } - lore.add(I18n.string("gui_museum.display.item_clean_value_label")); + lore.add(I18n.string("gui_museum.display.item_clean_value_label", l)); lore.add("§6" + StringUtility.commaify(new ItemPriceCalculator(item).calculateCleanPrice()) + " Coins"); lore.add(" "); - lore.add(I18n.string("gui_museum.display.item_value_label")); + lore.add(I18n.string("gui_museum.display.item_value_label", l)); if (data.getCalculatedPrices().containsKey(trackedItemUUID)) { lore.add("§6" + StringUtility.commaify(data.getCalculatedPrices().get(trackedItemUUID)) + " Coins"); } else { - lore.add(I18n.string("gui_museum.category.uncalculated")); + lore.add(I18n.string("gui_museum.category.uncalculated", l)); } return ItemStackCreator.updateLore(stack, lore); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIYourMuseum.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIYourMuseum.java index 57e22f2a0..2d7c8ba6b 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIYourMuseum.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/museum/GUIYourMuseum.java @@ -10,6 +10,7 @@ import net.swofty.proxyapi.ProxyService; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -21,6 +22,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @@ -40,7 +42,7 @@ public GUIYourMuseum() { @Override public void onOpen(InventoryGUIOpenEvent e) { if (!new ProxyService(ServiceType.ITEM_TRACKER).isOnline().join()) { - e.player().sendMessage(I18n.string("gui_museum.main.item_tracker_offline")); + e.player().sendMessage(I18n.string("gui_museum.main.item_tracker_offline", e.player().getLocale())); e.player().closeInventory(); return; } @@ -60,23 +62,24 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_museum.main.rewards_button"), Material.GOLD_BLOCK, 1, - I18n.lore("gui_museum.main.rewards_button.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_museum.main.rewards_button", Material.GOLD_BLOCK, 1, + "gui_museum.main.rewards_button.lore"); } }); set(new GUIItem(45) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - return ItemStackCreator.getStack(I18n.string("gui_museum.main.edit_npc_tags"), Material.NAME_TAG, 1, - I18n.lore("gui_museum.main.edit_npc_tags.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_museum.main.edit_npc_tags", Material.NAME_TAG, 1, + "gui_museum.main.edit_npc_tags.lore"); } }); set(new GUIItem(4) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - List lore = new ArrayList<>(I18n.lore("gui_museum.main.museum_info.lore")); + Locale l = p.getLocale(); + List lore = new ArrayList<>(I18n.lore("gui_museum.main.museum_info.lore", l)); int maxAmountOfItems = MuseumableItemCategory.getMuseumableItemCategorySize(); int unlockedItems = data.getAllItems().size(); @@ -84,13 +87,13 @@ public ItemStack.Builder getItem(HypixelPlayer p) { double percentageUnlocked = (double) unlockedItems / (double) maxAmountOfItems * 100; double percentageUnlockedToTwoDecimalPlaces = Math.round(percentageUnlocked * 100) / 100.0; - lore.add(I18n.string("gui_museum.main.items_donated", Map.of("percentage", String.valueOf(percentageUnlockedToTwoDecimalPlaces)))); + lore.add(I18n.string("gui_museum.main.items_donated", l, Map.of("percentage", String.valueOf(percentageUnlockedToTwoDecimalPlaces)))); lore.add(getAsDisplay(unlockedItems, maxAmountOfItems)); Map calculatedPrices = data.getCalculatedPrices(); if (!calculatedPrices.isEmpty()) { lore.add(" "); - lore.add(I18n.string("gui_museum.main.top_items")); + lore.add(I18n.string("gui_museum.main.top_items", l)); AtomicInteger index = new AtomicInteger(1); calculatedPrices.entrySet().stream() @@ -105,7 +108,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { }); } - return ItemStackCreator.getStackHead(I18n.string("gui_museum.main.museum_info"), + return ItemStackCreator.getStackHead(I18n.string("gui_museum.main.museum_info", l), "597e4e27a04afa5f06108265a9bfb797630391c7f3d880d244f610bb1ff393d8", 1, lore); } @@ -129,7 +132,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; - List lore = new ArrayList<>(I18n.lore("gui_museum.main.category_button.lore_prefix", + Locale l = p.getLocale(); + List lore = new ArrayList<>(I18n.lore("gui_museum.main.category_button.lore_prefix", l, Map.of("color", category.getColor(), "category", category.getCategory()))); int maxAmountOfItems = MuseumableItemCategory.getMuseumableItemCategorySize(category); @@ -137,10 +141,10 @@ public ItemStack.Builder getItem(HypixelPlayer p) { double percentage = (double) unlockedItems / (double) maxAmountOfItems * 100; double percentageToTwoDecimalPlaces = Math.round(percentage * 100) / 100.0; - lore.add(I18n.string("gui_museum.main.category_items_donated", Map.of("percentage", String.valueOf(percentageToTwoDecimalPlaces)))); + lore.add(I18n.string("gui_museum.main.category_items_donated", l, Map.of("percentage", String.valueOf(percentageToTwoDecimalPlaces)))); lore.add(getAsDisplay(unlockedItems, maxAmountOfItems)); lore.add(" "); - lore.add(I18n.string("gui_museum.main.category_click")); + lore.add(I18n.string("gui_museum.main.category_click", l)); return ItemStackCreator.getStack("§a" + category.getCategory(), category.getMaterial(), 1, diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/rusty/GUIRusty.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/rusty/GUIRusty.java index e664d378b..801a43d0a 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/rusty/GUIRusty.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/rusty/GUIRusty.java @@ -6,6 +6,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -29,10 +30,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack( - I18n.string("gui_rusty.main.weapons_button"), Material.IRON_SWORD, 1, - I18n.lore("gui_rusty.main.weapons_button.lore") - ); + return TranslatableItemStackCreator.getStack(player, "gui_rusty.main.weapons_button", Material.IRON_SWORD, 1, + "gui_rusty.main.weapons_button.lore"); } }); @@ -44,10 +43,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStackHead( - I18n.string("gui_rusty.main.pets_button"), "4e794274c1bb197ad306540286a7aa952974f5661bccf2b725424f6ed79c7884", 1, - I18n.lore("gui_rusty.main.pets_button.lore") - ); + return TranslatableItemStackCreator.getStackHead(player, "gui_rusty.main.pets_button", "4e794274c1bb197ad306540286a7aa952974f5661bccf2b725424f6ed79c7884", 1, + "gui_rusty.main.pets_button.lore"); } }); @@ -59,10 +56,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStackHead( - I18n.string("gui_rusty.main.accessories_button"), "3ada666715bfd2aa9fbd81daef59b9fe1c96c4fa0d08dbc72eae5633177dbf88", 1, - I18n.lore("gui_rusty.main.accessories_button.lore") - ); + return TranslatableItemStackCreator.getStackHead(player, "gui_rusty.main.accessories_button", "3ada666715bfd2aa9fbd81daef59b9fe1c96c4fa0d08dbc72eae5633177dbf88", 1, + "gui_rusty.main.accessories_button.lore"); } }); @@ -74,20 +69,16 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack( - I18n.string("gui_rusty.main.miscellaneous_button"), Material.FILLED_MAP, 1, - I18n.lore("gui_rusty.main.miscellaneous_button.lore") - ); + return TranslatableItemStackCreator.getStack(player, "gui_rusty.main.miscellaneous_button", Material.FILLED_MAP, 1, + "gui_rusty.main.miscellaneous_button.lore"); } }); set(new GUIItem(32) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack( - I18n.string("gui_rusty.main.janitor_info"), Material.REDSTONE_TORCH, 1, - I18n.lore("gui_rusty.main.janitor_info.lore") - ); + return TranslatableItemStackCreator.getStack(player, "gui_rusty.main.janitor_info", Material.REDSTONE_TORCH, 1, + "gui_rusty.main.janitor_info.lore"); } }); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/rusty/GUIRustySubMenu.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/rusty/GUIRustySubMenu.java index de241e0f3..98ad14a2c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/rusty/GUIRustySubMenu.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/rusty/GUIRustySubMenu.java @@ -9,6 +9,7 @@ import net.swofty.type.generic.data.datapoints.DatapointToggles; import net.swofty.type.generic.gui.inventory.HypixelPaginatedGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.i18n.I18n; @@ -21,6 +22,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.function.Function; import java.util.function.Supplier; @@ -113,18 +115,19 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { + Locale l = player.getLocale(); String toggleAction = player.getToggles().get(DatapointToggles.Toggles.ToggleType.RUSTY_PURCHASE_CONFIRMATION) ? "disable" : "enable"; - return ItemStackCreator.getStack(I18n.string("gui_rusty.submenu.shop_confirmations"), + return ItemStackCreator.getStack(I18n.string("gui_rusty.submenu.shop_confirmations", l), player.getToggles().get(DatapointToggles.Toggles.ToggleType.RUSTY_PURCHASE_CONFIRMATION) ? Material.LIME_DYE : Material.LIGHT_GRAY_DYE, 1, - I18n.lore("gui_rusty.submenu.shop_confirmations.lore", Map.of("toggle_action", toggleAction))); + I18n.lore("gui_rusty.submenu.shop_confirmations.lore", l, Map.of("toggle_action", toggleAction))); } }); set(new GUIItem(50) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack(I18n.string("gui_rusty.submenu.janitor_info"), Material.REDSTONE_TORCH, 1, - I18n.lore("gui_rusty.submenu.janitor_info.lore")); + return TranslatableItemStackCreator.getStack(player, "gui_rusty.submenu.janitor_info", Material.REDSTONE_TORCH, 1, + "gui_rusty.submenu.janitor_info.lore"); } }); @@ -140,9 +143,10 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { @Override public ItemStack.Builder getItem(HypixelPlayer player) { + Locale l = player.getLocale(); String status = player.getToggles().get(DatapointToggles.Toggles.ToggleType.RUSTY_SORT_BY_RARITY) ? "§aYES" : "§cNO"; - return ItemStackCreator.getStack(I18n.string("gui_rusty.submenu.sort_by_rarity"), Material.ENDER_EYE, 1, - I18n.lore("gui_rusty.submenu.sort_by_rarity.lore", Map.of("status", status))); + return ItemStackCreator.getStack(I18n.string("gui_rusty.submenu.sort_by_rarity", l), Material.ENDER_EYE, 1, + I18n.lore("gui_rusty.submenu.sort_by_rarity.lore", l, Map.of("status", status))); } }); @@ -163,8 +167,9 @@ public GUIClickableItem createItemFor(DisplayEntry display, int slot, Hypixel return new GUIClickableItem(slot) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer player) {} @Override public ItemStack.Builder getItem(HypixelPlayer player) { + Locale l = player.getLocale(); return ItemStackCreator.getStackHead( - I18n.string("gui_rusty.submenu.unknown_item"), + I18n.string("gui_rusty.submenu.unknown_item", l), "5359d91277242fc01c309accb87b533f1929be176ecba2cde63bf635e05e699b" ); } @@ -185,15 +190,16 @@ public void run(InventoryPreClickEvent e, HypixelPlayer player) { return; } + Locale l = skyblockPlayer.getLocale(); if (skyblockPlayer.getCoins() >= price) { skyblockPlayer.addAndUpdateItem(item); skyblockPlayer.removeCoins(price); - skyblockPlayer.sendMessage(I18n.string("gui_rusty.submenu.bought_message", Map.of( + skyblockPlayer.sendMessage(I18n.string("gui_rusty.submenu.bought_message", l, Map.of( "item_name", item.getDisplayName(), "price", String.valueOf(price) ))); } else { - skyblockPlayer.sendMessage(I18n.string("gui_rusty.submenu.not_enough_coins")); + skyblockPlayer.sendMessage(I18n.string("gui_rusty.submenu.not_enough_coins", l)); } } @@ -210,11 +216,12 @@ public ItemStack.Builder getItem(HypixelPlayer player) { .toList() ); + Locale l = player.getLocale(); lore.add(""); - lore.add(I18n.string("gui_rusty.submenu.cost_label")); + lore.add(I18n.string("gui_rusty.submenu.cost_label", l)); lore.add("§6" + StringUtility.commaify(entry.price()) + " Coins"); lore.add(""); - lore.add(I18n.string("gui_rusty.submenu.click_to_trade")); + lore.add(I18n.string("gui_rusty.submenu.click_to_trade", l)); return ItemStackCreator.updateLore(stack, lore); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUICrafting.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUICrafting.java index 3c20b442d..1947f91b3 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUICrafting.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUICrafting.java @@ -11,6 +11,7 @@ import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.generic.event.HypixelEventHandler; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ClickContext; import net.swofty.type.generic.gui.v2.context.ViewContext; @@ -24,18 +25,17 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Locale; import java.util.Objects; import java.util.stream.Collectors; public class GUICrafting implements StatefulView { - private static final ItemStack.Builder RECIPE_REQUIRED = ItemStackCreator.getStack(I18n.string("gui_sbmenu.crafting.recipe_required"), Material.BARRIER, 1, - I18n.lore("gui_sbmenu.crafting.recipe_required.lore")); private static final int[] CRAFT_SLOTS = new int[]{10, 11, 12, 19, 20, 21, 28, 29, 30}; private static final int RESULT_SLOT = 23; @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.crafting.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.crafting.title", InventoryType.CHEST_6_ROW); } @Override @@ -75,7 +75,7 @@ public void layout(ViewLayout layout, CraftingState state, ViewCo ); if (!hasValidRecipe) { - layout.slot(RESULT_SLOT, (s, c) -> RECIPE_REQUIRED); + layout.slot(RESULT_SLOT, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.crafting.recipe_required", Material.BARRIER, 1, "gui_sbmenu.crafting.recipe_required.lore")); } else if (!canCraft) { layout.slot(RESULT_SLOT, (s, c) -> ItemStackCreator.getStack(result.errorMessage()[0], Material.BEDROCK, 1, @@ -91,7 +91,8 @@ public void layout(ViewLayout layout, CraftingState state, ViewCo if (existingLore != null) { existingLore.stream().map(line -> "§7" + StringUtility.getTextFromComponent(line)).forEach(lore::add); } - lore.addAll(I18n.lore("gui_sbmenu.crafting.crafting_item.lore")); + Locale l = c.player().getLocale(); + lore.addAll(I18n.lore("gui_sbmenu.crafting.crafting_item.lore", l)); builder.set(DataComponents.LORE, lore.stream().map(line -> Component.text(line).decoration(TextDecoration.ITALIC, false)) .collect(Collectors.toList())); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUIPets.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUIPets.java index b815c0abd..1fdc08d37 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUIPets.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUIPets.java @@ -9,6 +9,7 @@ import net.swofty.commons.skyblock.item.Rarity; import net.swofty.commons.skyblock.item.attribute.attributes.ItemAttributePetData; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ClickContext; import net.swofty.type.generic.gui.v2.context.ViewContext; @@ -22,6 +23,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIPets extends PaginatedView { @@ -35,7 +37,7 @@ public class GUIPets extends PaginatedView { @Override public ViewConfiguration configuration() { return ViewConfiguration.withString( - (state, ctx) -> I18n.string("gui_sbmenu.pets.title", Map.of( + (state, ctx) -> I18n.string("gui_sbmenu.pets.title", ctx.player().getLocale(), Map.of( "page", String.valueOf(state.page() + 1), "max_page", String.valueOf(Math.max(1, (int) Math.ceil((double) getFilteredItems(state).size() / PAGINATED_SLOTS.length))) )), @@ -99,13 +101,14 @@ protected ItemStack.Builder renderItem(SkyBlockItem item, int index, HypixelPlay ItemStack.Builder itemStack = new NonPlayerItemUpdater(item).getUpdatedItem(); List lore = new ArrayList<>(itemStack.build().get(DataComponents.LORE).stream().map(StringUtility::getTextFromComponent).toList()); + Locale l = player.getLocale(); lore.add(" "); if (isPetEnabled) { ItemStackCreator.enchant(itemStack); - lore.add(I18n.string("gui_sbmenu.pets.currently_active")); - lore.add(I18n.string("gui_sbmenu.pets.click_to_deselect")); + lore.add(I18n.string("gui_sbmenu.pets.currently_active", l)); + lore.add(I18n.string("gui_sbmenu.pets.click_to_deselect", l)); } else { - lore.add(I18n.string("gui_sbmenu.pets.click_to_summon")); + lore.add(I18n.string("gui_sbmenu.pets.click_to_summon", l)); } return ItemStackCreator.updateLore(itemStack, lore); } @@ -113,6 +116,7 @@ protected ItemStack.Builder renderItem(SkyBlockItem item, int index, HypixelPlay @Override protected void onItemClick(ClickContext click, ViewContext ctx, SkyBlockItem item, int index) { SkyBlockPlayer player = (SkyBlockPlayer) ctx.player(); + Locale l = player.getLocale(); PetsState state = click.state(); boolean selected = player.getPetData().getEnabledPet() == item; @@ -120,7 +124,7 @@ protected void onItemClick(ClickContext click, ViewContext ctx, SkyBl player.getPetData().deselectCurrent(); player.getPetData().updatePetEntityImpl(player); ctx.session(PetsState.class).update(s -> (PetsState) s.withItems(getPetsFromPlayer(player))); - player.sendMessage(I18n.string("gui_sbmenu.pets.msg.deselected", Map.of("pet_name", item.getDisplayName()))); + player.sendMessage(I18n.string("gui_sbmenu.pets.msg.deselected", l, Map.of("pet_name", item.getDisplayName()))); return; } @@ -128,13 +132,13 @@ protected void onItemClick(ClickContext click, ViewContext ctx, SkyBl player.addAndUpdateItem(item); player.getPetData().removePet(item.getAttributeHandler().getPotentialType()); ctx.session(PetsState.class).update(s -> (PetsState) s.withItems(getPetsFromPlayer(player))); - player.sendMessage(I18n.string("gui_sbmenu.pets.msg.picked_up")); + player.sendMessage(I18n.string("gui_sbmenu.pets.msg.picked_up", l)); return; } player.getPetData().setEnabled(item.getAttributeHandler().getPotentialType(), true); player.getPetData().updatePetEntityImpl(player); - player.sendMessage(I18n.string("gui_sbmenu.pets.msg.selected", Map.of("pet_name", item.getDisplayName()))); + player.sendMessage(I18n.string("gui_sbmenu.pets.msg.selected", l, Map.of("pet_name", item.getDisplayName()))); ctx.session(PetsState.class).update(s -> (PetsState) s.withItems(getPetsFromPlayer(player))); } @@ -151,25 +155,27 @@ protected void layoutCustom(ViewLayout layout, PetsState state, ViewC layout.slot(4, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); String selectedPet = player.getPetData().getEnabledPet() == null ? "§cNone" : player.getPetData().getEnabledPet().getDisplayName(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.pets.info"), Material.BONE, 1, - I18n.lore("gui_sbmenu.pets.info.lore", Map.of("selected_pet", selectedPet))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.pets.info", Material.BONE, 1, + "gui_sbmenu.pets.info.lore", Map.of("selected_pet", selectedPet)); }); layout.slot(47, (s, c) -> { String status = s.convertToItem() ? "§aEnabled" : "§cDisabled"; - ItemStack.Builder itemStack = ItemStackCreator.getStack(I18n.string("gui_sbmenu.pets.convert_to_item"), Material.DIAMOND, 1, - I18n.lore("gui_sbmenu.pets.convert_to_item.lore", Map.of("status", status))); + ItemStack.Builder itemStack = TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.pets.convert_to_item", Material.DIAMOND, 1, + "gui_sbmenu.pets.convert_to_item.lore", Map.of("status", status)); if (s.convertToItem()) ItemStackCreator.enchant(itemStack); return itemStack; }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); String status = !click.state().convertToItem() ? "§aENABLED" : "§cDISABLED"; - player.sendMessage(I18n.string("gui_sbmenu.pets.msg.conversion_toggle", Map.of("status", status))); + player.sendMessage(I18n.string("gui_sbmenu.pets.msg.conversion_toggle", l, Map.of("status", status))); c.session(PetsState.class).update(s -> s.withConvertToItem(!s.convertToItem())); }); layout.slot(51, (s, c) -> { + Locale l = c.player().getLocale(); List lore = new ArrayList<>(); lore.add(" "); @@ -180,10 +186,10 @@ protected void layoutCustom(ViewLayout layout, PetsState state, ViewC } lore.add(" "); - lore.add(I18n.string("gui_sbmenu.pets.sort.right_click")); - lore.add(I18n.string("gui_sbmenu.pets.sort.click")); + lore.add(I18n.string("gui_sbmenu.pets.sort.right_click", l)); + lore.add(I18n.string("gui_sbmenu.pets.sort.click", l)); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.pets.sort"), Material.HOPPER, 1, lore); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.pets.sort", Material.HOPPER, 1, lore); }, (click, c) -> { boolean isRightClick = click.click() instanceof Click.Right; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockMenu.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockMenu.java index 997bb121b..8e04d6588 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockMenu.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockMenu.java @@ -7,6 +7,7 @@ import net.swofty.commons.StringUtility; import net.swofty.type.generic.data.datapoints.DatapointToggles; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.Components; import net.swofty.type.generic.gui.v2.DefaultState; import net.swofty.type.generic.gui.v2.StatelessView; @@ -37,13 +38,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUISkyBlockMenu extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.main.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.main.title", InventoryType.CHEST_6_ROW); } @Override @@ -53,6 +55,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(13, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); PlayerStatistics statistics = player.getStatistics(); StringBuilder statsDisplay = new StringBuilder(); List statNames = new ArrayList<>(List.of("Health", "Defense", "Speed", "Strength", "Intelligence", @@ -66,10 +69,10 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } }); - List lore = new ArrayList<>(I18n.lore("gui_sbmenu.main.your_profile.lore", + List lore = new ArrayList<>(I18n.lore("gui_sbmenu.main.your_profile.lore", l, Map.of("stats_display", statsDisplay.toString()))); - return ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.main.your_profile"), + return TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.main.your_profile", player.getPlayerSkin(), 1, lore ); @@ -83,19 +86,19 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont SkyBlockLevelRequirement levelRequirement = player.getSkyBlockExperience().getLevel(); SkyBlockLevelRequirement nextLevel = levelRequirement.getNextLevel(); - return ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.main.skyblock_leveling"), + return TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.main.skyblock_leveling", "3255327dd8e90afad681a19231665bea2bd06065a09d77ac1408837f9e0b242", 1, - I18n.lore("gui_sbmenu.main.skyblock_leveling.lore", Map.of( + "gui_sbmenu.main.skyblock_leveling.lore", Map.of( "level_display", levelRequirement.getColor() + String.valueOf(levelRequirement), "next_level", nextLevel == null ? "§cMAX" : String.valueOf(nextLevel), "next_level_display", player.getSkyBlockExperience().getNextLevelDisplay() - )) + ) ); }, (click, c) -> c.push(new GUISkyBlockLevels())); - layout.slot(29, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.main.your_bags"), + layout.slot(29, (s, c) -> TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.main.your_bags", "961a918c0c49ba8d053e522cb91abc74689367b4d8aa06bfc1ba9154730985ff", 1, - I18n.lore("gui_sbmenu.main.your_bags.lore") + "gui_sbmenu.main.your_bags.lore" ), (click, c) -> { c.push(new GUIYourBags()); }); @@ -103,8 +106,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(30, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); String selectedPet = player.getPetData().getEnabledPet() == null ? "§cNone" : player.getPetData().getEnabledPet().getDisplayName(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.pets"), Material.BONE, 1, - I18n.lore("gui_sbmenu.main.pets.lore", Map.of("selected_pet", selectedPet)) + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.pets", Material.BONE, 1, + "gui_sbmenu.main.pets.lore", Map.of("selected_pet", selectedPet) ); }, (click, c) -> c.push(new GUIPets(), GUIPets.createInitialState((SkyBlockPlayer) c.player()))); @@ -118,25 +121,25 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont missionDisplayStr.append(line); } - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.recipe_book"), Material.BOOK, 1, - I18n.lore("gui_sbmenu.main.recipe_book.lore", Map.of("mission_display", missionDisplayStr.toString()))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.recipe_book", Material.BOOK, 1, + "gui_sbmenu.main.recipe_book.lore", Map.of("mission_display", missionDisplayStr.toString())); }, (click, c) -> { c.push(new GUIRecipeBook()); }); - layout.slot(25, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.storage"), Material.CHEST, 1, - I18n.lore("gui_sbmenu.main.storage.lore") + layout.slot(25, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.storage", Material.CHEST, 1, + "gui_sbmenu.main.storage.lore" ), (click, c) -> c.push(new GUIStorage())); - layout.slot(23, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.quests"), Material.WRITABLE_BOOK, 1, - I18n.lore("gui_sbmenu.main.quests.lore") + layout.slot(23, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.quests", Material.WRITABLE_BOOK, 1, + "gui_sbmenu.main.quests.lore" ), (click, c) -> c.push(new GUIMissionLog())); - layout.autoUpdating(24, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.calendar"), Material.CLOCK, 1, getCalendarLore(ctx)), + layout.autoUpdating(24, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.calendar", Material.CLOCK, 1, getCalendarLore(ctx)), (click, c) -> c.push(new GUICalendar()), Duration.ofSeconds(1)); - layout.slot(19, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.skills"), Material.DIAMOND_SWORD, 1, - I18n.lore("gui_sbmenu.main.skills.lore") + layout.slot(19, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.skills", Material.DIAMOND_SWORD, 1, + "gui_sbmenu.main.skills.lore" ), (click, c) -> c.push(new GUISkills())); layout.slot(20, (s, c) -> { @@ -149,20 +152,20 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont collectionDisplayStr.append(line); } - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.collections"), Material.PAINTING, 1, - I18n.lore("gui_sbmenu.main.collections.lore", Map.of("collection_display", collectionDisplayStr.toString()))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.collections", Material.PAINTING, 1, + "gui_sbmenu.main.collections.lore", Map.of("collection_display", collectionDisplayStr.toString())); }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); player.openView(new GUICollections()); }); - layout.slot(31, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.crafting_table"), Material.CRAFTING_TABLE, 1, - I18n.lore("gui_sbmenu.main.crafting_table.lore") + layout.slot(31, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.crafting_table", Material.CRAFTING_TABLE, 1, + "gui_sbmenu.main.crafting_table.lore" ), (click, c) -> c.push(new GUICrafting())); - layout.slot(47, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.main.fast_travel"), + layout.slot(47, (s, c) -> TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.main.fast_travel", "f151cffdaf303673531a7651b36637cad912ba485643158e548d59b2ead5011", 1, - I18n.lore("gui_sbmenu.main.fast_travel.lore") + "gui_sbmenu.main.fast_travel.lore" ), (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); if (click.click() instanceof Click.Right) { @@ -175,34 +178,35 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(48, (s, c) -> { HypixelPlayer player = c.player(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.main.profile_management"), Material.NAME_TAG, 1, - I18n.lore("gui_sbmenu.main.profile_management.lore", Map.of( + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.main.profile_management", Material.NAME_TAG, 1, + "gui_sbmenu.main.profile_management.lore", Map.of( "profile_count", String.valueOf(((SkyBlockPlayer) player).getProfiles().getProfiles().size()) - )) + ) ); }, (click, c) -> c.push(new GUIProfileManagement())); } private static @NonNull List getCalendarLore(ViewContext ctx) { + Locale l = ctx.player().getLocale(); List currentEvents = SkyBlockCalendar.getCurrentEvents(); boolean multipleEvents = currentEvents.size() > 1; String date = StringUtility.ntify(SkyBlockCalendar.getDay()) + " " + SkyBlockCalendar.getMonthName() + " " + SkyBlockCalendar.getYear(); - List lore = new ArrayList<>(I18n.lore("gui_sbmenu.main.calendar.lore_header", Map.of("date", date))); + List lore = new ArrayList<>(I18n.lore("gui_sbmenu.main.calendar.lore_header", l, Map.of("date", date))); lore.add(""); if (multipleEvents) { - lore.add(I18n.string("gui_sbmenu.main.calendar.current_events")); + lore.add(I18n.string("gui_sbmenu.main.calendar.current_events", l)); for (CalendarEvent event : currentEvents) { lore.add(event.getDisplayName(SkyBlockCalendar.getYear())); } } else if (currentEvents.size() == 1) { CalendarEvent currentEvent = currentEvents.getFirst(); - lore.add(I18n.string("gui_sbmenu.main.calendar.current_event", Map.of("event_name", currentEvent.getDisplayName(SkyBlockCalendar.getYear())))); + lore.add(I18n.string("gui_sbmenu.main.calendar.current_event", l, Map.of("event_name", currentEvent.getDisplayName(SkyBlockCalendar.getYear())))); long ticksRemaining = getTicksRemaining(currentEvent); - lore.add(I18n.string("gui_sbmenu.main.calendar.event_ends_in", Map.of("time_left", StringUtility.formatTimeLeft(ticksRemaining * 50L)))); + lore.add(I18n.string("gui_sbmenu.main.calendar.event_ends_in", l, Map.of("time_left", StringUtility.formatTimeLeft(ticksRemaining * 50L)))); } else { - lore.add(I18n.string("gui_sbmenu.main.calendar.no_current_events")); + lore.add(I18n.string("gui_sbmenu.main.calendar.no_current_events", l)); } lore.add(" "); @@ -219,13 +223,13 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont SkyBlockCalendar.EventInfo info = entry.getKey(); CalendarEvent event = entry.getValue(); - lore.add(I18n.string("gui_sbmenu.main.calendar.next_event", Map.of("event_name", event.getDisplayName(info.year())))); - lore.add(I18n.string("gui_sbmenu.main.calendar.next_event_starting", Map.of("time_left", StringUtility.formatTimeLeft(info.timeUntilBegin() * 50L)))); + lore.add(I18n.string("gui_sbmenu.main.calendar.next_event", l, Map.of("event_name", event.getDisplayName(info.year())))); + lore.add(I18n.string("gui_sbmenu.main.calendar.next_event_starting", l, Map.of("time_left", StringUtility.formatTimeLeft(info.timeUntilBegin() * 50L)))); } else { - lore.add(I18n.string("gui_sbmenu.main.calendar.no_upcoming_events")); + lore.add(I18n.string("gui_sbmenu.main.calendar.no_upcoming_events", l)); } - lore.addAll(I18n.lore("gui_sbmenu.main.calendar.lore_footer")); + lore.addAll(I18n.lore("gui_sbmenu.main.calendar.lore_footer", l)); return lore; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockProfile.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockProfile.java index 4bb338036..f16e189da 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockProfile.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/GUISkyBlockProfile.java @@ -6,6 +6,7 @@ import net.swofty.commons.StringUtility; import net.swofty.commons.skyblock.statistics.ItemStatistic; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -27,7 +28,7 @@ public class GUISkyBlockProfile extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.profile.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.profile.title", InventoryType.CHEST_6_ROW); } @Override @@ -42,7 +43,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (!player.getItemInMainHand().isAir()) { return ItemStackCreator.getFromStack(player.getItemInMainHand()); } else { - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.empty_held_item"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.empty_held_item", Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } }); @@ -52,7 +53,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (!player.getHelmet().isAir()) { return ItemStackCreator.getFromStack(player.getHelmet()); } else { - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.empty_helmet"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.empty_helmet", Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); @@ -76,7 +77,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (!player.getChestplate().isAir()) { return ItemStackCreator.getFromStack(player.getChestplate()); } else { - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.empty_chestplate"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.empty_chestplate", Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); @@ -100,7 +101,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (!player.getLeggings().isAir()) { return ItemStackCreator.getFromStack(player.getLeggings()); } else { - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.empty_leggings"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.empty_leggings", Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); @@ -124,7 +125,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (!player.getBoots().isAir()) { return ItemStackCreator.getFromStack(player.getBoots()); } else { - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.empty_boots"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.empty_boots", Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); @@ -149,7 +150,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont SkyBlockItem pet = player.getPetData().getEnabledPet(); return new NonPlayerItemUpdater(pet).getUpdatedItem(); } else { - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.empty_pet"), Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.empty_pet", Material.LIGHT_GRAY_STAINED_GLASS_PANE, 1); } }, (click, c) -> { //c.player().openView(new GUIPets()) @@ -172,8 +173,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } }); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.combat_stats"), Material.DIAMOND_SWORD, 1, - I18n.lore("gui_sbmenu.profile.combat_stats.lore", Map.of("stats_display", statsDisplay.toString()))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.combat_stats", Material.DIAMOND_SWORD, 1, + "gui_sbmenu.profile.combat_stats.lore", Map.of("stats_display", statsDisplay.toString())); }, (click, c) -> { //c.player().openView(new GUICombatStats())) }); @@ -198,8 +199,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } }); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.gathering_stats"), Material.IRON_PICKAXE, 1, - I18n.lore("gui_sbmenu.profile.gathering_stats.lore", Map.of("stats_display", statsDisplay.toString()))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.gathering_stats", Material.IRON_PICKAXE, 1, + "gui_sbmenu.profile.gathering_stats.lore", Map.of("stats_display", statsDisplay.toString())); }, (click, c) -> { // c.player().openView(new GUIGatheringStats()); }); @@ -221,8 +222,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } }); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.wisdom_stats"), Material.BOOK, 1, - I18n.lore("gui_sbmenu.profile.wisdom_stats.lore", Map.of("stats_display", statsDisplay.toString()))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.wisdom_stats", Material.BOOK, 1, + "gui_sbmenu.profile.wisdom_stats.lore", Map.of("stats_display", statsDisplay.toString())); }, (click, c) -> { //c.player().openView(new GUIWisdomStats()) }); @@ -244,8 +245,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } }); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profile.misc_stats"), Material.CLOCK, 1, - I18n.lore("gui_sbmenu.profile.misc_stats.lore", Map.of("stats_display", statsDisplay.toString()))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profile.misc_stats", Material.CLOCK, 1, + "gui_sbmenu.profile.misc_stats.lore", Map.of("stats_display", statsDisplay.toString())); }, (click, c) -> { //c.player().openView(new GUIMiscStats()) }); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIAccessoryBag.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIAccessoryBag.java index caefec5c1..128d7b1c4 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIAccessoryBag.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIAccessoryBag.java @@ -4,6 +4,7 @@ import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.skyblockgeneric.collection.CustomCollectionAward; @@ -41,7 +42,7 @@ public ViewConfiguration configuration() { SkyBlockPlayer player = (SkyBlockPlayer) ctx.player(); int totalSlots = getTotalSlots(player); int totalPages = Math.max(1, (int) Math.ceil((double) totalSlots / 45)); - return I18n.string("gui_sbmenu.bags.accessory.title", Map.of( + return I18n.string("gui_sbmenu.bags.accessory.title", ctx.player().getLocale(), Map.of( "page", String.valueOf(state.page() + 1), "max_page", String.valueOf(totalPages) )); @@ -91,20 +92,20 @@ public void layout(ViewLayout layout, AccessoryBagState state int slotIndex = i + startIndex; CustomCollectionAward nextUpgrade = getUpgradeNeededForSlotIndex(slotIndex); if (nextUpgrade != null) { - layout.slot(i, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.accessory.locked"), Material.RED_STAINED_GLASS_PANE, 1, - I18n.lore("gui_sbmenu.bags.accessory.locked.lore", Map.of("upgrade_name", nextUpgrade.getDisplay())))); + layout.slot(i, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.accessory.locked", Material.RED_STAINED_GLASS_PANE, 1, + "gui_sbmenu.bags.accessory.locked.lore", Map.of("upgrade_name", nextUpgrade.getDisplay()))); } } // Previous page if (page > 0) { - layout.slot(45, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.accessory.previous_page"), Material.ARROW, 1), + layout.slot(45, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.accessory.previous_page", Material.ARROW, 1), (click, c) -> c.session(AccessoryBagState.class).update(s -> s.withPage(s.page() - 1))); } // Next page if (page < totalPages - 1) { - layout.slot(53, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.accessory.next_page"), Material.ARROW, 1), + layout.slot(53, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.accessory.next_page", Material.ARROW, 1), (click, c) -> c.session(AccessoryBagState.class).update(s -> s.withPage(s.page() + 1))); } } @@ -124,7 +125,7 @@ public boolean onBottomClick(net.swofty.type.generic.gui.v2.context.ClickContext return true; } - player.sendMessage(I18n.string("gui_sbmenu.bags.accessory.msg.cannot_put")); + player.sendMessage(I18n.string("gui_sbmenu.bags.accessory.msg.cannot_put", player.getLocale())); return false; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIQuiver.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIQuiver.java index 24abfdb63..a704563f5 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIQuiver.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIQuiver.java @@ -4,6 +4,7 @@ import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.skyblockgeneric.collection.CustomCollectionAward; @@ -24,7 +25,7 @@ public class GUIQuiver implements StatefulView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.bags.quiver.title"), InventoryType.CHEST_5_ROW); + return ViewConfiguration.translatable("gui_sbmenu.bags.quiver.title", InventoryType.CHEST_5_ROW); } @Override @@ -50,8 +51,8 @@ public void layout(ViewLayout layout, QuiverState state, ViewContex for (int i = 0; i < entry.getValue(); i++) { int slotIndex = i + rawAmountOfSlots; if (slotIndex < 36) { - layout.slot(slotIndex, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.quiver.locked_slot"), Material.RED_STAINED_GLASS_PANE, 1, - I18n.lore("gui_sbmenu.bags.quiver.locked_slot.lore", Map.of("upgrade_name", entry.getKey().getDisplay())))); + layout.slot(slotIndex, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.quiver.locked_slot", Material.RED_STAINED_GLASS_PANE, 1, + "gui_sbmenu.bags.quiver.locked_slot.lore", Map.of("upgrade_name", entry.getKey().getDisplay()))); } } rawAmountOfSlots += entry.getValue(); @@ -74,7 +75,7 @@ public void layout(ViewLayout layout, QuiverState state, ViewContex }, (slot, oldItem, newItem, s) -> { SkyBlockItem newSkyBlockItem = new SkyBlockItem(newItem); if (!isItemAllowed(newSkyBlockItem)) { - ctx.player().sendMessage(I18n.string("gui_sbmenu.bags.quiver.msg.cannot_put")); + ctx.player().sendMessage(I18n.string("gui_sbmenu.bags.quiver.msg.cannot_put", ctx.player().getLocale())); } }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUISack.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUISack.java index b7dd04928..2b955e409 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUISack.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUISack.java @@ -7,6 +7,7 @@ import net.swofty.commons.StringUtility; import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ClickContext; import net.swofty.type.generic.gui.v2.context.ViewContext; @@ -19,6 +20,7 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUISack implements StatefulView { @@ -82,8 +84,8 @@ public void layout(ViewLayout layout, SackState state, ViewContext ct }; if (!closeGUIButton) { - layout.slot(backSlot, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.sack.go_back"), Material.ARROW, 1, - I18n.lore("gui_sbmenu.bags.sack.go_back.lore")), + layout.slot(backSlot, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.sack.go_back", Material.ARROW, 1, + "gui_sbmenu.bags.sack.go_back.lore"), (click, c) -> c.player().openView(new GUISackOfSacks())); } else { Components.close(layout, backSlot); @@ -111,22 +113,23 @@ public void layout(ViewLayout layout, SackState state, ViewContext ct layout.slot(slot, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); ItemStack.Builder builder = PlayerItemUpdater.playerUpdate(p, skyBlockItem.getItemStack()); ArrayList lore = new ArrayList<>(); Integer amount = p.getSackItems().getAmount(linker); String color = (amount == finalMaxStorage) ? "§a" : "§e"; lore.add(""); - lore.add(I18n.string("gui_sbmenu.bags.sack.stored", Map.of( + lore.add(I18n.string("gui_sbmenu.bags.sack.stored", l, Map.of( "color", color, "amount", String.valueOf(amount), "max", StringUtility.shortenNumber(StringUtility.roundTo(finalMaxStorage, 0)) ))); lore.add(""); if (amount != 0) { - lore.add(I18n.string("gui_sbmenu.bags.sack.right_click_stack")); - lore.add(I18n.string("gui_sbmenu.bags.sack.click_to_pickup")); + lore.add(I18n.string("gui_sbmenu.bags.sack.right_click_stack", l)); + lore.add(I18n.string("gui_sbmenu.bags.sack.click_to_pickup", l)); } else { - lore.add(I18n.string("gui_sbmenu.bags.sack.empty")); + lore.add(I18n.string("gui_sbmenu.bags.sack.empty", l)); } return ItemStackCreator.updateLore(builder, lore); }, (click, c) -> handleSackItemClick(click, c, linker)); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUISackOfSacks.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUISackOfSacks.java index 8aa096265..972a9b252 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUISackOfSacks.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUISackOfSacks.java @@ -6,6 +6,7 @@ import net.minestom.server.item.Material; import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ClickContext; import net.swofty.type.generic.gui.v2.context.ViewContext; @@ -34,7 +35,7 @@ public class GUISackOfSacks implements StatefulView configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.bags.sack_of_sacks.title"), InventoryType.CHEST_5_ROW); + return ViewConfiguration.translatable("gui_sbmenu.bags.sack_of_sacks.title", InventoryType.CHEST_5_ROW); } @Override @@ -83,14 +84,14 @@ public void layout(ViewLayout layout, SackOfSacksState state, for (int i = totalSlots; i < slotsPerPage; i++) { CustomCollectionAward nextUpgrade = getUpgradeNeededForSlotIndex(i); if (nextUpgrade != null) { - layout.slot(i, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.sack_of_sacks.locked_slot"), Material.RED_STAINED_GLASS_PANE, 1, - I18n.lore("gui_sbmenu.bags.sack_of_sacks.locked_slot.lore", Map.of("upgrade_name", nextUpgrade.getDisplay())))); + layout.slot(i, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.sack_of_sacks.locked_slot", Material.RED_STAINED_GLASS_PANE, 1, + "gui_sbmenu.bags.sack_of_sacks.locked_slot.lore", Map.of("upgrade_name", nextUpgrade.getDisplay()))); } } // Insert inventory button - layout.slot(38, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.sack_of_sacks.insert_inventory"), Material.CHEST, 1, - I18n.lore("gui_sbmenu.bags.sack_of_sacks.insert_inventory.lore")), + layout.slot(38, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.sack_of_sacks.insert_inventory", Material.CHEST, 1, + "gui_sbmenu.bags.sack_of_sacks.insert_inventory.lore"), (click, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); int slot = 0; @@ -121,7 +122,7 @@ public boolean onBottomClick(ClickContext click, ViewContext c return true; } - player.sendMessage(I18n.string("gui_sbmenu.bags.sack_of_sacks.msg.cannot_put")); + player.sendMessage(I18n.string("gui_sbmenu.bags.sack_of_sacks.msg.cannot_put", player.getLocale())); return false; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIYourBags.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIYourBags.java index cc60244eb..4457aa385 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIYourBags.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/bags/GUIYourBags.java @@ -4,6 +4,7 @@ import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -17,7 +18,7 @@ public class GUIYourBags extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.bags.main.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.bags.main.title", InventoryType.CHEST_6_ROW); } @Override @@ -30,59 +31,59 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont // Sack of Sacks if (player.hasCustomCollectionAward(CustomCollectionAward.SACK_OF_SACKS)) { - layout.slot(20, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.bags.sack_of_sacks.unlocked"), + layout.slot(20, (s, c) -> TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.bags.sack_of_sacks.unlocked", "80a077e248d142772ea800864f8c578b9d36885b29daf836b64a706882b6ec10", 1, - I18n.lore("gui_sbmenu.bags.sack_of_sacks.unlocked.lore")), + "gui_sbmenu.bags.sack_of_sacks.unlocked.lore"), (click, c) -> c.player().openView(new GUISackOfSacks())); } else { - layout.slot(20, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.sack_of_sacks.locked"), Material.GRAY_DYE, 1, - I18n.lore("gui_sbmenu.bags.sack_of_sacks.locked.lore"))); + layout.slot(20, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.sack_of_sacks.locked", Material.GRAY_DYE, 1, + "gui_sbmenu.bags.sack_of_sacks.locked.lore")); } // Fishing Bag if (player.hasCustomCollectionAward(CustomCollectionAward.FISHING_BAG)) { - layout.slot(21, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.bags.fishing_bag.unlocked"), + layout.slot(21, (s, c) -> TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.bags.fishing_bag.unlocked", "eb8e297df6b8dffcf135dba84ec792d420ad8ecb458d144288572a84603b1631", 1, - I18n.lore("gui_sbmenu.bags.fishing_bag.unlocked.lore"))); + "gui_sbmenu.bags.fishing_bag.unlocked.lore")); } else { - layout.slot(21, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.fishing_bag.locked"), Material.GRAY_DYE, 1, - I18n.lore("gui_sbmenu.bags.fishing_bag.locked.lore"))); + layout.slot(21, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.fishing_bag.locked", Material.GRAY_DYE, 1, + "gui_sbmenu.bags.fishing_bag.locked.lore")); } // Potion Bag if (player.hasCustomCollectionAward(CustomCollectionAward.POTION_BAG)) { - layout.slot(22, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.bags.potion_bag.unlocked"), + layout.slot(22, (s, c) -> TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.bags.potion_bag.unlocked", "9f8b82427b260d0a61e6483fc3b2c35a585851e08a9a9df372548b4168cc817c", 1, - I18n.lore("gui_sbmenu.bags.potion_bag.unlocked.lore"))); + "gui_sbmenu.bags.potion_bag.unlocked.lore")); } else { - layout.slot(22, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.potion_bag.locked"), Material.GRAY_DYE, 1, - I18n.lore("gui_sbmenu.bags.potion_bag.locked.lore"))); + layout.slot(22, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.potion_bag.locked", Material.GRAY_DYE, 1, + "gui_sbmenu.bags.potion_bag.locked.lore")); } // Quiver if (player.hasCustomCollectionAward(CustomCollectionAward.QUIVER)) { - layout.slot(23, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.bags.quiver.unlocked"), + layout.slot(23, (s, c) -> TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.bags.quiver.unlocked", "396ce13ff6155fdf3235d8d22174c5de4bf5512f1adeda1afa3fc28180f3f7", 1, - I18n.lore("gui_sbmenu.bags.quiver.unlocked.lore")), + "gui_sbmenu.bags.quiver.unlocked.lore"), (click, c) -> c.player().openView(new GUIQuiver())); } else { - layout.slot(23, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.quiver.locked"), Material.GRAY_DYE, 1, - I18n.lore("gui_sbmenu.bags.quiver.locked.lore"))); + layout.slot(23, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.quiver.locked", Material.GRAY_DYE, 1, + "gui_sbmenu.bags.quiver.locked.lore")); } // Accessory Bag if (player.hasCustomCollectionAward(CustomCollectionAward.ACCESSORY_BAG)) { layout.slot(24, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); - return ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.bags.accessory_bag.unlocked"), + return TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.bags.accessory_bag.unlocked", "396ce13ff6155fdf3235d8d22174c5de4bf5512f1adeda1afa3fc28180f3f7", 1, - I18n.lore("gui_sbmenu.bags.accessory_bag.unlocked.lore", Map.of( + "gui_sbmenu.bags.accessory_bag.unlocked.lore", Map.of( "magical_power", StringUtility.commaify(p.getMagicalPower()) - ))); + )); }, (click, c) -> c.player().openView(new GUIAccessoryBag())); } else { - layout.slot(24, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.bags.accessory_bag.locked"), Material.GRAY_DYE, 1, - I18n.lore("gui_sbmenu.bags.accessory_bag.locked.lore"))); + layout.slot(24, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.bags.accessory_bag.locked", Material.GRAY_DYE, 1, + "gui_sbmenu.bags.accessory_bag.locked.lore")); } } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUILevelsGuide.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUILevelsGuide.java index d57da75de..27b57fd69 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUILevelsGuide.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUILevelsGuide.java @@ -4,6 +4,7 @@ import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -12,6 +13,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUILevelsGuide extends StatelessView { @@ -33,7 +35,9 @@ public GUILevelsGuide(LevelsGuide guide) { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.levels.guide.title", Map.of("guide_name", StringUtility.toNormalCase(guide.name()))), InventoryType.CHEST_6_ROW); + return ViewConfiguration.withString( + (state, ctx) -> I18n.string("gui_sbmenu.levels.guide.title", ctx.player().getLocale(), Map.of("guide_name", StringUtility.toNormalCase(guide.name()))), + InventoryType.CHEST_6_ROW); } @Override @@ -47,8 +51,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } // Guide info - layout.slot(50, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.guide.info"), Material.REDSTONE_TORCH, 1, - I18n.lore("gui_sbmenu.levels.guide.info.lore"))); + layout.slot(50, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.guide.info", Material.REDSTONE_TORCH, 1, + "gui_sbmenu.levels.guide.info.lore")); // Task items LevelsGuide.TasksSet[] tasks = guide.getTasksSets().toArray(new LevelsGuide.TasksSet[0]); @@ -58,10 +62,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(slot, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); List lore = new ArrayList<>(); if (task.getCauses().size() > 1) { - lore.add(I18n.string("gui_sbmenu.levels.guide.tasks", Map.of("count", String.valueOf(task.getCauses().size())))); + lore.add(I18n.string("gui_sbmenu.levels.guide.tasks", l, Map.of("count", String.valueOf(task.getCauses().size())))); lore.add(""); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUISkyBlockLevel.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUISkyBlockLevel.java index 6afea9d22..647f96d99 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUISkyBlockLevel.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUISkyBlockLevel.java @@ -31,7 +31,9 @@ public GUISkyBlockLevel(SkyBlockLevelRequirement levelRequirement) { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.levels.level.title", Map.of("level", String.valueOf(levelRequirement.asInt()))), InventoryType.CHEST_4_ROW); + return ViewConfiguration.withString( + (state, ctx) -> I18n.string("gui_sbmenu.levels.level.title", ctx.player().getLocale(), Map.of("level", String.valueOf(levelRequirement.asInt()))), + InventoryType.CHEST_4_ROW); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUISkyBlockLevels.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUISkyBlockLevels.java index 2da9b9627..63580e540 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUISkyBlockLevels.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/GUISkyBlockLevels.java @@ -4,6 +4,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.data.datapoints.DatapointToggles; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -16,13 +17,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUISkyBlockLevels extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.levels.main.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.levels.main.title", InventoryType.CHEST_6_ROW); } @Override @@ -34,18 +36,20 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont // Toggle SkyBlock Levels in Chat layout.slot(50, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); String status = player.getToggles().get(DatapointToggles.Toggles.ToggleType.SKYBLOCK_LEVELS_IN_CHAT) - ? I18n.string("gui_sbmenu.levels.main.chat_toggle.enabled") : I18n.string("gui_sbmenu.levels.main.chat_toggle.disabled"); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.chat_toggle"), + ? I18n.string("gui_sbmenu.levels.main.chat_toggle.enabled", l) : I18n.string("gui_sbmenu.levels.main.chat_toggle.disabled", l); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.main.chat_toggle", player.getToggles().get(DatapointToggles.Toggles.ToggleType.SKYBLOCK_LEVELS_IN_CHAT) ? Material.LIME_DYE : Material.GRAY_DYE, 1, - I18n.lore("gui_sbmenu.levels.main.chat_toggle.lore", Map.of("status", status))); + "gui_sbmenu.levels.main.chat_toggle.lore", Map.of("status", status)); }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); player.sendMessage(player.getToggles().get(DatapointToggles.Toggles.ToggleType.SKYBLOCK_LEVELS_IN_CHAT) ? - I18n.string("gui_sbmenu.levels.main.msg.chat_disabled") : - I18n.string("gui_sbmenu.levels.main.msg.chat_enabled")); + I18n.string("gui_sbmenu.levels.main.msg.chat_disabled", l) : + I18n.string("gui_sbmenu.levels.main.msg.chat_enabled", l)); player.getToggles().set(DatapointToggles.Toggles.ToggleType.SKYBLOCK_LEVELS_IN_CHAT, !player.getToggles().get(DatapointToggles.Toggles.ToggleType.SKYBLOCK_LEVELS_IN_CHAT)); c.session(DefaultState.class).render(); @@ -61,8 +65,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont display.append(displayList.get(j)); if (j < displayList.size() - 1) display.append("\n"); } - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.level_rewards"), Material.CHEST, 1, - I18n.lore("gui_sbmenu.levels.main.level_rewards.lore", Map.of("display", display.toString()))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.main.level_rewards", Material.CHEST, 1, + "gui_sbmenu.levels.main.level_rewards.lore", Map.of("display", display.toString())); }, (click, c) -> c.player().openView(new GUILevelRewards())); // Your SkyBlock Level Ranking @@ -72,22 +76,22 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont int completedChallenges = player.getSkyBlockExperience().getCompletedExperienceCauses().size(); int totalChallenges = SkyBlockLevelCause.getAmountOfCauses(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.ranking"), + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.main.ranking", Material.PAINTING, 1, - I18n.lore("gui_sbmenu.levels.main.ranking.lore", Map.of( + "gui_sbmenu.levels.main.ranking.lore", Map.of( "level_display", level.getColor() + level.toString(), "xp", String.valueOf(Math.round(player.getSkyBlockExperience().getTotalXP())), - "percent", new java.text.DecimalFormat("##.##").format((double) completedChallenges / totalChallenges * 100)))); + "percent", new java.text.DecimalFormat("##.##").format((double) completedChallenges / totalChallenges * 100))); }); // SkyBlock Guide - layout.slot(25, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.guide"), Material.FILLED_MAP, 1, - I18n.lore("gui_sbmenu.levels.main.guide.lore")), + layout.slot(25, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.main.guide", Material.FILLED_MAP, 1, + "gui_sbmenu.levels.main.guide.lore"), (click, c) -> c.player().openView(new GUILevelsGuide(LevelsGuide.STARTER))); // Prefix Emblems - layout.slot(43, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.emblems"), Material.NAME_TAG, 1, - I18n.lore("gui_sbmenu.levels.main.emblems.lore")), + layout.slot(43, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.main.emblems", Material.NAME_TAG, 1, + "gui_sbmenu.levels.main.emblems.lore"), (click, c) -> c.player().openView(new GUIEmblems())); // Level progression slots @@ -109,29 +113,30 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(slot, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); List lore = new ArrayList<>(); Material material = level.isMilestone() ? Material.RED_STAINED_GLASS : Material.RED_STAINED_GLASS_PANE; if (unlockedLevel == level.asInt()) { - lore.add(I18n.string("gui_sbmenu.levels.main.your_level")); + lore.add(I18n.string("gui_sbmenu.levels.main.your_level", l)); lore.add(" "); material = level.isMilestone() ? Material.LIME_STAINED_GLASS : Material.LIME_STAINED_GLASS_PANE; } else if (unlockedLevel + 1 == level.asInt()) { - lore.add(I18n.string("gui_sbmenu.levels.main.next_level")); + lore.add(I18n.string("gui_sbmenu.levels.main.next_level", l)); lore.add(" "); material = level.isMilestone() ? Material.YELLOW_STAINED_GLASS : Material.YELLOW_STAINED_GLASS_PANE; } - lore.add(I18n.string("gui_sbmenu.levels.main.rewards")); + lore.add(I18n.string("gui_sbmenu.levels.main.rewards", l)); level.getUnlocks().forEach(unlock -> lore.addAll(unlock.getDisplay(p, level.asInt()))); lore.add(" "); if (unlockedLevel == level.asInt()) { - lore.add(I18n.string("gui_sbmenu.levels.main.unlocked")); + lore.add(I18n.string("gui_sbmenu.levels.main.unlocked", l)); lore.add(" "); } - lore.add(I18n.string("gui_sbmenu.levels.main.click_to_view")); + lore.add(I18n.string("gui_sbmenu.levels.main.click_to_view", l)); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.level", Map.of("level", String.valueOf(level.asInt()))), material, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.level", l, Map.of("level", String.valueOf(level.asInt()))), material, 1, lore); }, (click, c) -> c.player().openView(new GUISkyBlockLevel(level))); } @@ -140,19 +145,20 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (currentMilestone != null) { layout.slot(30, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); List lore = new ArrayList<>(); - lore.add(I18n.string("gui_sbmenu.levels.main.milestone")); + lore.add(I18n.string("gui_sbmenu.levels.main.milestone", l)); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.main.rewards")); + lore.add(I18n.string("gui_sbmenu.levels.main.rewards", l)); currentMilestone.getUnlocks().forEach(unlock -> lore.addAll(unlock.getDisplay(p, currentMilestone.asInt()))); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.main.xp_left", Map.of( + lore.add(I18n.string("gui_sbmenu.levels.main.xp_left", l, Map.of( "xp", String.valueOf((long) (currentMilestone.getCumulativeExperience() - p.getSkyBlockExperience().getTotalXP())), "percent", String.valueOf((int) (p.getSkyBlockExperience().getTotalXP() / currentMilestone.getCumulativeExperience() * 100))))); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.main.click_to_view")); + lore.add(I18n.string("gui_sbmenu.levels.main.click_to_view", l)); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.level", Map.of("level", String.valueOf(currentMilestone.asInt()))), Material.PURPLE_STAINED_GLASS_PANE, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.main.level", l, Map.of("level", String.valueOf(currentMilestone.asInt()))), Material.PURPLE_STAINED_GLASS_PANE, 1, lore); }, (click, c) -> c.player().openView(new GUISkyBlockLevel(currentMilestone))); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/rewards/GUILevelRewards.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/rewards/GUILevelRewards.java index 06c4da5f3..a1fef09da 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/rewards/GUILevelRewards.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/levels/rewards/GUILevelRewards.java @@ -3,6 +3,7 @@ import net.minestom.server.inventory.InventoryType; import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -15,13 +16,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUILevelRewards extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.levels.rewards.title"), InventoryType.CHEST_4_ROW); + return ViewConfiguration.translatable("gui_sbmenu.levels.rewards.title", InventoryType.CHEST_4_ROW); } @Override @@ -33,44 +35,46 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont // Feature Rewards layout.slot(11, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); DatapointSkyBlockExperience.PlayerSkyBlockExperience experience = player.getSkyBlockExperience(); List lore = new ArrayList<>(); - lore.addAll(I18n.lore("gui_sbmenu.levels.rewards.feature.lore")); + lore.addAll(I18n.lore("gui_sbmenu.levels.rewards.feature.lore", l)); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.rewards.next_reward")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.next_reward", l)); Map.Entry> nextAward = CustomLevelAward.getNextReward(experience.getLevel().asInt()); if (nextAward == null) { - lore.add(I18n.string("gui_sbmenu.levels.rewards.no_more")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.no_more", l)); } else { nextAward.getValue().forEach(award -> lore.add("§7" + award.getDisplay())); - lore.add(I18n.string("gui_sbmenu.levels.rewards.at_level", Map.of("level", String.valueOf(nextAward.getKey())))); + lore.add(I18n.string("gui_sbmenu.levels.rewards.at_level", l, Map.of("level", String.valueOf(nextAward.getKey())))); } lore.add(" "); lore.addAll(getAsDisplay(CustomLevelAward.getFromLevel(experience.getLevel().asInt()).size(), CustomLevelAward.getTotalLevelAwards())); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.rewards.click_to_view")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.click_to_view", l)); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.rewards.feature"), Material.NETHER_STAR, 1, lore); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.rewards.feature", Material.NETHER_STAR, 1, lore); }, (click, c) -> c.player().openView(new GUILevelFeatureRewards())); // Prefix Color Rewards layout.slot(12, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); List lore = new ArrayList<>(); - lore.addAll(I18n.lore("gui_sbmenu.levels.rewards.prefix.lore")); + lore.addAll(I18n.lore("gui_sbmenu.levels.rewards.prefix.lore", l)); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.rewards.next_reward")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.next_reward", l)); Map.Entry nextPrefix = player.getSkyBlockExperience() .getLevel().getNextPrefixChange(); if (nextPrefix == null) { - lore.add(I18n.string("gui_sbmenu.levels.rewards.no_more")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.no_more", l)); } else { lore.add(nextPrefix.getValue() + nextPrefix.getKey().getPrefixDisplay()); - lore.add(I18n.string("gui_sbmenu.levels.rewards.at_level", Map.of("level", String.valueOf(nextPrefix.getKey().asInt())))); + lore.add(I18n.string("gui_sbmenu.levels.rewards.at_level", l, Map.of("level", String.valueOf(nextPrefix.getKey().asInt())))); } lore.add(" "); lore.addAll(getAsDisplay( @@ -78,18 +82,19 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont SkyBlockLevelRequirement.getAllPrefixChanges().size() )); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.rewards.click_to_view")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.click_to_view", l)); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.rewards.prefix"), Material.GRAY_DYE, 1, lore); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.rewards.prefix", Material.GRAY_DYE, 1, lore); }, (click, c) -> c.player().openView(new GUILevelPrefixRewards())); // Emblem Rewards layout.slot(13, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); List lore = new ArrayList<>(); - lore.addAll(I18n.lore("gui_sbmenu.levels.rewards.emblem.lore")); + lore.addAll(I18n.lore("gui_sbmenu.levels.rewards.emblem.lore", l)); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.rewards.next_reward")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.next_reward", l)); List levelEmblems = SkyBlockEmblems.getEmblemsWithLevelCause(); SkyBlockEmblems.SkyBlockEmblem nextEmblem = null; @@ -100,10 +105,10 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } if (nextEmblem == null) { - lore.add(I18n.string("gui_sbmenu.levels.rewards.no_more")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.no_more", l)); } else { lore.add("§f" + nextEmblem.displayName() + " " + nextEmblem.emblem()); - lore.add(I18n.string("gui_sbmenu.levels.rewards.at_level", Map.of("level", String.valueOf(((LevelCause) nextEmblem.cause()).getLevel())))); + lore.add(I18n.string("gui_sbmenu.levels.rewards.at_level", l, Map.of("level", String.valueOf(((LevelCause) nextEmblem.cause()).getLevel())))); } lore.add(" "); @@ -112,9 +117,9 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont levelEmblems.size() )); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.levels.rewards.click_to_view")); + lore.add(I18n.string("gui_sbmenu.levels.rewards.click_to_view", l)); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.rewards.emblem"), Material.NAME_TAG, 1, lore); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.rewards.emblem", Material.NAME_TAG, 1, lore); }, (click, c) -> c.player().openView(new GUILevelEmblemRewards())); // Statistic Rewards @@ -122,8 +127,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont SkyBlockPlayer player = (SkyBlockPlayer) c.player(); SkyBlockLevelRequirement nextLevel = player.getSkyBlockExperience().getLevel().getNextLevel(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.levels.rewards.statistic"), Material.DIAMOND_HELMET, 1, - I18n.lore("gui_sbmenu.levels.rewards.statistic.lore", Map.of("next_level", nextLevel == null ? "§cMAX" : String.valueOf(nextLevel.asInt())))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.levels.rewards.statistic", Material.DIAMOND_HELMET, 1, + "gui_sbmenu.levels.rewards.statistic.lore", Map.of("next_level", nextLevel == null ? "§cMAX" : String.valueOf(nextLevel.asInt()))); }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileCreate.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileCreate.java index e577737f0..f799d3139 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileCreate.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileCreate.java @@ -10,6 +10,7 @@ import net.swofty.type.generic.data.mongodb.UserDatabase; import net.swofty.type.generic.event.actions.data.ActionPlayerDataSave; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -25,7 +26,7 @@ public class GUIProfileCreate extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.profiles.create.title"), InventoryType.CHEST_3_ROW); + return ViewConfiguration.translatable("gui_sbmenu.profiles.create.title", InventoryType.CHEST_3_ROW); } @SneakyThrows @@ -35,8 +36,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont String profileName = SkyBlockPlayerProfiles.getRandomName(); - layout.slot(11, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.create.confirm"), Material.GREEN_TERRACOTTA, 1, - I18n.lore("gui_sbmenu.profiles.create.confirm.lore", Map.of("profile_name", profileName))), + layout.slot(11, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profiles.create.confirm", Material.GREEN_TERRACOTTA, 1, + "gui_sbmenu.profiles.create.confirm.lore", Map.of("profile_name", profileName)), (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); SkyBlockPlayerProfiles profiles = player.getProfiles(); @@ -62,7 +63,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont player.sendTo(ServerType.SKYBLOCK_ISLAND, true); }); - layout.slot(15, (s, c) -> ItemStackCreator.createNamedItemStack(Material.RED_TERRACOTTA, I18n.string("gui_sbmenu.profiles.create.cancel")), + layout.slot(15, (s, c) -> ItemStackCreator.createNamedItemStack(Material.RED_TERRACOTTA, I18n.string("gui_sbmenu.profiles.create.cancel", c.player().getLocale())), (click, c) -> c.player().openView(new GUIProfileSelectMode())); } } \ No newline at end of file diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileManagement.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileManagement.java index fa927ab0c..8141403a0 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileManagement.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileManagement.java @@ -11,6 +11,7 @@ import net.swofty.type.generic.data.mongodb.ProfilesDatabase; import net.swofty.type.generic.data.datapoints.DatapointLong; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -22,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.UUID; public class GUIProfileManagement extends StatelessView { @@ -29,7 +31,7 @@ public class GUIProfileManagement extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.profiles.management.title"), InventoryType.CHEST_4_ROW); + return ViewConfiguration.translatable("gui_sbmenu.profiles.management.title", InventoryType.CHEST_4_ROW); } @SneakyThrows @@ -48,8 +50,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (profileIds.size() <= profileCount) { // Empty profile slot - layout.slot(slot, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.empty_slot"), Material.OAK_BUTTON, 1, - I18n.lore("gui_sbmenu.profiles.empty_slot.lore")), + layout.slot(slot, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profiles.empty_slot", Material.OAK_BUTTON, 1, + "gui_sbmenu.profiles.empty_slot.lore"), (click, c) -> c.player().openView(new GUIProfileSelectMode())); continue; } @@ -74,29 +76,32 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (selected) { layout.slot(slot, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); - List lore = new ArrayList<>(Arrays.asList(I18n.string("gui_sbmenu.profiles.selected.subtitle"), " ")); + Locale l = p.getLocale(); + List lore = new ArrayList<>(Arrays.asList(I18n.string("gui_sbmenu.profiles.selected.subtitle", l), " ")); updateLore(p.getUuid(), finalDataHandler, lore); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.profiles.selected.playing")); + lore.add(I18n.string("gui_sbmenu.profiles.selected.playing", l)); String profileName = finalDataHandler.get(SkyBlockDataHandler.Data.PROFILE_NAME, DatapointString.class).getValue(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.selected", java.util.Map.of("profile_name", profileName)), Material.EMERALD_BLOCK, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.selected", l, java.util.Map.of("profile_name", profileName)), Material.EMERALD_BLOCK, 1, lore); }, (click, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); String profileName = finalDataHandler.get(SkyBlockDataHandler.Data.PROFILE_NAME, DatapointString.class).getValue(); - p.sendMessage(I18n.string("gui_sbmenu.profiles.msg.playing_on", java.util.Map.of("profile_name", profileName))); - p.sendMessage(I18n.string("gui_sbmenu.profiles.msg.switch_first")); + p.sendMessage(I18n.string("gui_sbmenu.profiles.msg.playing_on", l, java.util.Map.of("profile_name", profileName))); + p.sendMessage(I18n.string("gui_sbmenu.profiles.msg.switch_first", l)); }); } else { layout.slot(slot, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); - List lore = new ArrayList<>(Arrays.asList(I18n.string("gui_sbmenu.profiles.unselected.subtitle"), " ")); + Locale l = p.getLocale(); + List lore = new ArrayList<>(Arrays.asList(I18n.string("gui_sbmenu.profiles.unselected.subtitle", l), " ")); updateLore(p.getUuid(), finalDataHandler, lore); lore.add(" "); - lore.add(I18n.string("gui_sbmenu.profiles.unselected.click")); + lore.add(I18n.string("gui_sbmenu.profiles.unselected.click", l)); String profileName = finalDataHandler.get(SkyBlockDataHandler.Data.PROFILE_NAME, DatapointString.class).getValue(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.unselected", java.util.Map.of("profile_name", profileName)), Material.GRASS_BLOCK, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.unselected", l, java.util.Map.of("profile_name", profileName)), Material.GRASS_BLOCK, 1, lore); }, (click, c) -> c.player().openView(new GUIProfileSelect(profileId))); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileSelect.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileSelect.java index 90f1b7a31..40cbbb789 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileSelect.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileSelect.java @@ -10,6 +10,7 @@ import net.swofty.type.generic.data.mongodb.UserDatabase; import net.swofty.type.generic.event.actions.data.ActionPlayerDataSave; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler; @@ -30,7 +31,7 @@ public GUIProfileSelect(UUID profileUuid) { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.profiles.select.title"), InventoryType.CHEST_4_ROW); + return ViewConfiguration.translatable("gui_sbmenu.profiles.select.title", InventoryType.CHEST_4_ROW); } @Override @@ -50,8 +51,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont switchingTo = "Unknown"; } - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.select.switch"), Material.GRASS_BLOCK, 1, - I18n.lore("gui_sbmenu.profiles.select.switch.lore", Map.of("current", currentProfile, "switching_to", switchingTo))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profiles.select.switch", Material.GRASS_BLOCK, 1, + "gui_sbmenu.profiles.select.switch.lore", Map.of("current", currentProfile, "switching_to", switchingTo)); }, (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); SkyBlockPlayerProfiles profiles = player.getProfiles(); @@ -68,13 +69,14 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont }); // Delete Profile - layout.slot(15, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.select.delete"), Material.RED_STAINED_GLASS, 1, - I18n.lore("gui_sbmenu.profiles.select.delete.lore")), + layout.slot(15, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profiles.select.delete", Material.RED_STAINED_GLASS, 1, + "gui_sbmenu.profiles.select.delete.lore"), (click, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + java.util.Locale l = player.getLocale(); if (CoopDatabase.getFromMemberProfile(profileUuid) != null) { - player.sendMessage(I18n.string("gui_sbmenu.profiles.select.msg.cannot_delete_coop")); - player.sendMessage(I18n.string("gui_sbmenu.profiles.select.msg.coop_leave")); + player.sendMessage(I18n.string("gui_sbmenu.profiles.select.msg.cannot_delete_coop", l)); + player.sendMessage(I18n.string("gui_sbmenu.profiles.select.msg.coop_leave", l)); return; } @@ -83,10 +85,10 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont try { SkyBlockDataHandler handler = SkyBlockDataHandler.createFromProfileOnly(new ProfilesDatabase(profileUuid.toString()).getDocument()); - player.sendMessage(I18n.string("gui_sbmenu.profiles.select.msg.deleted", Map.of("profile_name", + player.sendMessage(I18n.string("gui_sbmenu.profiles.select.msg.deleted", l, Map.of("profile_name", handler.get(SkyBlockDataHandler.Data.PROFILE_NAME, DatapointString.class).getValue()))); } catch (Exception e) { - player.sendMessage(I18n.string("gui_sbmenu.profiles.select.msg.deleted_generic")); + player.sendMessage(I18n.string("gui_sbmenu.profiles.select.msg.deleted_generic", l)); } ProfilesDatabase.collection.deleteOne(Filters.eq("_id", profileUuid.toString())); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileSelectMode.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileSelectMode.java index d7cf14688..94cb8ef56 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileSelectMode.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/profiles/GUIProfileSelectMode.java @@ -3,6 +3,7 @@ import net.minestom.server.inventory.InventoryType; import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -12,7 +13,7 @@ public class GUIProfileSelectMode extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.profiles.mode.title"), InventoryType.CHEST_4_ROW); + return ViewConfiguration.translatable("gui_sbmenu.profiles.mode.title", InventoryType.CHEST_4_ROW); } @Override @@ -20,12 +21,12 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.fill(layout); Components.back(layout, 31, ctx); - layout.slot(11, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.mode.classic"), Material.GRASS_BLOCK, 1, - I18n.lore("gui_sbmenu.profiles.mode.classic.lore")), + layout.slot(11, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profiles.mode.classic", Material.GRASS_BLOCK, 1, + "gui_sbmenu.profiles.mode.classic.lore"), (click, c) -> c.player().openView(new GUIProfileCreate())); - layout.slot(15, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.profiles.mode.special"), Material.BLAZE_POWDER, 1, - I18n.lore("gui_sbmenu.profiles.mode.special.lore")), - (click, c) -> c.player().sendMessage(I18n.string("gui_sbmenu.profiles.mode.msg.unavailable"))); + layout.slot(15, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.profiles.mode.special", Material.BLAZE_POWDER, 1, + "gui_sbmenu.profiles.mode.special.lore"), + (click, c) -> c.player().sendMessage(I18n.string("gui_sbmenu.profiles.mode.msg.unavailable", c.player().getLocale()))); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/questlog/GUIFairySoulsGuide.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/questlog/GUIFairySoulsGuide.java index 7ad8ff3ff..cce86a326 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/questlog/GUIFairySoulsGuide.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/questlog/GUIFairySoulsGuide.java @@ -6,6 +6,8 @@ import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; + +import java.util.Locale; import net.swofty.type.skyblockgeneric.data.monogdb.FairySoulDatabase; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import net.swofty.type.skyblockgeneric.user.fairysouls.FairySoulZone; @@ -21,7 +23,7 @@ public class GUIFairySoulsGuide extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.questlog.fairy_souls_guide.title"), InventoryType.CHEST_5_ROW); + return ViewConfiguration.translatable("gui_sbmenu.questlog.fairy_souls_guide.title", InventoryType.CHEST_5_ROW); } @Override @@ -33,6 +35,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont // Miscellaneous fairy souls layout.slot(10, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); int obtainedSouls = player.getFairySoulHandler().getFound(FairySoulZone.MISC_DUNGEONS) + player.getFairySoulHandler().getFound(FairySoulZone.MISC_FISHING) + player.getFairySoulHandler().getFound(FairySoulZone.MISC_GARDEN) + @@ -43,14 +46,14 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont player.getFairySoulHandler().getMax(FairySoulZone.MISC_GARDEN) + player.getFairySoulHandler().getMax(FairySoulZone.MISC_PLACEABLE) + player.getFairySoulHandler().getMax(FairySoulZone.MISC_GLACITE_MINESHAFTS); - return ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.questlog.fairy_souls_guide.miscellaneous"), + return ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.questlog.fairy_souls_guide.miscellaneous", l), "126ec1ca185b47aad39f931db8b0a8500ded86a127a204886ed4b3783ad1775c", 1, - I18n.string("gui_sbmenu.questlog.fairy_souls_guide.fairy_souls_count", Map.of("found", String.valueOf(obtainedSouls), "total", String.valueOf(totalSouls))), - I18n.string("gui_sbmenu.questlog.fairy_souls_guide.dungeons", Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_DUNGEONS)))), - I18n.string("gui_sbmenu.questlog.fairy_souls_guide.fishing", Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_FISHING)))), - I18n.string("gui_sbmenu.questlog.fairy_souls_guide.garden", Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_GARDEN)))), - I18n.string("gui_sbmenu.questlog.fairy_souls_guide.placeable", Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_PLACEABLE)))), - I18n.string("gui_sbmenu.questlog.fairy_souls_guide.glacite_mineshafts", Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_GLACITE_MINESHAFTS))))); + I18n.string("gui_sbmenu.questlog.fairy_souls_guide.fairy_souls_count", l, Map.of("found", String.valueOf(obtainedSouls), "total", String.valueOf(totalSouls))), + I18n.string("gui_sbmenu.questlog.fairy_souls_guide.dungeons", l, Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_DUNGEONS)))), + I18n.string("gui_sbmenu.questlog.fairy_souls_guide.fishing", l, Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_FISHING)))), + I18n.string("gui_sbmenu.questlog.fairy_souls_guide.garden", l, Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_GARDEN)))), + I18n.string("gui_sbmenu.questlog.fairy_souls_guide.placeable", l, Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_PLACEABLE)))), + I18n.string("gui_sbmenu.questlog.fairy_souls_guide.glacite_mineshafts", l, Map.of("count", String.valueOf(player.getFairySoulHandler().getMax(FairySoulZone.MISC_GLACITE_MINESHAFTS))))); }); FairySouls[] allFairySouls = FairySouls.values(); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/questlog/GUIMissionLog.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/questlog/GUIMissionLog.java index aea9e0dbc..b020fb608 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/questlog/GUIMissionLog.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/questlog/GUIMissionLog.java @@ -5,6 +5,7 @@ import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.*; import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.i18n.I18n; @@ -20,6 +21,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIMissionLog extends StatelessView { @@ -42,7 +44,9 @@ public GUIMissionLog(boolean showCompleted) { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.questlog.title", Map.of("suffix", showCompleted ? "(Completed)" : "")), InventoryType.CHEST_6_ROW); + return ViewConfiguration.withString( + (state, ctx) -> I18n.string("gui_sbmenu.questlog.title", ctx.player().getLocale(), Map.of("suffix", showCompleted ? "(Completed)" : "")), + InventoryType.CHEST_6_ROW); } @Override @@ -51,29 +55,32 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.close(layout, 49); Components.back(layout, 48, ctx); - layout.slot(4, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.questlog.info", Map.of("suffix", showCompleted ? "(Completed)" : "")), - Material.WRITABLE_BOOK, 1, I18n.lore("gui_sbmenu.questlog.info.lore"))); + layout.slot(4, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.questlog.info", l, Map.of("suffix", showCompleted ? "(Completed)" : "")), + Material.WRITABLE_BOOK, 1, I18n.lore("gui_sbmenu.questlog.info.lore", l)); + }); // Fairy Souls layout.slot(10, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); - return ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.questlog.fairy_souls"), + return TranslatableItemStackCreator.getStackHead(c.player(), "gui_sbmenu.questlog.fairy_souls", "b96923ad247310007f6ae5d326d847ad53864cf16c3565a181dc8e6b20be2387", 1, - I18n.lore("gui_sbmenu.questlog.fairy_souls.lore", Map.of("found", String.valueOf(player.getFairySoulHandler().getTotalFoundFairySouls()), "total", String.valueOf(FairySoulDatabase.getAllSouls().size())))); + "gui_sbmenu.questlog.fairy_souls.lore", Map.of("found", String.valueOf(player.getFairySoulHandler().getTotalFoundFairySouls()), "total", String.valueOf(FairySoulDatabase.getAllSouls().size()))); }, (_, c) -> { c.push(new GUIFairySoulsGuide()); }); // Toggle completed/ongoing if (showCompleted) { - layout.slot(50, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.questlog.ongoing_quests"), Material.BOOK, 1, - I18n.lore("gui_sbmenu.questlog.ongoing_quests.lore")), + layout.slot(50, (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.questlog.ongoing_quests", Material.BOOK, 1, + "gui_sbmenu.questlog.ongoing_quests.lore"), (click, c) -> c.replace(new GUIMissionLog(false))); } else { layout.slot(50, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.questlog.completed_quests"), Material.BOOK, 1, - I18n.lore("gui_sbmenu.questlog.completed_quests.lore", Map.of("count", String.valueOf(player.getMissionData().getCompletedMissions().size())))); + return TranslatableItemStackCreator.getStack(c.player(), "gui_sbmenu.questlog.completed_quests", Material.BOOK, 1, + "gui_sbmenu.questlog.completed_quests.lore", Map.of("count", String.valueOf(player.getMissionData().getCompletedMissions().size()))); }, (_, c) -> c.replace(new GUIMissionLog(true))); } @@ -111,6 +118,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(slot, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); MissionData data = p.getMissionData(); List lore = new ArrayList<>(List.of("§7 ")); @@ -139,7 +147,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (firstMissionInSetEntry != null) { MissionData.ActiveMission firstMissionInSet = firstMissionInSetEntry.getKey(); - lore.add(I18n.string("gui_sbmenu.questlog.started")); + lore.add(I18n.string("gui_sbmenu.questlog.started", l)); lore.add("§f " + SkyBlockCalendar.getMonthName( SkyBlockCalendar.getMonth(firstMissionInSet.getMissionStarted())) + " " + StringUtility.ntify(SkyBlockCalendar.getDay(firstMissionInSet.getMissionStarted()))); @@ -147,14 +155,14 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (showCompleted) { lore.add("§7 "); - lore.add(I18n.string("gui_sbmenu.questlog.completed")); + lore.add(I18n.string("gui_sbmenu.questlog.completed", l)); lore.add("§f " + SkyBlockCalendar.getMonthName( SkyBlockCalendar.getMonth(firstMissionInSet.getMissionEnded())) + " " + StringUtility.ntify(SkyBlockCalendar.getDay(firstMissionInSet.getMissionEnded()))); lore.add("§7 " + SkyBlockCalendar.getDisplay(firstMissionInSet.getMissionEnded())); } } else { - lore.add(I18n.string("gui_sbmenu.questlog.not_started")); + lore.add(I18n.string("gui_sbmenu.questlog.not_started", l)); } return ItemStackCreator.enchant(ItemStackCreator.getStack("§a" + StringUtility.toNormalCase(missionSet.name()), diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIMinionRecipes.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIMinionRecipes.java index 6075aad97..7567588c1 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIMinionRecipes.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIMinionRecipes.java @@ -32,7 +32,8 @@ public GUIMinionRecipes(MinionRegistry minionRegistry) { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.recipe.minion.title", Map.of("minion_name", StringUtility.toNormalCase(minionRegistry.toString()))), + return ViewConfiguration.withString( + (state, ctx) -> I18n.string("gui_sbmenu.recipe.minion.title", ctx.player().getLocale(), Map.of("minion_name", StringUtility.toNormalCase(minionRegistry.toString()))), InventoryType.CHEST_6_ROW); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipe.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipe.java index a9f269158..f118522ff 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipe.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipe.java @@ -43,7 +43,9 @@ public GUIRecipe(SkyBlockItem item, int recipeIndex) { public ViewConfiguration configuration() { ItemType type = item.getAttributeHandler().getPotentialType(); String name = type != null ? type.getDisplayName() : "Unknown"; - return new ViewConfiguration<>(I18n.string("gui_sbmenu.recipe.view.title", java.util.Map.of("item_name", name)), InventoryType.CHEST_6_ROW); + return ViewConfiguration.withString( + (state, ctx) -> I18n.string("gui_sbmenu.recipe.view.title", ctx.player().getLocale(), java.util.Map.of("item_name", name)), + InventoryType.CHEST_6_ROW); } @SneakyThrows @@ -53,8 +55,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.close(layout, 49); Components.back(layout, 48, ctx); - layout.slot(23, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.view.crafting_table"), Material.CRAFTING_TABLE, 1, - I18n.lore("gui_sbmenu.recipe.view.crafting_table.lore"))); + layout.slot(23, (s, c) -> { + java.util.Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.view.crafting_table", l), Material.CRAFTING_TABLE, 1, + I18n.lore("gui_sbmenu.recipe.view.crafting_table.lore", l)); + }); ItemType itemTypeLinker = item.getAttributeHandler().getPotentialType(); if (item.toConfigurableItem() == null) { @@ -71,8 +76,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont // Next recipe button if (recipes.size() > actualRecipeIndex + 1) { - layout.slot(32, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.view.next"), Material.ARROW, 1, - I18n.lore("gui_sbmenu.recipe.view.next.lore")), + layout.slot(32, (s, c) -> { + java.util.Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.view.next", l), Material.ARROW, 1, + I18n.lore("gui_sbmenu.recipe.view.next.lore", l)); + }, (click, c) -> { c.push(new GUIRecipe(item, actualRecipeIndex + 1)); }); @@ -80,8 +88,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont // Previous recipe button if (actualRecipeIndex > 0) { - layout.slot(14, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.view.previous"), Material.ARROW, 1, - I18n.lore("gui_sbmenu.recipe.view.previous.lore")), + layout.slot(14, (s, c) -> { + java.util.Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.view.previous", l), Material.ARROW, 1, + I18n.lore("gui_sbmenu.recipe.view.previous.lore", l)); + }, (click, c) -> { c.push(new GUIRecipe(item, actualRecipeIndex - 1)); }); @@ -109,7 +120,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont List existingLore = builder.build().get(DataComponents.LORE); ArrayList lore = existingLore != null ? new ArrayList<>(existingLore) : new ArrayList<>(); lore.add(Component.text(" ")); - lore.add(Component.text(I18n.string("gui_sbmenu.recipe.view.click_to_view"))); + lore.add(Component.text(I18n.string("gui_sbmenu.recipe.view.click_to_view", player.getLocale()))); builder.set(DataComponents.LORE, lore); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeBook.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeBook.java index a5ddcf749..563161d63 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeBook.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeBook.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIRecipeBook extends StatelessView { @@ -26,7 +27,7 @@ public class GUIRecipeBook extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.recipe.book.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.recipe.book.title", InventoryType.CHEST_6_ROW); } @Override @@ -39,8 +40,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont allRecipes.addAll(ShapedRecipe.CACHED_RECIPES); allRecipes.addAll(ShapelessRecipe.CACHED_RECIPES); - layout.slot(51, (_, _) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.search"), Material.OAK_SIGN, 1, - I18n.lore("gui_sbmenu.recipe.book.search.lore")), (_, c) -> { + layout.slot(51, (_, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.search", l), Material.OAK_SIGN, 1, + I18n.lore("gui_sbmenu.recipe.book.search.lore", l)); + }, (_, c) -> { new HypixelSignGUI(c.player()).open(new String[]{"Enter query", ""}).thenAccept(line -> { if (line == null) { return; @@ -52,6 +56,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(4, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); StringBuilder missionDisplay = new StringBuilder(); List missionLore = new ArrayList<>(); SkyBlockRecipe.getMissionDisplay(missionLore, player.getUuid()); @@ -59,8 +64,8 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont missionDisplay.append(missionLore.get(j)); if (j < missionLore.size() - 1) missionDisplay.append("\n"); } - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.info"), Material.BOOK, 1, - I18n.lore("gui_sbmenu.recipe.book.info.lore", Map.of("mission_display", missionDisplay.toString()))); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.info", l), Material.BOOK, 1, + I18n.lore("gui_sbmenu.recipe.book.info.lore", l, Map.of("mission_display", missionDisplay.toString()))); }); for (int i = 0; i < CATEGORY_SLOTS.length && i < SkyBlockRecipe.RecipeType.values().length; i++) { @@ -76,6 +81,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(slot, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); ArrayList allowedRecipes = new ArrayList<>(); typeRecipes.forEach(recipe -> { @@ -96,15 +102,16 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont String progressBar = completedLoadingBar + uncompletedLoadingBar + "§r §e" + allowedRecipes.size() + "§6/§e" + typeRecipes.size(); String categoryName = StringUtility.toNormalCase(type.name()); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.category", Map.of("category_name", categoryName)), + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.category", l, Map.of("category_name", categoryName)), type.getMaterial(), 1, - I18n.lore("gui_sbmenu.recipe.book.category.lore", Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); + I18n.lore("gui_sbmenu.recipe.book.category.lore", l, Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); }, (_, c) -> c.push(new GUIRecipeCategory(type), GUIRecipeCategory.createInitialState((SkyBlockPlayer) c.player(), type))); } // Slayer recipes layout.slot(32, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); SkyBlockRecipe.RecipeType type = SkyBlockRecipe.RecipeType.SLAYER; ArrayList recipeTypes = new ArrayList<>(); @@ -141,9 +148,9 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont completedLoadingBar.length() - formattingCodeLength, maxBarLength)); String progressBar = completedLoadingBar + uncompletedLoadingBar + "§r §e" + allowedRecipes.size() + "§6/§e" + typeRecipes.size(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.category", Map.of("category_name", categoryName)), + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.category", l, Map.of("category_name", categoryName)), type.getMaterial(), 1, - I18n.lore("gui_sbmenu.recipe.book.category.lore", Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); + I18n.lore("gui_sbmenu.recipe.book.category.lore", l, Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); }, (click, c) -> c.push(new GUIRecipeSlayers())); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeCategory.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeCategory.java index 6023ced02..7ae4024ee 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeCategory.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeCategory.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -46,7 +47,7 @@ public GUIRecipeCategory(SkyBlockRecipe.RecipeType type) { @Override public ViewConfiguration configuration() { return ViewConfiguration.withString( - (state, ctx) -> I18n.string("gui_sbmenu.recipe.category.title", Map.of("page", String.valueOf(state.page() + 1), "max_page", String.valueOf(Math.max(1, (int) Math.ceil((double) getFilteredItems(state).size() / PAGINATED_SLOTS.length))), "category_name", StringUtility.toNormalCase(type.name()))), + (state, ctx) -> I18n.string("gui_sbmenu.recipe.category.title", ctx.player().getLocale(), Map.of("page", String.valueOf(state.page() + 1), "max_page", String.valueOf(Math.max(1, (int) Math.ceil((double) getFilteredItems(state).size() / PAGINATED_SLOTS.length))), "category_name", StringUtility.toNormalCase(type.name()))), InventoryType.CHEST_6_ROW ); } @@ -59,6 +60,7 @@ protected int[] getPaginatedSlots() { @Override protected ItemStack.Builder renderItem(SkyBlockRecipe item, int index, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = player.getLocale(); SkyBlockRecipe.CraftingResult result = item.getCanCraft().apply(player); ItemStack.Builder itemStack = PlayerItemUpdater.playerUpdate( player, item.getResult().getItemStack() @@ -69,7 +71,7 @@ protected ItemStack.Builder renderItem(SkyBlockRecipe item, int index, Hypixe Objects.requireNonNull(itemStack.build().get(DataComponents.LORE)).stream().map(StringUtility::getTextFromComponent).toList() ); lore.add("§e "); - lore.add(I18n.string("gui_sbmenu.recipe.category.click_to_view")); + lore.add(I18n.string("gui_sbmenu.recipe.category.click_to_view", l)); return itemStack.set(DataComponents.LORE, lore.stream().map(line -> Component.text(line).decoration(TextDecoration.ITALIC, false)) @@ -77,7 +79,7 @@ protected ItemStack.Builder renderItem(SkyBlockRecipe item, int index, Hypixe } else { List lore = Arrays.asList(result.errorMessage()); lore = lore.stream().map(line -> "§7" + line).toList(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.category.locked"), Material.GRAY_DYE, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.category.locked", l), Material.GRAY_DYE, 1, lore); } } @@ -89,7 +91,7 @@ protected void onItemClick(ClickContext click, ViewContext if (result.allowed()) { ctx.push(new GUIRecipe(item.getResult().getAttributeHandler().getPotentialType())); } else { - player.sendMessage(I18n.string("gui_sbmenu.recipe.category.msg.not_unlocked")); + player.sendMessage(I18n.string("gui_sbmenu.recipe.category.msg.not_unlocked", player.getLocale())); } } @@ -110,6 +112,7 @@ protected void layoutCustom(ViewLayout layout, RecipeCatego // Title item layout.slot(4, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); ArrayList> typeRecipes = new ArrayList<>(); ArrayList> allowedRecipes = new ArrayList<>(); @@ -141,9 +144,9 @@ protected void layoutCustom(ViewLayout layout, RecipeCatego )); String progressBar = completedLoadingBar + uncompletedLoadingBar + "§r §e" + allowedRecipes.size() + "§6/§e" + typeRecipes.size(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.category.info", Map.of("category_name", categoryName)), + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.category.info", l, Map.of("category_name", categoryName)), type.getMaterial(), 1, - I18n.lore("gui_sbmenu.recipe.category.info.lore", Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); + I18n.lore("gui_sbmenu.recipe.category.info.lore", l, Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); }); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeSlayers.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeSlayers.java index 538a21fe8..38c144d03 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeSlayers.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUIRecipeSlayers.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIRecipeSlayers extends StatelessView { @@ -30,7 +31,7 @@ public class GUIRecipeSlayers extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.recipe.slayers.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.recipe.slayers.title", InventoryType.CHEST_6_ROW); } @Override @@ -46,6 +47,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont // Title item layout.slot(4, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); SkyBlockRecipe.RecipeType type = SkyBlockRecipe.RecipeType.SLAYER; @@ -81,9 +83,9 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont )); String progressBar = completedLoadingBar + uncompletedLoadingBar + "§r §e" + allowedRecipes.size() + "§6/§e" + typeRecipes.size(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.category", Map.of("category_name", categoryName)), + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.category", l, Map.of("category_name", categoryName)), type.getMaterial(), 1, - I18n.lore("gui_sbmenu.recipe.book.category.lore", Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); + I18n.lore("gui_sbmenu.recipe.book.category.lore", l, Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); }); // Category items @@ -93,6 +95,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(slot, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); ArrayList typeRecipes = new ArrayList<>(); ArrayList allowedRecipes = new ArrayList<>(); @@ -126,9 +129,9 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont )); String progressBar = completedLoadingBar + uncompletedLoadingBar + "§r §e" + allowedRecipes.size() + "§6/§e" + typeRecipes.size(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.category", Map.of("category_name", categoryName)), + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.category", l, Map.of("category_name", categoryName)), type.getMaterial(), 1, - I18n.lore("gui_sbmenu.recipe.book.category.lore", Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); + I18n.lore("gui_sbmenu.recipe.book.category.lore", l, Map.of("category_name", categoryName, "percent", unlockedPercentage, "progress_bar", progressBar))); }, (_, c) -> c.push(new GUIRecipeCategory(type), GUIRecipeCategory.createInitialState((SkyBlockPlayer) c.player(), type))); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUISearchRecipe.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUISearchRecipe.java index 709a649b5..9b69f3eee 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUISearchRecipe.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/recipe/GUISearchRecipe.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; @@ -46,6 +47,7 @@ protected int[] getPaginatedSlots() { @Override protected ItemStack.Builder renderItem(SkyBlockRecipe item, int index, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = player.getLocale(); SkyBlockRecipe.CraftingResult result = item.getCanCraft().apply(player); ItemStack.Builder itemStack = PlayerItemUpdater.playerUpdate( player, item.getResult().getItemStack() @@ -56,7 +58,7 @@ protected ItemStack.Builder renderItem(SkyBlockRecipe item, int index, Hypixe itemStack.build().get(DataComponents.LORE).stream().map(StringUtility::getTextFromComponent).toList() ); lore.add("§e "); - lore.add(I18n.string("gui_sbmenu.recipe.category.click_to_view")); + lore.add(I18n.string("gui_sbmenu.recipe.category.click_to_view", l)); return itemStack.set(DataComponents.LORE, lore.stream().map(line -> Component.text(line).decoration(TextDecoration.ITALIC, false)) @@ -64,7 +66,7 @@ protected ItemStack.Builder renderItem(SkyBlockRecipe item, int index, Hypixe } else { List lore = Arrays.asList(result.errorMessage()); lore = lore.stream().map(line -> "§7" + line).toList(); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.category.locked"), Material.GRAY_DYE, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.category.locked", l), Material.GRAY_DYE, 1, lore); } } @@ -76,7 +78,7 @@ protected void onItemClick(ClickContext click, ViewContext ctx, Sky if (result.allowed()) { ctx.push(new GUIRecipe(item.getResult().getAttributeHandler().getPotentialType())); } else { - player.sendMessage(I18n.string("gui_sbmenu.recipe.category.msg.not_unlocked")); + player.sendMessage(I18n.string("gui_sbmenu.recipe.category.msg.not_unlocked", player.getLocale())); } } @@ -86,9 +88,12 @@ public void layout(ViewLayout layout, SearchState state, ViewContex Components.back(layout, 48, ctx); Components.close(layout, 49); - layout.slot(50, (_, _) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.search"), Material.OAK_SIGN, 1, - I18n.lore("gui_sbmenu.recipe.book.search.lore")), (_, c) -> { - new HypixelSignGUI(c.player()).open(new String[]{I18n.string("gui_sbmenu.recipe.search.sign_prompt")}).thenAccept(line -> { + layout.slot(50, (_, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.book.search", l), Material.OAK_SIGN, 1, + I18n.lore("gui_sbmenu.recipe.book.search.lore", l)); + }, (_, c) -> { + new HypixelSignGUI(c.player()).open(new String[]{I18n.string("gui_sbmenu.recipe.search.sign_prompt", c.player().getLocale())}).thenAccept(line -> { if (line == null) { return; } @@ -99,8 +104,11 @@ public void layout(ViewLayout layout, SearchState state, ViewContex // if no results if (state.items().isEmpty()) { - layout.slot(22, (searchState, _) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.search.no_results"), Material.BARRIER, 1, - I18n.lore("gui_sbmenu.recipe.search.no_results.lore", Map.of("query", searchState.query())))); + layout.slot(22, (searchState, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.recipe.search.no_results", l), Material.BARRIER, 1, + I18n.lore("gui_sbmenu.recipe.search.no_results.lore", l, Map.of("query", searchState.query()))); + }); } } @@ -111,7 +119,7 @@ protected boolean shouldFilterFromSearch(SearchState state, SkyBlockRecipe it @Override public ViewConfiguration configuration() { - return ViewConfiguration.withString((state, ctx) -> I18n.string("gui_sbmenu.recipe.search.title", Map.of("query", state.query(), "page", String.valueOf(state.page() + 1), "max_page", String.valueOf(Math.max(1, (int) Math.ceil((double) state.items().size() / DEFAULT_SLOTS.length))))), InventoryType.CHEST_6_ROW); + return ViewConfiguration.withString((state, ctx) -> I18n.string("gui_sbmenu.recipe.search.title", ctx.player().getLocale(), Map.of("query", state.query(), "page", String.valueOf(state.page() + 1), "max_page", String.valueOf(Math.max(1, (int) Math.ceil((double) state.items().size() / DEFAULT_SLOTS.length))))), InventoryType.CHEST_6_ROW); } public static SearchState createInitialState(String query) { diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/skills/GUISkillCategory.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/skills/GUISkillCategory.java index fc9ade475..f11a641e5 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/skills/GUISkillCategory.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/skills/GUISkillCategory.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUISkillCategory extends StatelessView { @@ -33,7 +34,9 @@ public GUISkillCategory(SkillCategories category, int page) { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.skills.category.title", Map.of("category_name", category.toString())), InventoryType.CHEST_6_ROW); + return ViewConfiguration.withString( + (state, ctx) -> I18n.string("gui_sbmenu.skills.category.title", ctx.player().getLocale(), Map.of("category_name", category.toString())), + InventoryType.CHEST_6_ROW); } @Override @@ -51,30 +54,32 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (category == SkillCategories.COMBAT && player.getToggles().get(DatapointToggles.Toggles.ToggleType.HAS_SPOKEN_TO_BRAMASS_BEASTSLAYER)) { layout.slot(39, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); ArrayList lore = new ArrayList<>(); p.getBestiaryData().getTotalDisplay(lore); lore.add(""); - lore.add(I18n.string("gui_sbmenu.skills.category.bestiary.click")); - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.skills.category.bestiary"), Material.WRITTEN_BOOK, 1, lore); + lore.add(I18n.string("gui_sbmenu.skills.category.bestiary.click", l)); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.skills.category.bestiary", l), Material.WRITTEN_BOOK, 1, lore); }, (click, c) -> c.push(new GUIBestiary())); } // Skill info layout.slot(0, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); List lore = new ArrayList<>(category.asCategory().getDescription()); lore.add(" "); Integer next = p.getSkills().getNextLevel(category); if (next == null) { - lore.add(I18n.string("gui_sbmenu.skills.category.max_level")); + lore.add(I18n.string("gui_sbmenu.skills.category.max_level", l)); } else { p.getSkills().getDisplay(lore, category, category.asCategory().getReward(next).requirement(), "§7Progress to Level " + StringUtility.getAsRomanNumeral(next) + ": "); } lore.add(" "); - lore.addAll(I18n.lore("gui_sbmenu.skills.category.increase_level", Map.of("category_name", category.toString()))); + lore.addAll(I18n.lore("gui_sbmenu.skills.category.increase_level", l, Map.of("category_name", category.toString()))); return ItemStackCreator.getStack("§a" + category + " Skill", category.asCategory().getDisplayIcon(), 1, lore); @@ -84,15 +89,21 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont // Next page button if (rewards.size() > (page + 1) * DISPLAY_SLOTS.length) { - layout.slot(50, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.skills.category.next_page"), Material.ARROW, 1, - I18n.lore("gui_sbmenu.skills.category.next_page.lore")), + layout.slot(50, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.skills.category.next_page", l), Material.ARROW, 1, + I18n.lore("gui_sbmenu.skills.category.next_page.lore", l)); + }, (click, c) -> c.replace(new GUISkillCategory(category, page + 1))); } // Previous page button if (page > 0) { - layout.slot(48, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.skills.category.previous_page"), Material.ARROW, 1, - I18n.lore("gui_sbmenu.skills.category.previous_page.lore")), + layout.slot(48, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.skills.category.previous_page", l), Material.ARROW, 1, + I18n.lore("gui_sbmenu.skills.category.previous_page.lore", l)); + }, (click, c) -> c.replace(new GUISkillCategory(category, page - 1))); } @@ -107,6 +118,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(slot, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); int currentLevel = p.getSkills().getCurrentLevel(category); List lore = new ArrayList<>(); reward.getDisplay(lore); @@ -118,7 +130,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont icon = Material.LIME_STAINED_GLASS_PANE; colour = "§a"; lore.add(" "); - lore.add(I18n.string("gui_sbmenu.skills.category.unlocked")); + lore.add(I18n.string("gui_sbmenu.skills.category.unlocked", l)); } else if ((currentLevel + 1) == reward.level()) { icon = Material.YELLOW_STAINED_GLASS_PANE; colour = "§e"; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/skills/GUISkills.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/skills/GUISkills.java index 814ff00c7..2364377f4 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/skills/GUISkills.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/skills/GUISkills.java @@ -12,6 +12,7 @@ import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import java.util.ArrayList; +import java.util.Locale; public class GUISkills extends StatelessView { private static final int[] DISPLAY_SLOTS = { @@ -21,7 +22,7 @@ public class GUISkills extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.skills.main.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.skills.main.title", InventoryType.CHEST_6_ROW); } @Override @@ -30,8 +31,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.close(layout, 49); Components.back(layout, 48, ctx); - layout.slot(4, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.skills.main.info"), Material.DIAMOND_SWORD, 1, - I18n.lore("gui_sbmenu.skills.main.info.lore"))); + layout.slot(4, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.skills.main.info", l), Material.DIAMOND_SWORD, 1, + I18n.lore("gui_sbmenu.skills.main.info.lore", l)); + }); SkillCategories[] allCategories = SkillCategories.values(); for (int i = 0; i < DISPLAY_SLOTS.length && i < allCategories.length; i++) { @@ -41,10 +45,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(slot, (s, c) -> { SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); ArrayList lore = new ArrayList<>(); if (category == SkillCategories.CARPENTRY && !player.getMissionData().hasCompleted("give_wool_to_carpenter")) { - lore.addAll(I18n.lore("gui_sbmenu.skills.main.carpentry_locked.lore")); + lore.addAll(I18n.lore("gui_sbmenu.skills.main.carpentry_locked.lore", l)); } else { lore.addAll(skillCategory.getDescription()); lore.add(" "); @@ -61,11 +66,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont reward.getDisplay(lore); } else { - lore.add(I18n.string("gui_sbmenu.skills.main.max_level")); + lore.add(I18n.string("gui_sbmenu.skills.main.max_level", l)); } lore.add(" "); - lore.add(I18n.string("gui_sbmenu.skills.main.click_to_view")); + lore.add(I18n.string("gui_sbmenu.skills.main.click_to_view", l)); } return ItemStackCreator.getStack( diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorage.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorage.java index 527179a7c..ca4dafeb7 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorage.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorage.java @@ -19,13 +19,14 @@ import net.swofty.type.skyblockgeneric.item.updater.PlayerItemUpdater; import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import java.util.Locale; import java.util.Map; public class GUIStorage extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_sbmenu.storage.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_sbmenu.storage.title", InventoryType.CHEST_6_ROW); } @Override @@ -34,11 +35,17 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.back(layout, 48, ctx); Components.close(layout, 49); - layout.slot(4, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.ender_chest"), Material.ENDER_CHEST, 1, - I18n.lore("gui_sbmenu.storage.ender_chest.lore"))); + layout.slot(4, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.ender_chest", l), Material.ENDER_CHEST, 1, + I18n.lore("gui_sbmenu.storage.ender_chest.lore", l)); + }); - layout.slot(22, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.backpacks"), Material.CHEST, 1, - I18n.lore("gui_sbmenu.storage.backpacks.lore"))); + layout.slot(22, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.backpacks", l), Material.CHEST, 1, + I18n.lore("gui_sbmenu.storage.backpacks.lore", l)); + }); SkyBlockPlayer player = (SkyBlockPlayer) ctx.player(); DatapointStorage.PlayerStorage storage = player.getSkyblockDataHandler().get( @@ -55,19 +62,20 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(enderSlot, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); DatapointStorage.PlayerStorage playerStorage = p.getSkyblockDataHandler().get( SkyBlockDataHandler.Data.STORAGE, DatapointStorage.class ).getValue(); if (!playerStorage.hasPage(page)) - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.locked_page"), Material.RED_STAINED_GLASS_PANE, 1, - I18n.lore("gui_sbmenu.storage.locked_page.lore")); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.locked_page", l), Material.RED_STAINED_GLASS_PANE, 1, + I18n.lore("gui_sbmenu.storage.locked_page.lore", l)); Material material = playerStorage.getPage(page).display; - return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.ender_chest_page", Map.of("page", String.valueOf(page))), + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.ender_chest_page", l, Map.of("page", String.valueOf(page))), material, page, - I18n.lore("gui_sbmenu.storage.ender_chest_page.lore")); + I18n.lore("gui_sbmenu.storage.ender_chest_page.lore", l)); }, (click, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); DatapointStorage.PlayerStorage playerStorage = p.getSkyblockDataHandler().get( @@ -94,16 +102,22 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont int slot = backpackSlot - 26; if (backpacks.getUnlockedSlots() < slot) { - layout.slot(backpackSlot, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.locked_backpack", Map.of("slot", String.valueOf(slot))), + layout.slot(backpackSlot, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.locked_backpack", l, Map.of("slot", String.valueOf(slot))), Material.GRAY_DYE, 1, - I18n.lore("gui_sbmenu.storage.locked_backpack.lore"))); + I18n.lore("gui_sbmenu.storage.locked_backpack.lore", l)); + }); continue; } if (!backpackItems.containsKey(slot)) { - layout.slot(backpackSlot, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.empty_backpack", Map.of("slot", String.valueOf(slot))), + layout.slot(backpackSlot, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.empty_backpack", l, Map.of("slot", String.valueOf(slot))), Material.BROWN_STAINED_GLASS_PANE, slot, - I18n.lore("gui_sbmenu.storage.empty_backpack.lore")), + I18n.lore("gui_sbmenu.storage.empty_backpack.lore", l)); + }, (click, c) -> handleEmptyBackpackSlotClick(click, c, slot)); continue; } @@ -112,12 +126,13 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont layout.slot(backpackSlot, (s, c) -> { SkyBlockPlayer p = (SkyBlockPlayer) c.player(); + Locale l = p.getLocale(); String itemName = item.getAttributeHandler().getRarity().getColor() + item.getAttributeHandler().getPotentialType().getDisplayName(); String slots = String.valueOf(item.getComponent(BackpackComponent.class).getRows() * 9); - return ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_slot", Map.of("slot", String.valueOf(slot))), + return ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_slot", l, Map.of("slot", String.valueOf(slot))), item.getComponent(SkullHeadComponent.class).getSkullTexture(item), slot, - I18n.lore("gui_sbmenu.storage.backpack_slot.lore", Map.of( + I18n.lore("gui_sbmenu.storage.backpack_slot.lore", l, Map.of( "item_name", itemName, "slots", slots ))); @@ -134,11 +149,11 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont && !backpackItem.getAttributeHandler().getBackpackData().items() .stream() .map(SkyBlockItem::new).allMatch(SkyBlockItem::isNA)) { - p.sendMessage(I18n.string("gui_sbmenu.storage.msg.not_empty", Map.of("slot", String.valueOf(slot)))); + p.sendMessage(I18n.string("gui_sbmenu.storage.msg.not_empty", p.getLocale(), Map.of("slot", String.valueOf(slot)))); return; } - p.sendMessage(I18n.string("gui_sbmenu.storage.msg.removed", Map.of("slot", String.valueOf(slot)))); + p.sendMessage(I18n.string("gui_sbmenu.storage.msg.removed", p.getLocale(), Map.of("slot", String.valueOf(slot)))); p.getInventory().setCursorItem(PlayerItemUpdater.playerUpdate(p, backpackItem.getItemStack()).build()); playerBackpackItems.remove(slot); @@ -168,8 +183,9 @@ private void handleEmptyBackpackSlotClick(ClickContext click, View new DatapointBackpacks.PlayerBackpacks(backpackItems, backpacks.getUnlockedSlots()) ); - player.sendMessage(I18n.string("gui_sbmenu.storage.msg.placing", Map.of("slot", String.valueOf(slot)))); - player.sendMessage(I18n.string("gui_sbmenu.storage.msg.success")); + Locale l = player.getLocale(); + player.sendMessage(I18n.string("gui_sbmenu.storage.msg.placing", l, Map.of("slot", String.valueOf(slot)))); + player.sendMessage(I18n.string("gui_sbmenu.storage.msg.success", l)); player.getInventory().setCursorItem(ItemStack.AIR); ctx.session(DefaultState.class).refresh(); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorageBackpackPage.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorageBackpackPage.java index 0765b1b44..84e40a034 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorageBackpackPage.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorageBackpackPage.java @@ -52,15 +52,18 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.close(layout, 0); - layout.slot(1, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.backpack_page.go_back"), Material.ARROW, 1, - I18n.lore("gui_sbmenu.storage.backpack_page.go_back.lore")), + layout.slot(1, (s, c) -> { + java.util.Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.backpack_page.go_back", l), Material.ARROW, 1, + I18n.lore("gui_sbmenu.storage.backpack_page.go_back.lore", l)); + }, (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); c.player().openView(new GUIStorage()); }); if (page != data.getHighestBackpackSlot()) { - layout.slot(8, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_page.last_page"), + layout.slot(8, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_page.last_page", c.player().getLocale()), "1ceb50d0d79b9fb790a7392660bc296b7ad2f856c5cbe1c566d99cfec191e668"), (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); @@ -72,7 +75,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont }); if (data.getBackpacks().containsKey(page + 1)) { - layout.slot(7, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_page.next_page"), + layout.slot(7, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_page.next_page", c.player().getLocale()), "848ca732a6e35dafd15e795ebc10efedd9ef58ff2df9b17af6e3d807bdc0708b"), (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); @@ -85,7 +88,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } if (page != data.getLowestBackpackSlot()) { - layout.slot(5, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_page.first_page"), + layout.slot(5, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_page.first_page", c.player().getLocale()), "8af22a97292de001079a5d98a0ae3a82c427172eabc370ed6d4a31c7e3a0024f"), (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); @@ -97,7 +100,7 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont }); if (data.getBackpacks().containsKey(page - 1)) { - layout.slot(6, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_page.previous_page"), + layout.slot(6, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.backpack_page.previous_page", c.player().getLocale()), "9c042597eda9f061794fe11dacf78926d247f9eea8ddef39dfbe6022989b8395"), (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorageIconSelection.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorageIconSelection.java index 2f6c429f6..cfa6b644f 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorageIconSelection.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStorageIconSelection.java @@ -38,7 +38,7 @@ public ViewConfiguration configuration() { return ViewConfiguration.withString( (state, ctx) -> { int totalPages = Math.max(1, (int) Math.ceil((double) getFilteredItems(state).size() / PAGINATED_SLOTS.length)); - return I18n.string("gui_sbmenu.storage.icon.title", Map.of("page", String.valueOf(state.page() + 1), "max_page", String.valueOf(totalPages))); + return I18n.string("gui_sbmenu.storage.icon.title", ctx.player().getLocale(), Map.of("page", String.valueOf(state.page() + 1), "max_page", String.valueOf(totalPages))); }, InventoryType.CHEST_6_ROW ); @@ -72,11 +72,12 @@ protected int getPreviousPageSlot() { @Override protected ItemStack.Builder renderItem(Material item, int index, HypixelPlayer player) { + java.util.Locale l = player.getLocale(); return ItemStackCreator.getStack( - (item == Material.BARRIER ? I18n.string("gui_sbmenu.storage.icon.reset") : + (item == Material.BARRIER ? I18n.string("gui_sbmenu.storage.icon.reset", l) : StringUtility.toNormalCase(item.name().replace("minecraft:", ""))), item, 1, - I18n.lore("gui_sbmenu.storage.icon.lore")); + I18n.lore("gui_sbmenu.storage.icon.lore", l)); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStoragePage.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStoragePage.java index 0680f8258..4a0f491d9 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStoragePage.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/sbmenu/storage/GUIStoragePage.java @@ -30,7 +30,7 @@ public ViewConfiguration configuration() { SkyBlockPlayer player = (SkyBlockPlayer) ctx.player(); int highestPage = player.getSkyblockDataHandler().get(SkyBlockDataHandler.Data.STORAGE, DatapointStorage.class) .getValue().getHighestPage(); - return I18n.string("gui_sbmenu.storage.page.title", Map.of("page", String.valueOf(page), "max_page", String.valueOf(highestPage))); + return I18n.string("gui_sbmenu.storage.page.title", player.getLocale(), Map.of("page", String.valueOf(page), "max_page", String.valueOf(highestPage))); }, InventoryType.CHEST_6_ROW ); @@ -49,19 +49,22 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont Components.close(layout, 0); - layout.slot(1, (s, c) -> ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.page.go_back"), Material.ARROW, 1, - I18n.lore("gui_sbmenu.storage.page.go_back.lore")), + layout.slot(1, (s, c) -> { + java.util.Locale l = c.player().getLocale(); + return ItemStackCreator.getStack(I18n.string("gui_sbmenu.storage.page.go_back", l), Material.ARROW, 1, + I18n.lore("gui_sbmenu.storage.page.go_back.lore", l)); + }, (_, c) -> c.player().openView(new GUIStorage())); if (page != highestPage) { - layout.slot(8, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.page.last_page"), + layout.slot(8, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.page.last_page", c.player().getLocale()), "1ceb50d0d79b9fb790a7392660bc296b7ad2f856c5cbe1c566d99cfec191e668"), (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); c.player().openView(new GUIStoragePage(highestPage)); }); - layout.slot(7, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.page.next_page"), + layout.slot(7, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.page.next_page", c.player().getLocale()), "848ca732a6e35dafd15e795ebc10efedd9ef58ff2df9b17af6e3d807bdc0708b"), (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); @@ -70,14 +73,14 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } if (page != 1) { - layout.slot(5, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.page.first_page"), + layout.slot(5, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.page.first_page", c.player().getLocale()), "8af22a97292de001079a5d98a0ae3a82c427172eabc370ed6d4a31c7e3a0024f"), (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); c.player().openView(new GUIStoragePage(1)); }); - layout.slot(6, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.page.previous_page"), + layout.slot(6, (s, c) -> ItemStackCreator.getStackHead(I18n.string("gui_sbmenu.storage.page.previous_page", c.player().getLocale()), "9c042597eda9f061794fe11dacf78926d247f9eea8ddef39dfbe6022989b8395"), (click, c) -> { saveItems((SkyBlockPlayer) c.player(), c); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/shop/ConfirmBuyView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/shop/ConfirmBuyView.java index 8df23564d..fd61a4450 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/shop/ConfirmBuyView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/shop/ConfirmBuyView.java @@ -6,6 +6,7 @@ import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.Components; import net.swofty.type.generic.gui.v2.View; import net.swofty.type.generic.gui.v2.ViewConfiguration; @@ -16,13 +17,14 @@ import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import java.util.ArrayList; +import java.util.Locale; import java.util.Map; public final class ConfirmBuyView implements View { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_shop.confirm_buy.title"), InventoryType.CHEST_3_ROW); + return ViewConfiguration.translatable("gui_shop.confirm_buy.title", InventoryType.CHEST_3_ROW); } @Override @@ -30,33 +32,35 @@ public void layout(ViewLayout layout, State state, ViewContext ctx) { Components.fill(layout); layout.slot(12, - (_, __) -> { - ArrayList lore = new ArrayList<>(I18n.lore("gui_shop.confirm_buy.confirm_button.lore", Map.of( + (s, c) -> { + Locale l = c.player().getLocale(); + ArrayList lore = new ArrayList<>(I18n.lore("gui_shop.confirm_buy.confirm_button.lore", l, Map.of( "item_name", state.item.getDisplayName(), "cost", StringUtility.commaify(state.price) ))); - return ItemStackCreator.getStack(I18n.string("gui_shop.confirm_buy.confirm_button"), Material.LIME_TERRACOTTA, 1, lore); + return ItemStackCreator.getStack(I18n.string("gui_shop.confirm_buy.confirm_button", l), Material.LIME_TERRACOTTA, 1, lore); }, (click, c) -> { if (!(click.click() instanceof Click.Left || click.click() instanceof Click.Right)) return; SkyBlockPlayer player = (SkyBlockPlayer) c.player(); + Locale l = player.getLocale(); if (player.getCoins() >= state.price) { player.addAndUpdateItem(state.item); player.removeCoins(state.price); - player.sendMessage(I18n.string("gui_shop.confirm_buy.bought_message", Map.of( + player.sendMessage(I18n.string("gui_shop.confirm_buy.bought_message", l, Map.of( "item_name", state.item.getDisplayName(), "cost", String.valueOf(state.price) ))); } else { - player.sendMessage(I18n.string("gui_shop.confirm_buy.not_enough_coins")); + player.sendMessage(I18n.string("gui_shop.confirm_buy.not_enough_coins", l)); } player.closeInventory(); } ); layout.slot(16, - (_, __) -> ItemStackCreator.getStack(I18n.string("gui_shop.confirm_buy.cancel_button"), Material.RED_TERRACOTTA, 1), + (s, c) -> TranslatableItemStackCreator.getStack(c.player(), "gui_shop.confirm_buy.cancel_button", Material.RED_TERRACOTTA, 1), (_, c) -> c.player().closeInventory() ); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/shop/TradingOptionsView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/shop/TradingOptionsView.java index 0c0ebeb9c..bb6dab70b 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/shop/TradingOptionsView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/shop/TradingOptionsView.java @@ -8,6 +8,7 @@ import net.minestom.server.item.ItemStack; import net.swofty.commons.StringUtility; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.v2.Components; import net.swofty.type.generic.gui.v2.View; import net.swofty.type.generic.gui.v2.ViewConfiguration; @@ -22,13 +23,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public final class TradingOptionsView implements View { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>(I18n.string("gui_shop.trading_options.title"), InventoryType.CHEST_6_ROW); + return ViewConfiguration.translatable("gui_shop.trading_options.title", InventoryType.CHEST_6_ROW); } @Override @@ -54,14 +56,15 @@ private ItemStack.Builder createTradeItem(ShopView.ShopItem item, int amount, Sk List lore = new ArrayList<>((existingLoreComponents == null ? List.of() : existingLoreComponents) .stream().map(StringUtility::getTextFromComponent).toList()); + Locale l = player.getLocale(); lore.add(""); - lore.add(I18n.string("gui_shop.trading_options.cost_label")); + lore.add(I18n.string("gui_shop.trading_options.cost_label", l)); lore.addAll(totalPrice.getGUIDisplay()); lore.add(""); - lore.add(I18n.string("gui_shop.trading_options.stock_label")); - lore.add(I18n.string("gui_shop.trading_options.stock_remaining", Map.of("count", String.valueOf(player.getShoppingData().getStock(item.getItem().toUnderstandable()))))); + lore.add(I18n.string("gui_shop.trading_options.stock_label", l)); + lore.add(I18n.string("gui_shop.trading_options.stock_remaining", l, Map.of("count", String.valueOf(player.getShoppingData().getStock(item.getItem().toUnderstandable()))))); lore.add(""); - lore.add(I18n.string("gui_shop.trading_options.click_to_purchase")); + lore.add(I18n.string("gui_shop.trading_options.click_to_purchase", l)); Component baseName = itemStack.build().get(DataComponents.CUSTOM_NAME); if (baseName == null) { @@ -76,14 +79,15 @@ private ItemStack.Builder createTradeItem(ShopView.ShopItem item, int amount, Sk private void attemptBuy(State state, int amount, ViewContext ctx) { SkyBlockPlayer player = (SkyBlockPlayer) ctx.player(); + Locale l = player.getLocale(); if (!player.getShoppingData().canPurchase(state.item.getItem().toUnderstandable(), amount)) { - player.sendMessage(I18n.string("gui_shop.trading_options.max_reached")); + player.sendMessage(I18n.string("gui_shop.trading_options.max_reached", l)); return; } ShopPrice totalPrice = state.stackPrice.multiply(amount); if (!totalPrice.canAfford(player)) { - player.sendMessage(I18n.string("gui_shop.trading_options.not_enough", Map.of("currency", state.stackPrice.getNamePlural()))); + player.sendMessage(I18n.string("gui_shop.trading_options.not_enough", l, Map.of("currency", state.stackPrice.getNamePlural()))); return; } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/stash/GUIStashItem.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/stash/GUIStashItem.java index e443ceb1e..fd91405a1 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/stash/GUIStashItem.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/stash/GUIStashItem.java @@ -7,6 +7,7 @@ import net.minestom.server.item.Material; import net.swofty.type.generic.gui.inventory.HypixelPaginatedGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; @@ -17,6 +18,7 @@ import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIStashItem extends HypixelPaginatedGUI { @@ -63,11 +65,12 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; e.setCancelled(true); + Locale l = player.getLocale(); DatapointStash.PlayerStash stash = player.getStash(); int pickedUp = 0; if (stash.getItemStashCount() == 0) { - player.sendMessage(I18n.string("gui_stash.item.empty_message")); + player.sendMessage(I18n.string("gui_stash.item.empty_message", l)); return; } @@ -75,17 +78,17 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockItem removed = stash.removeFromItemStash(0); if (removed != null) { player.addAndUpdateItem(removed); - player.sendMessage(I18n.string("gui_stash.item.from_stash", Map.of("item_name", removed.getDisplayName()))); + player.sendMessage(I18n.string("gui_stash.item.from_stash", l, Map.of("item_name", removed.getDisplayName()))); pickedUp++; } } if (pickedUp == 0) { - player.sendMessage(I18n.string("gui_stash.item.inventory_full")); + player.sendMessage(I18n.string("gui_stash.item.inventory_full", l)); } else if (stash.getItemStashCount() == 0) { - player.sendMessage(I18n.string("gui_stash.item.all_picked_up")); + player.sendMessage(I18n.string("gui_stash.item.all_picked_up", l)); } else { - player.sendMessage(I18n.string("gui_stash.item.remaining", Map.of("count", String.valueOf(stash.getItemStashCount())))); + player.sendMessage(I18n.string("gui_stash.item.remaining", l, Map.of("count", String.valueOf(stash.getItemStashCount())))); } player.closeInventory(); @@ -95,8 +98,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; int count = player.getStash().getItemStashCount(); - return ItemStackCreator.getStack(I18n.string("gui_stash.item.fill_inventory"), Material.EMERALD, 1, - I18n.lore("gui_stash.item.fill_inventory.lore", Map.of("count", String.valueOf(count)))); + return TranslatableItemStackCreator.getStack(p, "gui_stash.item.fill_inventory", Material.EMERALD, 1, + "gui_stash.item.fill_inventory.lore", Map.of("count", String.valueOf(count))); } }); @@ -112,10 +115,11 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public String getTitle(HypixelPlayer player, String query, int page, PaginationList paged) { int maxPage = paged.getPageCount(); + Locale l = player.getLocale(); if (maxPage <= 1) { - return I18n.string("gui_stash.item.title"); + return I18n.string("gui_stash.item.title", l); } - return I18n.string("gui_stash.item.title_paged", Map.of("page", String.valueOf(page), "max_page", String.valueOf(maxPage))); + return I18n.string("gui_stash.item.title_paged", l, Map.of("page", String.valueOf(page), "max_page", String.valueOf(maxPage))); } @Override @@ -130,9 +134,10 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; e.setCancelled(true); + Locale l = player.getLocale(); // Check if player has inventory space if (!player.hasEmptySlots(1)) { - player.sendMessage(I18n.string("gui_stash.item.inventory_full")); + player.sendMessage(I18n.string("gui_stash.item.inventory_full", l)); return; } @@ -149,12 +154,12 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockItem removed = player.getStash().removeFromItemStash(currentIndex); if (removed != null) { player.addAndUpdateItem(removed); - player.sendMessage(I18n.string("gui_stash.item.from_stash", Map.of("item_name", removed.getDisplayName()))); + player.sendMessage(I18n.string("gui_stash.item.from_stash", l, Map.of("item_name", removed.getDisplayName()))); if (player.getStash().getItemStashCount() == 0) { - player.sendMessage(I18n.string("gui_stash.item.all_picked_up")); + player.sendMessage(I18n.string("gui_stash.item.all_picked_up", l)); } else { - player.sendMessage(I18n.string("gui_stash.item.remaining", Map.of("count", String.valueOf(player.getStash().getItemStashCount())))); + player.sendMessage(I18n.string("gui_stash.item.remaining", l, Map.of("count", String.valueOf(player.getStash().getItemStashCount())))); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/stash/GUIStashMaterial.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/stash/GUIStashMaterial.java index e5e63f152..eb25b4346 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/stash/GUIStashMaterial.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/stash/GUIStashMaterial.java @@ -9,6 +9,7 @@ import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.generic.gui.inventory.HypixelPaginatedGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.TranslatableItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; @@ -20,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class GUIStashMaterial extends HypixelPaginatedGUI> { @@ -64,6 +66,7 @@ public void performSearch(HypixelPlayer p, String query, int page, int maxPage) @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = player.getLocale(); e.setCancelled(true); DatapointStash.PlayerStash stash = player.getStash(); @@ -81,7 +84,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockItem newItem = new SkyBlockItem(type); newItem.setAmount(removed); player.addAndUpdateItem(newItem); - player.sendMessage(I18n.string("gui_stash.material.from_stash", Map.of("item_name", type.getDisplayName(), "amount", String.valueOf(removed)))); + player.sendMessage(I18n.string("gui_stash.material.from_stash", l, Map.of("item_name", type.getDisplayName(), "amount", String.valueOf(removed)))); pickedUp += removed; amount -= removed; } else { @@ -93,11 +96,11 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { } if (pickedUp == 0) { - player.sendMessage(I18n.string("gui_stash.material.inventory_full")); + player.sendMessage(I18n.string("gui_stash.material.inventory_full", l)); } else if (stash.getMaterialStashCount() == 0) { - player.sendMessage(I18n.string("gui_stash.material.all_picked_up")); + player.sendMessage(I18n.string("gui_stash.material.all_picked_up", l)); } else { - player.sendMessage(I18n.string("gui_stash.material.remaining", Map.of( + player.sendMessage(I18n.string("gui_stash.material.remaining", l, Map.of( "count", String.valueOf(stash.getMaterialStashCount()), "types", String.valueOf(stash.getMaterialTypeCount())))); } @@ -110,10 +113,10 @@ public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; int count = player.getStash().getMaterialStashCount(); int types = player.getStash().getMaterialTypeCount(); - return ItemStackCreator.getStack(I18n.string("gui_stash.material.fill_inventory"), Material.EMERALD, 1, - I18n.lore("gui_stash.material.fill_inventory.lore", Map.of( + return TranslatableItemStackCreator.getStack(p, "gui_stash.material.fill_inventory", Material.EMERALD, 1, + "gui_stash.material.fill_inventory.lore", Map.of( "count", StringUtility.commaify(count), - "types", String.valueOf(types)))); + "types", String.valueOf(types))); } }); @@ -122,6 +125,7 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = player.getLocale(); e.setCancelled(true); DatapointStash.PlayerStash stash = player.getStash(); @@ -138,9 +142,9 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { } if (inserted > 0) { - player.sendMessage(I18n.string("gui_stash.material.transferred_to_sacks")); + player.sendMessage(I18n.string("gui_stash.material.transferred_to_sacks", l)); } else { - player.sendMessage(I18n.string("gui_stash.material.no_transfer")); + player.sendMessage(I18n.string("gui_stash.material.no_transfer", l)); } new GUIStashMaterial().open(player, query, 1); @@ -148,8 +152,8 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { - return ItemStackCreator.getStack(I18n.string("gui_stash.material.insert_into_sacks"), Material.CHEST, 1, - I18n.lore("gui_stash.material.insert_into_sacks.lore")); + return TranslatableItemStackCreator.getStack(p, "gui_stash.material.insert_into_sacks", Material.CHEST, 1, + "gui_stash.material.insert_into_sacks.lore"); } }); @@ -165,10 +169,11 @@ public ItemStack.Builder getItem(HypixelPlayer p) { @Override public String getTitle(HypixelPlayer player, String query, int page, PaginationList> paged) { int maxPage = paged.getPageCount(); + Locale l = player.getLocale(); if (maxPage <= 1) { - return I18n.string("gui_stash.material.title"); + return I18n.string("gui_stash.material.title", l); } - return I18n.string("gui_stash.material.title_paged", Map.of("page", String.valueOf(page), "max_page", String.valueOf(maxPage))); + return I18n.string("gui_stash.material.title_paged", l, Map.of("page", String.valueOf(page), "max_page", String.valueOf(maxPage))); } @Override @@ -180,6 +185,7 @@ public GUIClickableItem createItemFor(Map.Entry entry, int sl @Override public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = player.getLocale(); e.setCancelled(true); int currentAmount = player.getStash().getMaterialStash().getOrDefault(itemType, 0); @@ -194,7 +200,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { // Check if player has inventory space if (!player.hasEmptySlots(1)) { - player.sendMessage(I18n.string("gui_stash.material.inventory_full")); + player.sendMessage(I18n.string("gui_stash.material.inventory_full", l)); return; } @@ -204,12 +210,12 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockItem newItem = new SkyBlockItem(itemType); newItem.setAmount(removed); player.addAndUpdateItem(newItem); - player.sendMessage(I18n.string("gui_stash.material.from_stash", Map.of("item_name", itemType.getDisplayName(), "amount", String.valueOf(removed)))); + player.sendMessage(I18n.string("gui_stash.material.from_stash", l, Map.of("item_name", itemType.getDisplayName(), "amount", String.valueOf(removed)))); if (player.getStash().getMaterialStashCount() == 0) { - player.sendMessage(I18n.string("gui_stash.material.all_picked_up")); + player.sendMessage(I18n.string("gui_stash.material.all_picked_up", l)); } else { - player.sendMessage(I18n.string("gui_stash.material.remaining", Map.of( + player.sendMessage(I18n.string("gui_stash.material.remaining", l, Map.of( "count", String.valueOf(player.getStash().getMaterialStashCount()), "types", String.valueOf(player.getStash().getMaterialTypeCount())))); } @@ -222,6 +228,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { @Override public ItemStack.Builder getItem(HypixelPlayer p) { SkyBlockPlayer player = (SkyBlockPlayer) p; + Locale l = player.getLocale(); int currentAmount = player.getStash().getMaterialStash().getOrDefault(itemType, amount); SkyBlockItem item = new SkyBlockItem(itemType); @@ -229,9 +236,9 @@ public ItemStack.Builder getItem(HypixelPlayer p) { ItemStack.Builder stack = new NonPlayerItemUpdater(item.getItemStack()).getUpdatedItem(); ArrayList lore = new ArrayList<>(item.getLore()); lore.add(""); - lore.add(I18n.string("gui_stash.material.amount_label", Map.of("amount", StringUtility.commaify(currentAmount)))); + lore.add(I18n.string("gui_stash.material.amount_label", l, Map.of("amount", StringUtility.commaify(currentAmount)))); lore.add(""); - lore.add(I18n.string("gui_stash.material.click_to_pickup")); + lore.add(I18n.string("gui_stash.material.click_to_pickup", l)); return ItemStackCreator.updateLore(stack, lore); } }; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/item/ItemLore.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/item/ItemLore.java index e92af3317..d47ac6f8e 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/item/ItemLore.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/item/ItemLore.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; @@ -49,6 +50,7 @@ public ItemLore(ItemStack stack) { @SneakyThrows public void updateLore(@Nullable SkyBlockPlayer player) { + Locale l = player != null ? player.getLocale() : Locale.US; SkyBlockItem item = new SkyBlockItem(stack); @Nullable ItemType type = item.getAttributeHandler().getPotentialType(); ItemAttributeHandler handler = item.getAttributeHandler(); @@ -74,18 +76,18 @@ public void updateLore(@Nullable SkyBlockPlayer player) { if (effectForName != null) { String effectDisplay = effectForName.getLevelDisplay(potionDataForName.getLevel()); if (potionDataForName.isSplash()) { - displayName = effectDisplay + " " + I18n.string("items.lore.splash_potion_suffix"); + displayName = effectDisplay + " " + I18n.string("items.lore.splash_potion_suffix", l); } else { - displayName = effectDisplay + " " + I18n.string("items.lore.potion_suffix"); + displayName = effectDisplay + " " + I18n.string("items.lore.potion_suffix", l); } } else if (handler.getPotentialType() != null) { - displayName = I18n.string("items." + handler.getPotentialType().name()); + displayName = I18n.string("items." + handler.getPotentialType().name(), l); } else { Material material = stack.material(); displayName = StringUtility.toNormalCase(material.key().value()); } } else if (handler.getPotentialType() != null) { - displayName = I18n.string("items." + handler.getPotentialType().name()); + displayName = I18n.string("items." + handler.getPotentialType().name(), l); } else { Material material = stack.material(); displayName = StringUtility.toNormalCase(material.key().value()); @@ -124,20 +126,20 @@ public void updateLore(@Nullable SkyBlockPlayer player) { underNameDisplay.getDisplays().forEach(line -> addLoreLine("§8" + line)); if (type != null && CollectionCategories.getCategory(type) != null) { - addLoreLine(I18n.string("items.lore.collection_item")); + addLoreLine(I18n.string("items.lore.collection_item", l)); } addLoreLine(null); } else { if (type != null && CollectionCategories.getCategory(type) != null) { - addLoreLine(I18n.string("items.lore.collection_item")); + addLoreLine(I18n.string("items.lore.collection_item", l)); addLoreLine(null); } } // Handle Item Statistics if (handler.isMiningTool()) { - addLoreLine(I18n.string("items.lore.breaking_power", Map.of("value", String.valueOf(handler.getBreakingPower())))); + addLoreLine(I18n.string("items.lore.breaking_power", l, Map.of("value", String.valueOf(handler.getBreakingPower())))); addLoreLine(null); } @@ -158,7 +160,7 @@ public void updateLore(@Nullable SkyBlockPlayer player) { if (item.hasComponent(ShortBowComponent.class)) { ShortBowComponent shortBowComponent = item.getComponent(ShortBowComponent.class); - addLoreLine(I18n.string("items.lore.shot_cooldown", Map.of("cooldown", String.valueOf(shortBowComponent.getCooldown())))); + addLoreLine(I18n.string("items.lore.shot_cooldown", l, Map.of("cooldown", String.valueOf(shortBowComponent.getCooldown())))); addNextLine = true; } @@ -292,7 +294,7 @@ public void updateLore(@Nullable SkyBlockPlayer player) { AbilityComponent abilityComponent = item.getComponent(AbilityComponent.class); abilityComponent.getAbilities().forEach(ability -> { - addLoreLine(I18n.string("items.lore.ability_label", Map.of("name", ability.getName(), "activation", ability.getActivation().getDisplay()))); + addLoreLine(I18n.string("items.lore.ability_label", l, Map.of("name", ability.getName(), "activation", ability.getActivation().getDisplay()))); for (String line : StringUtility.splitByWordAndLength(ability.getDescription().apply(player, item), 40)) addLoreLine("§7" + line); @@ -300,7 +302,7 @@ public void updateLore(@Nullable SkyBlockPlayer player) { if (costDisplay != null) addLoreLine(costDisplay); if (ability.getCooldownTicks() > 20) { - addLoreLine(I18n.string("items.lore.ability_cooldown", Map.of("cooldown", StringUtility.decimalify((double) ability.getCooldownTicks() / 20, 1)))); + addLoreLine(I18n.string("items.lore.ability_cooldown", l, Map.of("cooldown", StringUtility.decimalify((double) ability.getCooldownTicks() / 20, 1)))); } addLoreLine(null); @@ -333,13 +335,13 @@ public void updateLore(@Nullable SkyBlockPlayer player) { } } int totalPieces = ArmorSetRegistry.getPieceCount(ArmorSetRegistry.getArmorSet(armorSet.getClass())); - addLoreLine(I18n.string("items.lore.full_set_bonus", Map.of("name", armorSet.getName(), "wearing", String.valueOf(wearingAmount), "total", String.valueOf(totalPieces)))); + addLoreLine(I18n.string("items.lore.full_set_bonus", l, Map.of("name", armorSet.getName(), "wearing", String.valueOf(wearingAmount), "total", String.valueOf(totalPieces)))); armorSet.getDescription().forEach(line -> addLoreLine("§7" + line)); addLoreLine(null); } if (item.hasComponent(RightClickRecipeComponent.class)) { - addLoreLine(I18n.string("items.lore.right_click_recipes")); + addLoreLine(I18n.string("items.lore.right_click_recipes", l)); addLoreLine(null); } @@ -349,20 +351,20 @@ public void updateLore(@Nullable SkyBlockPlayer player) { } if (item.hasComponent(ReforgableComponent.class)) { - addLoreLine(I18n.string("items.lore.reforgeable")); + addLoreLine(I18n.string("items.lore.reforgeable", l)); if (handler.getReforge() != null) displayName = handler.getReforge().getPrefix() + " " + displayName; } ItemAttributeSoulbound.SoulBoundData bound = handler.getSoulBoundData(); if (bound != null) - addLoreLine(I18n.string("items.lore.soulbound", Map.of("prefix", bound.isCoopAllowed() ? I18n.string("items.lore.soulbound_coop_prefix") : ""))); + addLoreLine(I18n.string("items.lore.soulbound", l, Map.of("prefix", bound.isCoopAllowed() ? I18n.string("items.lore.soulbound_coop_prefix", l) : ""))); if (item.hasComponent(ArrowComponent.class)) { - addLoreLine(I18n.string("items.lore.stats_when_shot")); + addLoreLine(I18n.string("items.lore.stats_when_shot", l)); } if (item.hasComponent(NotFinishedYetComponent.class)) { - addLoreLine(I18n.string("items.lore.not_finished")); + addLoreLine(I18n.string("items.lore.not_finished", l)); addLoreLine(null); } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/tabmodules/AccountInformationModule.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/tabmodules/AccountInformationModule.java index 95fc84660..2191a899c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/tabmodules/AccountInformationModule.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/tabmodules/AccountInformationModule.java @@ -17,23 +17,25 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class AccountInformationModule extends TablistModule { public List getEntries(SkyBlockPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.account_info")), TablistSkinRegistry.ORANGE) + new TablistEntry(getCentered(I18n.string("tablist.module.account_info", l)), TablistSkinRegistry.ORANGE) )); SkyBlockDataHandler dataHandler = player.getSkyblockDataHandler(); DatapointBankData.BankData bankData = dataHandler.get(SkyBlockDataHandler.Data.BANK_DATA, DatapointBankData.class).getValue(); - entries.add(new TablistEntry(I18n.string("tablist.account_info.profile_label", Map.of( + entries.add(new TablistEntry(I18n.string("tablist.account_info.profile_label", l, Map.of( "profile_name", dataHandler.get(SkyBlockDataHandler.Data.PROFILE_NAME, DatapointString.class).getValue() )), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.account_info.pet_sitter"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.account_info.bank", Map.of( + entries.add(new TablistEntry(I18n.string("tablist.account_info.pet_sitter", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.account_info.bank", l, Map.of( "amount", StringUtility.shortenNumber(bankData.getAmount()), "limit", StringUtility.shortenNumber(bankData.getBalanceLimit()) )), TablistSkinRegistry.GRAY)); @@ -42,32 +44,32 @@ public List getEntries(SkyBlockPlayer player) { SkillCategories skillCategory = dataHandler.get(SkyBlockDataHandler.Data.LAST_EDITED_SKILL, DatapointSkillCategory.class).getValue(); DatapointSkills.PlayerSkills skills = player.getSkills(); ItemStatistics playerStatistics = player.getStatistics().allStatistics(); - entries.add(new TablistEntry(I18n.string("tablist.account_info.skills_label", Map.of( + entries.add(new TablistEntry(I18n.string("tablist.account_info.skills_label", l, Map.of( "skill", String.valueOf(skillCategory), "level", String.valueOf(skills.getCurrentLevel(skillCategory)), "percentage", String.valueOf(skills.getPercentage(skillCategory)) )), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.account_info.speed", Map.of( + entries.add(new TablistEntry(I18n.string("tablist.account_info.speed", l, Map.of( "color", ItemStatistic.SPEED.getDisplayColor(), "symbol", ItemStatistic.SPEED.getSymbol(), "value", String.valueOf(playerStatistics.getOverall(ItemStatistic.SPEED)) )), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.account_info.strength", Map.of( + entries.add(new TablistEntry(I18n.string("tablist.account_info.strength", l, Map.of( "color", ItemStatistic.STRENGTH.getDisplayColor(), "symbol", ItemStatistic.STRENGTH.getSymbol(), "value", String.valueOf(playerStatistics.getOverall(ItemStatistic.STRENGTH)) )), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.account_info.crit_chance", Map.of( + entries.add(new TablistEntry(I18n.string("tablist.account_info.crit_chance", l, Map.of( "color", ItemStatistic.CRITICAL_CHANCE.getDisplayColor(), "symbol", ItemStatistic.CRITICAL_CHANCE.getSymbol(), "value", String.valueOf(playerStatistics.getOverall(ItemStatistic.CRITICAL_CHANCE)) )), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.account_info.crit_damage", Map.of( + entries.add(new TablistEntry(I18n.string("tablist.account_info.crit_damage", l, Map.of( "color", ItemStatistic.CRITICAL_DAMAGE.getDisplayColor(), "symbol", ItemStatistic.CRITICAL_DAMAGE.getSymbol(), "value", String.valueOf(playerStatistics.getOverall(ItemStatistic.CRITICAL_DAMAGE)) )), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.account_info.attack_speed", Map.of( + entries.add(new TablistEntry(I18n.string("tablist.account_info.attack_speed", l, Map.of( "color", ItemStatistic.BONUS_ATTACK_SPEED.getDisplayColor(), "symbol", ItemStatistic.BONUS_ATTACK_SPEED.getSymbol(), "value", String.valueOf(playerStatistics.getOverall(ItemStatistic.BONUS_ATTACK_SPEED)) diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/tabmodules/SkyBlockPlayersOnlineModule.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/tabmodules/SkyBlockPlayersOnlineModule.java index 1fca1a4d0..65d0ca511 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/tabmodules/SkyBlockPlayersOnlineModule.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/tabmodules/SkyBlockPlayersOnlineModule.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; public class SkyBlockPlayersOnlineModule extends TablistModule { @@ -23,10 +24,11 @@ public SkyBlockPlayersOnlineModule(int page) { public List getEntries(SkyBlockPlayer player) { + Locale l = player.getLocale(); List players = SkyBlockGenericLoader.getLoadedPlayers(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.players", Map.of("count", String.valueOf(players.size())))), TablistSkinRegistry.GREEN) + new TablistEntry(getCentered(I18n.string("tablist.module.players", l, Map.of("count", String.valueOf(players.size())))), TablistSkinRegistry.GREEN) )); List toShow = new ArrayList<>(); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockScoreboard.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockScoreboard.java index b24b3cffc..98db123da 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockScoreboard.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/user/SkyBlockScoreboard.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Map; public class SkyBlockScoreboard { @@ -46,6 +47,7 @@ public static void start() { } for (SkyBlockPlayer player : SkyBlockGenericLoader.getLoadedPlayers()) { + Locale l = player.getLocale(); SkyBlockDataHandler dataHandler = player.getSkyblockDataHandler(); SkyBlockRegion region = player.getRegion(); MissionData missionData = player.getMissionData(); @@ -55,7 +57,7 @@ public static void start() { } List lines = new ArrayList<>(); - lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format")).format(new Date()) + " §8" + HypixelConst.getServerName()); + lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); lines.add("§f " + SkyBlockCalendar.getMonthName() + " " + StringUtility.ntify(SkyBlockCalendar.getDay())); lines.add("§7 " + SkyBlockCalendar.getDisplay(SkyBlockCalendar.getElapsed())); @@ -67,7 +69,7 @@ public static void start() { } lines.add("§7 ⏣ " + region.getType().getColor() + name); } catch (NullPointerException ignored) { - lines.add(" " + I18n.string("scoreboard.skyblock.region_unknown")); + lines.add(" " + I18n.string("scoreboard.skyblock.region_unknown", l)); } lines.add("§7 "); @@ -83,8 +85,8 @@ public static void start() { lines.add(bars + " " + candidate.getColoredName()); }); } else { - lines.add(I18n.string("scoreboard.skyblock.purse_label") + StringUtility.commaify(dataHandler.get(SkyBlockDataHandler.Data.COINS, DatapointDouble.class).getValue())); - lines.add(I18n.string("scoreboard.skyblock.bits_label") + StringUtility.commaify(dataHandler.get(SkyBlockDataHandler.Data.BITS, DatapointInteger.class).getValue())); + lines.add(I18n.string("scoreboard.skyblock.purse_label", l) + StringUtility.commaify(dataHandler.get(SkyBlockDataHandler.Data.COINS, DatapointDouble.class).getValue())); + lines.add(I18n.string("scoreboard.skyblock.bits_label", l) + StringUtility.commaify(dataHandler.get(SkyBlockDataHandler.Data.BITS, DatapointInteger.class).getValue())); if (DarkAuctionHandler.isPlayerInAuction(player.getUuid()) && DarkAuctionHandler.getLocalState() != null @@ -94,8 +96,8 @@ public static void start() { DarkAuctionHandler.DarkAuctionLocalState auctionState = DarkAuctionHandler.getLocalState(); int timeRemaining = DarkAuctionHandler.getTimeLeft().get(); - lines.add(I18n.string("scoreboard.skyblock.dark_auction.time_left_label") + timeRemaining + I18n.string("scoreboard.skyblock.dark_auction.time_left_suffix")); - lines.add(I18n.string("scoreboard.skyblock.dark_auction.current_item_label")); + lines.add(I18n.string("scoreboard.skyblock.dark_auction.time_left_label", l) + timeRemaining + I18n.string("scoreboard.skyblock.dark_auction.time_left_suffix", l)); + lines.add(I18n.string("scoreboard.skyblock.dark_auction.current_item_label", l)); String currentItem = auctionState.getCurrentItemType(); if (currentItem != null) { @@ -107,7 +109,7 @@ public static void start() { lines.add(" §f" + currentItem.replace("_", " ")); } } else { - lines.add(" " + I18n.string("scoreboard.skyblock.dark_auction.waiting")); + lines.add(" " + I18n.string("scoreboard.skyblock.dark_auction.waiting", l)); } } else { if (region != null && @@ -117,13 +119,13 @@ public static void start() { SkyBlockMission skyBlockMission = MissionData.getMissionClass(mission.getMissionID()); if (skyBlockMission instanceof LocationAssociatedMission locationAssociatedMission) { - lines.add(I18n.string("scoreboard.skyblock.objective_label") + " " + BlockUtility.getArrow( + lines.add(I18n.string("scoreboard.skyblock.objective_label", l) + " " + BlockUtility.getArrow( player.getPosition(), locationAssociatedMission.getLocation() )); lines.add("§e" + mission); } else { - lines.add(I18n.string("scoreboard.skyblock.objective_label")); + lines.add(I18n.string("scoreboard.skyblock.objective_label", l)); lines.add("§e" + mission); } @@ -135,10 +137,10 @@ public static void start() { } lines.add("§7 "); - lines.add(I18n.string("scoreboard.common.footer")); + lines.add(I18n.string("scoreboard.common.footer", l)); - String title = " " + getSidebarName(skyblockName, false) - + (player.isCoop() ? " " + I18n.string("scoreboard.skyblock.coop_suffix") + " " : " "); + String title = " " + getSidebarName(skyblockName, false, l) + + (player.isCoop() ? " " + I18n.string("scoreboard.skyblock.coop_suffix", l) + " " : " "); if (!scoreboard.hasScoreboard(player)) { scoreboard.createScoreboard(player, title); @@ -155,8 +157,8 @@ public static void removeCache(Player player) { scoreboard.removeScoreboard(player); } - private static String getSidebarName(int counter, boolean isGuest) { - String baseText = I18n.string("scoreboard.skyblock.title_base"); + private static String getSidebarName(int counter, boolean isGuest, Locale locale) { + String baseText = I18n.string("scoreboard.skyblock.title_base", locale); String[] colors = {"§f§l", "§6§l", "§e§l"}; String endColor = "§a§l"; String endText = isGuest ? " GUEST" : ""; diff --git a/type.skywarsgame/src/main/java/net/swofty/type/skywarsgame/SkywarsGameScoreboard.java b/type.skywarsgame/src/main/java/net/swofty/type/skywarsgame/SkywarsGameScoreboard.java index f58253b02..f85967501 100644 --- a/type.skywarsgame/src/main/java/net/swofty/type/skywarsgame/SkywarsGameScoreboard.java +++ b/type.skywarsgame/src/main/java/net/swofty/type/skywarsgame/SkywarsGameScoreboard.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Map; public class SkywarsGameScoreboard { @@ -36,30 +37,31 @@ public static void start() { for (HypixelPlayer player : HypixelGenericLoader.getLoadedPlayers()) { SkywarsGame game = TypeSkywarsGameLoader.getPlayerGame(player); if (game == null) continue; + Locale l = player.getLocale(); SkywarsPlayer swPlayer = (SkywarsPlayer) player; List lines = new ArrayList<>(); - lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format")).format(new Date()) + " §8" + HypixelConst.getServerName()); + lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); if (game.getGameStatus() == SkywarsGameStatus.IN_PROGRESS) { long elapsedMs = System.currentTimeMillis() - game.getGameStartTime(); long elapsedSeconds = elapsedMs / 1000; - String nextEventLine = getNextEventLine(game.getCurrentEvent(), elapsedSeconds); + String nextEventLine = getNextEventLine(game.getCurrentEvent(), elapsedSeconds, l); if (nextEventLine != null) { - lines.add(I18n.string("scoreboard.skywars_game.next_event_label")); + lines.add(I18n.string("scoreboard.skywars_game.next_event_label", l)); lines.add(nextEventLine); lines.add("§7 "); } int alive = (int) game.getPlayers().stream().filter(p -> !p.isEliminated()).count(); - lines.add(I18n.string("scoreboard.skywars_game.players_left_label") + alive); + lines.add(I18n.string("scoreboard.skywars_game.players_left_label", l) + alive); lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_game.kills_label") + swPlayer.getKillsThisGame()); + lines.add(I18n.string("scoreboard.skywars_game.kills_label", l) + swPlayer.getKillsThisGame()); } else if (game.getGameStatus() == SkywarsGameStatus.ENDING) { - lines.add(I18n.string("scoreboard.skywars_game.top_killers_label")); + lines.add(I18n.string("scoreboard.skywars_game.top_killers_label", l)); java.util.List topKillers = game.getPlayers().stream() .sorted((a, b) -> Integer.compare(b.getKillsThisGame(), a.getKillsThisGame())) @@ -67,9 +69,9 @@ public static void start() { .toList(); String[] places = { - I18n.string("scoreboard.skywars_game.place_1st"), - I18n.string("scoreboard.skywars_game.place_2nd"), - I18n.string("scoreboard.skywars_game.place_3rd") + I18n.string("scoreboard.skywars_game.place_1st", l), + I18n.string("scoreboard.skywars_game.place_2nd", l), + I18n.string("scoreboard.skywars_game.place_3rd", l) }; for (int i = 0; i < topKillers.size(); i++) { SkywarsPlayer killer = topKillers.get(i); @@ -77,29 +79,29 @@ public static void start() { } lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_game.your_kills_label") + swPlayer.getKillsThisGame()); + lines.add(I18n.string("scoreboard.skywars_game.your_kills_label", l) + swPlayer.getKillsThisGame()); } else if (game.getGameStatus() == SkywarsGameStatus.WAITING) { - lines.add(I18n.string("scoreboard.skywars_game.players_label") + game.getPlayers().size() + "/" + game.getGameType().getMaxPlayers()); + lines.add(I18n.string("scoreboard.skywars_game.players_label", l) + game.getPlayers().size() + "/" + game.getGameType().getMaxPlayers()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_game.waiting")); + lines.add(I18n.string("scoreboard.skywars_game.waiting", l)); } else if (game.getGameStatus() == SkywarsGameStatus.STARTING) { - lines.add(I18n.string("scoreboard.skywars_game.players_label") + game.getPlayers().size() + "/" + game.getGameType().getMaxPlayers()); + lines.add(I18n.string("scoreboard.skywars_game.players_label", l) + game.getPlayers().size() + "/" + game.getGameType().getMaxPlayers()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_game.starting_in_label") + game.getCountdown().getSecondsRemaining() + I18n.string("scoreboard.skywars_game.starting_in_suffix")); + lines.add(I18n.string("scoreboard.skywars_game.starting_in_label", l) + game.getCountdown().getSecondsRemaining() + I18n.string("scoreboard.skywars_game.starting_in_suffix", l)); } lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_game.map_label") + game.getMapEntry().getName()); - lines.add(I18n.string("scoreboard.skywars_game.mode_label") + game.getGameType().getDisplayName()); + lines.add(I18n.string("scoreboard.skywars_game.map_label", l) + game.getMapEntry().getName()); + lines.add(I18n.string("scoreboard.skywars_game.mode_label", l) + game.getGameType().getDisplayName()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.common.footer")); + lines.add(I18n.string("scoreboard.common.footer", l)); if (!scoreboard.hasScoreboard(player)) { - scoreboard.createScoreboard(player, getSidebarName(animationFrame)); + scoreboard.createScoreboard(player, getSidebarName(animationFrame, l)); } scoreboard.updateLines(player, lines); - scoreboard.updateTitle(player, getSidebarName(animationFrame)); + scoreboard.updateTitle(player, getSidebarName(animationFrame, l)); } return TaskSchedule.tick(4); }); @@ -109,8 +111,8 @@ public static void removeCache(Player player) { scoreboard.removeScoreboard(player); } - private static String getSidebarName(int counter) { - String baseText = I18n.string("scoreboard.skywars_game.title_base"); + private static String getSidebarName(int counter, Locale locale) { + String baseText = I18n.string("scoreboard.skywars_game.title_base", locale); String[] colors = {"§f§l", "§e§l", "§6§l"}; if (counter > 0 && counter <= 7) { @@ -125,21 +127,21 @@ private static String getSidebarName(int counter) { } } - private static String getNextEventLine(SkywarsGame.GameEvent currentEvent, long elapsedSeconds) { + private static String getNextEventLine(SkywarsGame.GameEvent currentEvent, long elapsedSeconds, Locale locale) { SkywarsGame.GameEvent nextEvent = currentEvent.getNext(); return switch (nextEvent) { case FIRST_REFILL -> { long timeUntil = Math.max(0, SkywarsGame.FIRST_REFILL_SECONDS - elapsedSeconds); - yield I18n.string("scoreboard.skywars_game.event_refill", Map.of("time", formatTime(timeUntil))); + yield I18n.string("scoreboard.skywars_game.event_refill", locale, Map.of("time", formatTime(timeUntil))); } case SECOND_REFILL -> { long timeUntil = Math.max(0, SkywarsGame.SECOND_REFILL_SECONDS - elapsedSeconds); - yield I18n.string("scoreboard.skywars_game.event_refill", Map.of("time", formatTime(timeUntil))); + yield I18n.string("scoreboard.skywars_game.event_refill", locale, Map.of("time", formatTime(timeUntil))); } case DRAGON_SPAWN -> { long timeUntil = Math.max(0, SkywarsGame.DRAGON_SPAWN_SECONDS - elapsedSeconds); - yield I18n.string("scoreboard.skywars_game.event_dragon", Map.of("time", formatTime(timeUntil))); + yield I18n.string("scoreboard.skywars_game.event_dragon", locale, Map.of("time", formatTime(timeUntil))); } case GAME_END, GAME_START -> null; }; diff --git a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkywarsLobbyScoreboard.java b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkywarsLobbyScoreboard.java index c350d172a..791790cde 100644 --- a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkywarsLobbyScoreboard.java +++ b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkywarsLobbyScoreboard.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; public class SkywarsLobbyScoreboard { private static final HypixelScoreboard scoreboard = new HypixelScoreboard(); @@ -37,6 +38,7 @@ public static void start() { } for (HypixelPlayer player : HypixelGenericLoader.getLoadedPlayers()) { + Locale l = player.getLocale(); SkywarsDataHandler swDataHandler = SkywarsDataHandler.getUser(player); if (swDataHandler == null) { @@ -61,27 +63,27 @@ public static void start() { int level = SkywarsLevelRegistry.calculateLevel(experience); List lines = new ArrayList<>(); - lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format")).format(new Date()) + " §8" + HypixelConst.getServerName()); + lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_lobby.your_level_label") + " " + SkywarsLevelColor.getLevelDisplay(level)); + lines.add(I18n.string("scoreboard.skywars_lobby.your_level_label", l) + " " + SkywarsLevelColor.getLevelDisplay(level)); lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_lobby.solo_kills_label") + soloKills); - lines.add(I18n.string("scoreboard.skywars_lobby.solo_wins_label") + soloWins); - lines.add(I18n.string("scoreboard.skywars_lobby.doubles_kills_label") + doublesKills); - lines.add(I18n.string("scoreboard.skywars_lobby.doubles_wins_label") + doublesWins); + lines.add(I18n.string("scoreboard.skywars_lobby.solo_kills_label", l) + soloKills); + lines.add(I18n.string("scoreboard.skywars_lobby.solo_wins_label", l) + soloWins); + lines.add(I18n.string("scoreboard.skywars_lobby.doubles_kills_label", l) + doublesKills); + lines.add(I18n.string("scoreboard.skywars_lobby.doubles_wins_label", l) + doublesWins); lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_lobby.coins_label") + coins); - lines.add(I18n.string("scoreboard.skywars_lobby.souls_label") + souls); - lines.add(I18n.string("scoreboard.skywars_lobby.tokens_label") + tokens); + lines.add(I18n.string("scoreboard.skywars_lobby.coins_label", l) + coins); + lines.add(I18n.string("scoreboard.skywars_lobby.souls_label", l) + souls); + lines.add(I18n.string("scoreboard.skywars_lobby.tokens_label", l) + tokens); lines.add("§7 "); - lines.add(I18n.string("scoreboard.common.footer")); + lines.add(I18n.string("scoreboard.common.footer", l)); if (!scoreboard.hasScoreboard(player)) { - scoreboard.createScoreboard(player, getSidebarName(animationFrame)); + scoreboard.createScoreboard(player, getSidebarName(animationFrame, l)); } scoreboard.updateLines(player, lines); - scoreboard.updateTitle(player, getSidebarName(animationFrame)); + scoreboard.updateTitle(player, getSidebarName(animationFrame, l)); } return TaskSchedule.tick(4); }); @@ -91,8 +93,8 @@ public static void removeCache(Player player) { scoreboard.removeScoreboard(player); } - private static String getSidebarName(int counter) { - String baseText = I18n.string("scoreboard.skywars_lobby.title_base"); + private static String getSidebarName(int counter, Locale locale) { + String baseText = I18n.string("scoreboard.skywars_lobby.title_base", locale); String[] colors = {"§f§l", "§e§l", "§6§l"}; if (counter > 0 && counter <= 7) { diff --git a/type.spidersden/src/main/java/net/swofty/type/spidersden/tab/SpidersDenServerModule.java b/type.spidersden/src/main/java/net/swofty/type/spidersden/tab/SpidersDenServerModule.java index 993f6f69f..1b8d2662f 100644 --- a/type.spidersden/src/main/java/net/swofty/type/spidersden/tab/SpidersDenServerModule.java +++ b/type.spidersden/src/main/java/net/swofty/type/spidersden/tab/SpidersDenServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class SpidersDenServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.spiders_den"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.spiders_den", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.theend/src/main/java/net/swofty/type/theend/tab/TheEndServerModule.java b/type.theend/src/main/java/net/swofty/type/theend/tab/TheEndServerModule.java index c1c4ddbdf..586cc9871 100644 --- a/type.theend/src/main/java/net/swofty/type/theend/tab/TheEndServerModule.java +++ b/type.theend/src/main/java/net/swofty/type/theend/tab/TheEndServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class TheEndServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.the_end"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.the_end", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.thefarmingislands/src/main/java/net/swofty/type/thefarmingislands/tab/TheFarmingIslandsServerModule.java b/type.thefarmingislands/src/main/java/net/swofty/type/thefarmingislands/tab/TheFarmingIslandsServerModule.java index ea219def9..2b6c4e110 100644 --- a/type.thefarmingislands/src/main/java/net/swofty/type/thefarmingislands/tab/TheFarmingIslandsServerModule.java +++ b/type.thefarmingislands/src/main/java/net/swofty/type/thefarmingislands/tab/TheFarmingIslandsServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class TheFarmingIslandsServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.the_farming_islands"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.the_farming_islands", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); diff --git a/type.thepark/src/main/java/net/swofty/type/thepark/tab/TheParkServerModule.java b/type.thepark/src/main/java/net/swofty/type/thepark/tab/TheParkServerModule.java index 04aa18dd2..ae0bd5ed0 100644 --- a/type.thepark/src/main/java/net/swofty/type/thepark/tab/TheParkServerModule.java +++ b/type.thepark/src/main/java/net/swofty/type/thepark/tab/TheParkServerModule.java @@ -8,17 +8,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class TheParkServerModule extends TablistModule { @Override public List getEntries(HypixelPlayer player) { + Locale l = player.getLocale(); ArrayList entries = new ArrayList<>(List.of( - new TablistEntry(getCentered(I18n.string("tablist.module.server_info")), TablistSkinRegistry.CYAN) + new TablistEntry(getCentered(I18n.string("tablist.module.server_info", l)), TablistSkinRegistry.CYAN) )); - entries.add(new TablistEntry(I18n.string("tablist.server_info.area.the_park"), TablistSkinRegistry.GRAY)); - entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.area.the_park", l), TablistSkinRegistry.GRAY)); + entries.add(new TablistEntry(I18n.string("tablist.server_info.server_label", l, Map.of("server_name", HypixelConst.getServerName())), TablistSkinRegistry.GRAY)); fillRestWithGray(entries); From 7c3ab1c8c049395a8c6e0b1b9ba57698529c5cd3 Mon Sep 17 00:00:00 2001 From: Swofty Date: Sat, 28 Feb 2026 03:01:21 +1100 Subject: [PATCH 11/17] feat(elections): scalable vote storage with atomic MongoDB ops and multi-server safety Replace single-document read-modify-write with per-voter documents and atomic $inc tally counters for O(1) vote reads. Add StartElection and ResolveElection endpoints for idempotent multi-server election lifecycle. Remove SaveElectionData endpoint. --- .../ResolveElectionProtocolObject.java | 64 +++++ .../SaveElectionDataProtocolObject.java | 58 ----- .../election/StartElectionProtocolObject.java | 68 +++++ .../service/election/ElectionDatabase.java | 123 +++++++-- .../service/election/ElectionService.java | 2 +- .../election/endpoints/CastVoteEndpoint.java | 35 ++- .../endpoints/GetCandidatesEndpoint.java | 19 +- .../endpoints/GetElectionDataEndpoint.java | 26 +- .../endpoints/GetPlayerVoteEndpoint.java | 11 +- .../endpoints/ResolveElectionEndpoint.java | 238 ++++++++++++++++++ .../endpoints/SaveElectionDataEndpoint.java | 30 --- .../endpoints/StartElectionEndpoint.java | 71 ++++++ 12 files changed, 579 insertions(+), 166 deletions(-) create mode 100644 commons/src/main/java/net/swofty/commons/protocol/objects/election/ResolveElectionProtocolObject.java delete mode 100644 commons/src/main/java/net/swofty/commons/protocol/objects/election/SaveElectionDataProtocolObject.java create mode 100644 commons/src/main/java/net/swofty/commons/protocol/objects/election/StartElectionProtocolObject.java create mode 100644 service.elections/src/main/java/net/swofty/service/election/endpoints/ResolveElectionEndpoint.java delete mode 100644 service.elections/src/main/java/net/swofty/service/election/endpoints/SaveElectionDataEndpoint.java create mode 100644 service.elections/src/main/java/net/swofty/service/election/endpoints/StartElectionEndpoint.java diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/ResolveElectionProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/ResolveElectionProtocolObject.java new file mode 100644 index 000000000..e99f73632 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/ResolveElectionProtocolObject.java @@ -0,0 +1,64 @@ +package net.swofty.commons.protocol.objects.election; + +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; +import org.json.JSONObject; + +public class ResolveElectionProtocolObject + extends ProtocolObject { + + @Override + public Serializer getSerializer() { + return new Serializer<>() { + @Override + public String serialize(ResolveElectionMessage value) { + JSONObject json = new JSONObject(); + json.put("year", value.year()); + return json.toString(); + } + + @Override + public ResolveElectionMessage deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new ResolveElectionMessage(obj.getInt("year")); + } + + @Override + public ResolveElectionMessage clone(ResolveElectionMessage value) { + return value; + } + }; + } + + @Override + public Serializer getReturnSerializer() { + return new Serializer<>() { + @Override + public String serialize(ResolveElectionResponse value) { + JSONObject json = new JSONObject(); + json.put("resolved", value.resolved()); + json.put("serializedData", value.serializedData()); + return json.toString(); + } + + @Override + public ResolveElectionResponse deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new ResolveElectionResponse( + obj.getBoolean("resolved"), + obj.optString("serializedData", null) + ); + } + + @Override + public ResolveElectionResponse clone(ResolveElectionResponse value) { + return value; + } + }; + } + + public record ResolveElectionMessage(int year) {} + + public record ResolveElectionResponse(boolean resolved, String serializedData) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/SaveElectionDataProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/SaveElectionDataProtocolObject.java deleted file mode 100644 index a6e59d65e..000000000 --- a/commons/src/main/java/net/swofty/commons/protocol/objects/election/SaveElectionDataProtocolObject.java +++ /dev/null @@ -1,58 +0,0 @@ -package net.swofty.commons.protocol.objects.election; - -import net.swofty.commons.protocol.ProtocolObject; -import net.swofty.commons.protocol.Serializer; -import org.json.JSONObject; - -public class SaveElectionDataProtocolObject - extends ProtocolObject { - - @Override - public Serializer getSerializer() { - return new Serializer<>() { - @Override - public String serialize(SaveElectionDataMessage value) { - JSONObject json = new JSONObject(); - json.put("data", value.serializedData()); - return json.toString(); - } - - @Override - public SaveElectionDataMessage deserialize(String json) { - JSONObject obj = new JSONObject(json); - return new SaveElectionDataMessage(obj.getString("data")); - } - - @Override - public SaveElectionDataMessage clone(SaveElectionDataMessage value) { - return value; - } - }; - } - - @Override - public Serializer getReturnSerializer() { - return new Serializer<>() { - @Override - public String serialize(SaveElectionDataResponse value) { - return new JSONObject().put("success", value.success()).toString(); - } - - @Override - public SaveElectionDataResponse deserialize(String json) { - JSONObject obj = new JSONObject(json); - return new SaveElectionDataResponse(obj.getBoolean("success")); - } - - @Override - public SaveElectionDataResponse clone(SaveElectionDataResponse value) { - return value; - } - }; - } - - public record SaveElectionDataMessage(String serializedData) {} - - public record SaveElectionDataResponse(boolean success) {} -} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/StartElectionProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/StartElectionProtocolObject.java new file mode 100644 index 000000000..7833f2df1 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/StartElectionProtocolObject.java @@ -0,0 +1,68 @@ +package net.swofty.commons.protocol.objects.election; + +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; +import org.json.JSONObject; + +public class StartElectionProtocolObject + extends ProtocolObject { + + @Override + public Serializer getSerializer() { + return new Serializer<>() { + @Override + public String serialize(StartElectionMessage value) { + JSONObject json = new JSONObject(); + json.put("year", value.year()); + json.put("candidatesJson", value.candidatesJson()); + return json.toString(); + } + + @Override + public StartElectionMessage deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new StartElectionMessage( + obj.getInt("year"), + obj.getString("candidatesJson") + ); + } + + @Override + public StartElectionMessage clone(StartElectionMessage value) { + return value; + } + }; + } + + @Override + public Serializer getReturnSerializer() { + return new Serializer<>() { + @Override + public String serialize(StartElectionResponse value) { + JSONObject json = new JSONObject(); + json.put("started", value.started()); + json.put("serializedData", value.serializedData()); + return json.toString(); + } + + @Override + public StartElectionResponse deserialize(String json) { + JSONObject obj = new JSONObject(json); + return new StartElectionResponse( + obj.getBoolean("started"), + obj.optString("serializedData", null) + ); + } + + @Override + public StartElectionResponse clone(StartElectionResponse value) { + return value; + } + }; + } + + public record StartElectionMessage(int year, String candidatesJson) {} + + public record StartElectionResponse(boolean started, String serializedData) {} +} diff --git a/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java b/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java index 40d63bc31..ef48f8c2f 100644 --- a/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java +++ b/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java @@ -7,14 +7,21 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; +import com.mongodb.client.model.ReplaceOptions; import com.mongodb.client.model.Updates; import net.swofty.service.generic.MongoDB; import org.bson.Document; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public record ElectionDatabase(String key) implements MongoDB { public static MongoClient client; public static MongoDatabase database; public static MongoCollection electionCollection; + public static MongoCollection votesCollection; + public static MongoCollection talliesCollection; @Override public MongoDB connect(String connectionString) { @@ -24,6 +31,8 @@ public MongoDB connect(String connectionString) { database = client.getDatabase("Minestom"); electionCollection = database.getCollection("elections"); + votesCollection = database.getCollection("election-votes"); + talliesCollection = database.getCollection("election-tallies"); return this; } @@ -42,33 +51,25 @@ public boolean exists() { @Override public Object get(String key, Object def) { Document doc = electionCollection.find(Filters.eq("_id", this.key)).first(); - if (doc == null) { - return def; - } + if (doc == null) return def; return doc.get(key); } @Override public void insertOrUpdate(String key, Object value) { - if (exists()) { - Document query = new Document("_id", this.key); - Document found = electionCollection.find(query).first(); - assert found != null; - electionCollection.updateOne(found, Updates.set(key, value)); - return; - } - Document newDoc = new Document("_id", this.key); - newDoc.append(key, value); - electionCollection.insertOne(newDoc); + Document doc = new Document("_id", this.key).append(key, value); + electionCollection.replaceOne( + Filters.eq("_id", this.key), + doc, + new ReplaceOptions().upsert(true) + ); } @Override public boolean remove(String id) { Document query = new Document("_id", id); Document found = electionCollection.find(query).first(); - if (found == null) { - return false; - } + if (found == null) return false; electionCollection.deleteOne(query); return true; } @@ -80,14 +81,88 @@ public static String loadElectionData() { } public static void saveElectionData(String serializedData) { - Document query = new Document("_id", "election_data"); - Document existing = electionCollection.find(query).first(); - if (existing != null) { - electionCollection.updateOne(query, Updates.set("data", serializedData)); - } else { - Document newDoc = new Document("_id", "election_data"); - newDoc.append("data", serializedData); - electionCollection.insertOne(newDoc); + Document doc = new Document("_id", "election_data").append("data", serializedData); + electionCollection.replaceOne( + Filters.eq("_id", "election_data"), + doc, + new ReplaceOptions().upsert(true) + ); + } + + public static void castVote(String playerId, String candidateName, int electionYear) { + String talliesDocId = "tallies_" + electionYear; + + Document existingVote = votesCollection.find( + Filters.and(Filters.eq("_id", playerId), Filters.eq("electionYear", electionYear)) + ).first(); + + if (existingVote != null) { + String oldCandidate = existingVote.getString("candidate"); + if (oldCandidate != null && !oldCandidate.equals(candidateName)) { + talliesCollection.updateOne( + Filters.eq("_id", talliesDocId), + Updates.inc(oldCandidate, -1L) + ); + } + } + + Document voteDoc = new Document("_id", playerId) + .append("candidate", candidateName) + .append("electionYear", electionYear); + votesCollection.replaceOne( + Filters.eq("_id", playerId), + voteDoc, + new ReplaceOptions().upsert(true) + ); + + if (existingVote == null || !candidateName.equals(existingVote.getString("candidate"))) { + talliesCollection.updateOne( + Filters.eq("_id", talliesDocId), + Updates.inc(candidateName, 1L), + new com.mongodb.client.model.UpdateOptions().upsert(true) + ); } } + + public static String getPlayerVote(String playerId, int electionYear) { + Document doc = votesCollection.find( + Filters.and(Filters.eq("_id", playerId), Filters.eq("electionYear", electionYear)) + ).first(); + if (doc == null) return null; + return doc.getString("candidate"); + } + + public static Map getTallies(int electionYear) { + String talliesDocId = "tallies_" + electionYear; + Document doc = talliesCollection.find(Filters.eq("_id", talliesDocId)).first(); + if (doc == null) return new HashMap<>(); + + Map tallies = new HashMap<>(); + for (String key : doc.keySet()) { + if (key.equals("_id")) continue; + Object val = doc.get(key); + if (val instanceof Number num) { + tallies.put(key, num.longValue()); + } + } + return tallies; + } + + public static void initTallies(int electionYear, List candidateNames) { + String talliesDocId = "tallies_" + electionYear; + Document doc = new Document("_id", talliesDocId); + for (String name : candidateNames) { + doc.append(name, 0L); + } + talliesCollection.replaceOne( + Filters.eq("_id", talliesDocId), + doc, + new ReplaceOptions().upsert(true) + ); + } + + public static void clearVotesForYear(int electionYear) { + votesCollection.deleteMany(Filters.eq("electionYear", electionYear)); + talliesCollection.deleteMany(Filters.eq("_id", "tallies_" + electionYear)); + } } diff --git a/service.elections/src/main/java/net/swofty/service/election/ElectionService.java b/service.elections/src/main/java/net/swofty/service/election/ElectionService.java index e49a391fb..ba20b9026 100644 --- a/service.elections/src/main/java/net/swofty/service/election/ElectionService.java +++ b/service.elections/src/main/java/net/swofty/service/election/ElectionService.java @@ -9,7 +9,7 @@ public class ElectionService implements SkyBlockService { - static void main() { + public static void main(String[] args) { String mongoUri = ConfigProvider.settings().getMongodb(); new ElectionDatabase(null).connect(mongoUri); SkyBlockService.init(new ElectionService()); diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java index 7c3776b6a..9da7af8dc 100644 --- a/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java @@ -6,9 +6,8 @@ import net.swofty.commons.protocol.objects.election.CastVoteProtocolObject; import net.swofty.service.election.ElectionDatabase; import net.swofty.service.generic.redis.ServiceEndpoint; +import org.tinylog.Logger; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,8 +40,12 @@ public CastVoteProtocolObject.CastVoteResponse onMessage( return new CastVoteProtocolObject.CastVoteResponse(false, null); } + int electionYear = ((Number) data.get("electionYear")).intValue(); + List> candidates = (List>) data.get("candidates"); - if (candidates == null) candidates = new ArrayList<>(); + if (candidates == null) { + return new CastVoteProtocolObject.CastVoteResponse(false, null); + } boolean validCandidate = candidates.stream() .anyMatch(c -> messageObject.candidateName().equals(c.get("mayorName"))); @@ -50,26 +53,16 @@ public CastVoteProtocolObject.CastVoteResponse onMessage( return new CastVoteProtocolObject.CastVoteResponse(false, null); } - Map votes = (Map) data.get("votes"); - if (votes == null) { - votes = new HashMap<>(); - data.put("votes", votes); - } - votes.put(messageObject.accountId().toString(), messageObject.candidateName()); - - String updatedData = GSON.toJson(data); - ElectionDatabase.saveElectionData(updatedData); - - Map tally = new HashMap<>(); - for (Map c : candidates) { - tally.put((String) c.get("mayorName"), 0L); - } - for (String candidateName : votes.values()) { - tally.merge(candidateName, 1L, Long::sum); - } + ElectionDatabase.castVote( + messageObject.accountId().toString(), + messageObject.candidateName(), + electionYear + ); - return new CastVoteProtocolObject.CastVoteResponse(true, GSON.toJson(tally)); + Map tallies = ElectionDatabase.getTallies(electionYear); + return new CastVoteProtocolObject.CastVoteResponse(true, GSON.toJson(tallies)); } catch (Exception e) { + Logger.error(e, "Failed to cast vote"); return new CastVoteProtocolObject.CastVoteResponse(false, null); } } diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetCandidatesEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetCandidatesEndpoint.java index d5ae2d8d3..e3ecd303b 100644 --- a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetCandidatesEndpoint.java +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetCandidatesEndpoint.java @@ -6,6 +6,7 @@ import net.swofty.commons.protocol.objects.election.GetCandidatesProtocolObject; import net.swofty.service.election.ElectionDatabase; import net.swofty.service.generic.redis.ServiceEndpoint; +import org.tinylog.Logger; import java.util.ArrayList; import java.util.List; @@ -40,35 +41,29 @@ public GetCandidatesProtocolObject.GetCandidatesResponse onMessage( return new GetCandidatesProtocolObject.GetCandidatesResponse(false, List.of()); } + int electionYear = ((Number) data.get("electionYear")).intValue(); + List> candidates = (List>) data.get("candidates"); if (candidates == null || candidates.isEmpty()) { return new GetCandidatesProtocolObject.GetCandidatesResponse(true, List.of()); } - Map votes = (Map) data.get("votes"); - if (votes == null) votes = Map.of(); - - Map tally = new java.util.HashMap<>(); - for (Map c : candidates) { - tally.put((String) c.get("mayorName"), 0L); - } - for (String candidateName : votes.values()) { - tally.merge(candidateName, 1L, Long::sum); - } - long totalVotes = tally.values().stream().mapToLong(Long::longValue).sum(); + Map tallies = ElectionDatabase.getTallies(electionYear); + long totalVotes = tallies.values().stream().mapToLong(Long::longValue).sum(); List infos = new ArrayList<>(); for (Map c : candidates) { String name = (String) c.get("mayorName"); List perks = (List) c.get("activePerks"); if (perks == null) perks = List.of(); - long voteCount = tally.getOrDefault(name, 0L); + long voteCount = tallies.getOrDefault(name, 0L); double pct = totalVotes > 0 ? (voteCount * 100.0) / totalVotes : 0; infos.add(new GetCandidatesProtocolObject.CandidateInfo(name, perks, voteCount, pct)); } return new GetCandidatesProtocolObject.GetCandidatesResponse(true, infos); } catch (Exception e) { + Logger.error(e, "Failed to get candidates"); return new GetCandidatesProtocolObject.GetCandidatesResponse(false, List.of()); } } diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java index a860cbd4d..54ec89c11 100644 --- a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetElectionDataEndpoint.java @@ -6,8 +6,8 @@ import net.swofty.commons.protocol.objects.election.GetElectionDataProtocolObject; import net.swofty.service.election.ElectionDatabase; import net.swofty.service.generic.redis.ServiceEndpoint; +import org.tinylog.Logger; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -36,27 +36,19 @@ public GetElectionDataProtocolObject.GetElectionDataResponse onMessage( try { Map parsed = GSON.fromJson(data, Map.class); - Map votes = (Map) parsed.get("votes"); - List> candidates = (List>) parsed.get("candidates"); + parsed.remove("votes"); - Map tallies = new HashMap<>(); - if (candidates != null) { - for (Map c : candidates) { - tallies.put((String) c.get("mayorName"), 0L); - } - } - if (votes != null) { - for (String candidateName : votes.values()) { - tallies.merge(candidateName, 1L, Long::sum); - } + Number yearNum = (Number) parsed.get("electionYear"); + if (yearNum != null) { + int electionYear = yearNum.intValue(); + Map tallies = ElectionDatabase.getTallies(electionYear); + parsed.put("voteTallies", tallies); } - parsed.put("voteTallies", tallies); - parsed.remove("votes"); - return new GetElectionDataProtocolObject.GetElectionDataResponse(true, GSON.toJson(parsed)); } catch (Exception e) { - return new GetElectionDataProtocolObject.GetElectionDataResponse(true, data); + Logger.error(e, "Failed to parse election data"); + return new GetElectionDataProtocolObject.GetElectionDataResponse(false, null); } } } diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetPlayerVoteEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetPlayerVoteEndpoint.java index 29e734b99..95ba1d31a 100644 --- a/service.elections/src/main/java/net/swofty/service/election/endpoints/GetPlayerVoteEndpoint.java +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/GetPlayerVoteEndpoint.java @@ -6,6 +6,7 @@ import net.swofty.commons.protocol.objects.election.GetPlayerVoteProtocolObject; import net.swofty.service.election.ElectionDatabase; import net.swofty.service.generic.redis.ServiceEndpoint; +import org.tinylog.Logger; import java.util.Map; @@ -33,14 +34,18 @@ public GetPlayerVoteProtocolObject.GetPlayerVoteResponse onMessage( } Map data = GSON.fromJson(rawData, Map.class); - Map votes = (Map) data.get("votes"); - if (votes == null) { + Number yearNum = (Number) data.get("electionYear"); + if (yearNum == null) { return new GetPlayerVoteProtocolObject.GetPlayerVoteResponse(null); } - String vote = votes.get(messageObject.accountId().toString()); + String vote = ElectionDatabase.getPlayerVote( + messageObject.accountId().toString(), + yearNum.intValue() + ); return new GetPlayerVoteProtocolObject.GetPlayerVoteResponse(vote); } catch (Exception e) { + Logger.error(e, "Failed to get player vote"); return new GetPlayerVoteProtocolObject.GetPlayerVoteResponse(null); } } diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/ResolveElectionEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/ResolveElectionEndpoint.java new file mode 100644 index 000000000..7d394683e --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/ResolveElectionEndpoint.java @@ -0,0 +1,238 @@ +package net.swofty.service.election.endpoints; + +import com.google.gson.Gson; +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.objects.election.ResolveElectionProtocolObject; +import net.swofty.service.election.ElectionDatabase; +import net.swofty.service.generic.redis.ServiceEndpoint; +import org.tinylog.Logger; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; + +public class ResolveElectionEndpoint implements ServiceEndpoint + { + + private static final Gson GSON = new Gson(); + + private static final List SPECIAL_MAYORS = List.of("SCORPIUS", "DERPY", "JERRY"); + + @Override + public ProtocolObject associatedProtocolObject() { + return new ResolveElectionProtocolObject(); + } + + @Override + @SuppressWarnings("unchecked") + public ResolveElectionProtocolObject.ResolveElectionResponse onMessage( + ServiceProxyRequest message, + ResolveElectionProtocolObject.ResolveElectionMessage messageObject) { + try { + String rawData = ElectionDatabase.loadElectionData(); + if (rawData == null) { + return new ResolveElectionProtocolObject.ResolveElectionResponse(false, null); + } + + Map data = GSON.fromJson(rawData, Map.class); + Boolean electionOpen = (Boolean) data.get("electionOpen"); + + if (electionOpen == null || !electionOpen) { + data.remove("votes"); + return new ResolveElectionProtocolObject.ResolveElectionResponse(false, GSON.toJson(data)); + } + + int electionYear = messageObject.year(); + Map tallies = ElectionDatabase.getTallies(electionYear); + + List> candidates = (List>) data.get("candidates"); + if (candidates == null) candidates = new ArrayList<>(); + + for (Map c : candidates) { + String name = (String) c.get("mayorName"); + tallies.putIfAbsent(name, 0L); + } + + List> sorted = new ArrayList<>(tallies.entrySet()); + sorted.sort((a, b) -> Long.compare(b.getValue(), a.getValue())); + + if (sorted.isEmpty()) { + return new ResolveElectionProtocolObject.ResolveElectionResponse(false, GSON.toJson(data)); + } + + long topVotes = sorted.getFirst().getValue(); + List> tied = sorted.stream() + .filter(e -> e.getValue() == topVotes).toList(); + + String winnerName; + if (tied.size() > 1) { + winnerName = tied.get(ThreadLocalRandom.current().nextInt(tied.size())).getKey(); + } else { + winnerName = sorted.getFirst().getKey(); + } + + Map winnerCandidate = candidates.stream() + .filter(c -> winnerName.equals(c.get("mayorName"))) + .findFirst().orElse(null); + + int winnerIndex = winnerCandidate != null + ? ((Number) winnerCandidate.getOrDefault("index", 0)).intValue() + : 0; + + boolean isSpecialWinner = SPECIAL_MAYORS.contains(winnerName); + + data.put("currentMayor", winnerName); + data.put("currentMayorColor", colorForIndex(winnerIndex)); + + if (winnerCandidate != null && winnerCandidate.get("activePerks") != null) { + data.put("currentMayorPerks", winnerCandidate.get("activePerks")); + } else { + data.put("currentMayorPerks", List.of()); + } + data.put("mayorElectedYear", electionYear); + + Map lastElectedYear = (Map) data.getOrDefault("lastElectedYear", new HashMap<>()); + lastElectedYear.put(winnerName, electionYear); + data.put("lastElectedYear", lastElectedYear); + + if (isSpecialWinner) { + data.put("currentMinister", null); + data.put("ministerPerk", null); + data.put("currentMinisterColor", null); + } else { + String secondPlace = sorted.stream() + .filter(e -> !e.getKey().equals(winnerName)) + .findFirst().map(Map.Entry::getKey).orElse(null); + + if (secondPlace != null) { + Map ministerCandidate = candidates.stream() + .filter(c -> secondPlace.equals(c.get("mayorName"))) + .findFirst().orElse(null); + + int ministerIndex = ministerCandidate != null + ? ((Number) ministerCandidate.getOrDefault("index", 1)).intValue() + : 1; + + data.put("currentMinister", secondPlace); + data.put("currentMinisterColor", colorForIndex(ministerIndex)); + + List ministerPerks = ministerCandidate != null + ? (List) ministerCandidate.get("activePerks") + : null; + if (ministerPerks != null && !ministerPerks.isEmpty()) { + data.put("ministerPerk", ministerPerks.get( + ThreadLocalRandom.current().nextInt(ministerPerks.size()))); + } + } + } + + updatePerkProgression(data, candidates, winnerName); + + long totalVoteCount = tallies.values().stream().mapToLong(Long::longValue).sum(); + Map electionResult = new HashMap<>(); + electionResult.put("year", electionYear); + List> candidateResults = new ArrayList<>(); + for (Map.Entry entry : sorted) { + Map cr = new HashMap<>(); + cr.put("mayorName", entry.getKey()); + cr.put("votes", entry.getValue()); + cr.put("percentage", totalVoteCount > 0 ? (entry.getValue() * 100.0) / totalVoteCount : 0); + candidateResults.add(cr); + } + electionResult.put("candidateResults", candidateResults); + data.put("lastElectionResult", electionResult); + + data.put("candidates", List.of()); + data.remove("votes"); + data.put("voteTallies", Map.of()); + data.put("electionOpen", false); + + ElectionDatabase.saveElectionData(GSON.toJson(data)); + + return new ResolveElectionProtocolObject.ResolveElectionResponse(true, GSON.toJson(data)); + } catch (Exception e) { + Logger.error(e, "Failed to resolve election"); + return new ResolveElectionProtocolObject.ResolveElectionResponse(false, null); + } + } + + @SuppressWarnings("unchecked") + private void updatePerkProgression(Map data, + List> candidates, + String winnerName) { + Map candidateActivePerks = (Map) data.getOrDefault("candidateActivePerks", new HashMap<>()); + Map failedPerkGainLastTime = (Map) data.getOrDefault("failedPerkGainLastTime", new HashMap<>()); + + for (Map candidate : candidates) { + String name = (String) candidate.get("mayorName"); + if (name.equals(winnerName)) { + candidateActivePerks.remove(winnerName); + failedPerkGainLastTime.remove(winnerName); + continue; + } + + if (SPECIAL_MAYORS.contains(name)) continue; + + List currentPerks = candidate.get("activePerks") != null + ? new ArrayList<>((List) candidate.get("activePerks")) + : new ArrayList<>(); + + int maxPerks = estimateMaxPerks(name); + if (currentPerks.size() < maxPerks) { + Boolean failedLast = (Boolean) failedPerkGainLastTime.get(name); + boolean gainPerk = Boolean.TRUE.equals(failedLast) || ThreadLocalRandom.current().nextBoolean(); + + if (gainPerk) { + failedPerkGainLastTime.put(name, false); + } else { + failedPerkGainLastTime.put(name, true); + } + } + candidateActivePerks.put(name, currentPerks); + } + + if (!SPECIAL_MAYORS.contains(winnerName)) { + List winnerCurrentPerks = (List) candidateActivePerks.getOrDefault(winnerName, new ArrayList<>()); + if (winnerCurrentPerks.isEmpty()) { + List winnerPerksFromCandidate = candidates.stream() + .filter(c -> winnerName.equals(c.get("mayorName"))) + .findFirst() + .map(c -> (List) c.get("activePerks")) + .orElse(List.of()); + if (!winnerPerksFromCandidate.isEmpty()) { + String randomPerk = winnerPerksFromCandidate.get( + ThreadLocalRandom.current().nextInt(winnerPerksFromCandidate.size())); + candidateActivePerks.put(winnerName, List.of(randomPerk)); + } + } + } + + data.put("candidateActivePerks", candidateActivePerks); + data.put("failedPerkGainLastTime", failedPerkGainLastTime); + } + + private int estimateMaxPerks(String mayorName) { + return switch (mayorName) { + case "PAUL" -> 3; + case "SCORPIUS" -> 2; + case "JERRY" -> 3; + default -> 4; + }; + } + + private static String colorForIndex(int index) { + return switch (index) { + case 0 -> "§c"; + case 1 -> "§a"; + case 2 -> "§b"; + case 3 -> "§e"; + case 4 -> "§d"; + default -> "§f"; + }; + } +} diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/SaveElectionDataEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/SaveElectionDataEndpoint.java deleted file mode 100644 index aaa074e23..000000000 --- a/service.elections/src/main/java/net/swofty/service/election/endpoints/SaveElectionDataEndpoint.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.swofty.service.election.endpoints; - -import net.swofty.commons.impl.ServiceProxyRequest; -import net.swofty.commons.protocol.ProtocolObject; -import net.swofty.commons.protocol.objects.election.SaveElectionDataProtocolObject; -import net.swofty.service.election.ElectionDatabase; -import net.swofty.service.generic.redis.ServiceEndpoint; - -public class SaveElectionDataEndpoint implements ServiceEndpoint - { - - @Override - public ProtocolObject associatedProtocolObject() { - return new SaveElectionDataProtocolObject(); - } - - @Override - public SaveElectionDataProtocolObject.SaveElectionDataResponse onMessage( - ServiceProxyRequest message, - SaveElectionDataProtocolObject.SaveElectionDataMessage messageObject) { - try { - ElectionDatabase.saveElectionData(messageObject.serializedData()); - return new SaveElectionDataProtocolObject.SaveElectionDataResponse(true); - } catch (Exception e) { - return new SaveElectionDataProtocolObject.SaveElectionDataResponse(false); - } - } -} diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/StartElectionEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/StartElectionEndpoint.java new file mode 100644 index 000000000..ca6c5444e --- /dev/null +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/StartElectionEndpoint.java @@ -0,0 +1,71 @@ +package net.swofty.service.election.endpoints; + +import com.google.gson.Gson; +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.objects.election.StartElectionProtocolObject; +import net.swofty.service.election.ElectionDatabase; +import net.swofty.service.generic.redis.ServiceEndpoint; +import org.tinylog.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class StartElectionEndpoint implements ServiceEndpoint + { + + private static final Gson GSON = new Gson(); + + @Override + public ProtocolObject associatedProtocolObject() { + return new StartElectionProtocolObject(); + } + + @Override + @SuppressWarnings("unchecked") + public StartElectionProtocolObject.StartElectionResponse onMessage( + ServiceProxyRequest message, + StartElectionProtocolObject.StartElectionMessage messageObject) { + try { + String rawData = ElectionDatabase.loadElectionData(); + + if (rawData != null) { + Map existing = GSON.fromJson(rawData, Map.class); + Boolean electionOpen = (Boolean) existing.get("electionOpen"); + Number existingYear = (Number) existing.get("electionYear"); + + if (electionOpen != null && electionOpen + && existingYear != null && existingYear.intValue() == messageObject.year()) { + Map tallies = ElectionDatabase.getTallies(messageObject.year()); + existing.put("voteTallies", tallies); + existing.remove("votes"); + return new StartElectionProtocolObject.StartElectionResponse(false, GSON.toJson(existing)); + } + } + + Map electionData = GSON.fromJson( + messageObject.candidatesJson(), Map.class + ); + + ElectionDatabase.saveElectionData(messageObject.candidatesJson()); + + List> candidates = (List>) electionData.get("candidates"); + List candidateNames = new ArrayList<>(); + if (candidates != null) { + for (Map c : candidates) { + candidateNames.add((String) c.get("mayorName")); + } + } + ElectionDatabase.initTallies(messageObject.year(), candidateNames); + + electionData.remove("votes"); + return new StartElectionProtocolObject.StartElectionResponse(true, GSON.toJson(electionData)); + } catch (Exception e) { + Logger.error(e, "Failed to start election"); + return new StartElectionProtocolObject.StartElectionResponse(false, null); + } + } +} From a1d126c8aae90bc7aa520cab4e623dd5858afc33 Mon Sep 17 00:00:00 2001 From: Swofty Date: Sat, 28 Feb 2026 03:01:40 +1100 Subject: [PATCH 12/17] refactor(elections): remove mutable enum state and delegate operations to service Remove mutable color field from SkyBlockMayor, use ElectionData.colorForIndex() instead. Remove local resolveElection/saveToService from ElectionManager, delegate to service endpoints. Fix loadFromService to not require minister for special mayors. --- .../elections/ElectionData.java | 164 ++---------------- .../elections/ElectionManager.java | 116 +++++++------ .../elections/SkyBlockMayor.java | 18 -- 3 files changed, 76 insertions(+), 222 deletions(-) diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java index 4e4878d0b..dec3cdd72 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionData.java @@ -27,7 +27,6 @@ public class ElectionData { private String ministerPerk; private List candidates = new ArrayList<>(); - private transient Map votes = new HashMap<>(); private Map voteTallies = new HashMap<>(); private boolean electionOpen; @@ -42,7 +41,7 @@ public ElectionData() {} public SkyBlockMayor getMayorEnum() { if (currentMayor == null) return null; try { - return SkyBlockMayor.valueOf(currentMayor).setColor(currentMayorColor); + return SkyBlockMayor.valueOf(currentMayor); } catch (IllegalArgumentException e) { return null; } @@ -51,7 +50,7 @@ public SkyBlockMayor getMayorEnum() { public SkyBlockMayor getMinisterEnum() { if (currentMinister == null) return null; try { - return SkyBlockMayor.valueOf(currentMinister).setColor(currentMinisterColor); + return SkyBlockMayor.valueOf(currentMinister); } catch (IllegalArgumentException e) { return null; } @@ -77,17 +76,7 @@ public List getCurrentMayorPerkEnums() { } public Map tallyVotes() { - if (!voteTallies.isEmpty()) { - return new HashMap<>(voteTallies); - } - Map tally = new HashMap<>(); - for (CandidateData candidate : candidates) { - tally.put(candidate.getMayorName(), 0L); - } - for (String candidateName : votes.values()) { - tally.merge(candidateName, 1L, Long::sum); - } - return tally; + return new HashMap<>(voteTallies); } public void updateTallies(Map newTallies) { @@ -95,132 +84,9 @@ public void updateTallies(Map newTallies) { voteTallies.putAll(newTallies); } - public void incrementTally(String candidateName, String previousVote) { - if (previousVote != null) { - voteTallies.computeIfPresent(previousVote, (k, v) -> Math.max(0, v - 1)); - } - voteTallies.merge(candidateName, 1L, Long::sum); - } - - public void resolveElection(int currentYear) { - Map tally = tallyVotes(); - List> sorted = new ArrayList<>(tally.entrySet()); - sorted.sort((a, b) -> Long.compare(b.getValue(), a.getValue())); - - if (sorted.isEmpty()) return; - - long topVotes = sorted.getFirst().getValue(); - List> tied = sorted.stream() - .filter(e -> e.getValue() == topVotes).toList(); - - String winnerName; - if (tied.size() > 1) { - winnerName = tied.get(ThreadLocalRandom.current().nextInt(tied.size())).getKey(); - } else { - winnerName = sorted.getFirst().getKey(); - } - - SkyBlockMayor winner = SkyBlockMayor.valueOf(winnerName); - - CandidateData winnerCandidate = candidates.stream() - .filter(c -> c.getMayorName().equals(winnerName)) - .findFirst().orElse(null); - - currentMayor = winnerName; - currentMayorColor = winner.getColor(); - currentMayorPerks = winnerCandidate != null - ? new ArrayList<>(winnerCandidate.getActivePerks()) - : Arrays.stream(winner.getAllPerks()).map(Enum::name).toList(); - mayorElectedYear = currentYear; - lastElectedYear.put(winnerName, currentYear); - - if (winner.isSpecial()) { - currentMinister = null; - ministerPerk = null; - currentMinisterColor = null; - } else { - String secondPlace = sorted.stream().filter(entry -> !entry.getKey().equals(winnerName)).findFirst().map(Map.Entry::getKey).orElse(null); - if (secondPlace != null) { - SkyBlockMayor ministerMayor = SkyBlockMayor.valueOf(secondPlace); - currentMinister = secondPlace; - currentMinisterColor = ministerMayor.getColor(); - - CandidateData ministerCandidate = candidates.stream() - .filter(c -> c.getMayorName().equals(secondPlace)) - .findFirst().orElse(null); - - if (ministerCandidate != null && !ministerCandidate.getActivePerks().isEmpty()) { - List perks = ministerCandidate.getActivePerks(); - ministerPerk = perks.get(ThreadLocalRandom.current().nextInt(perks.size())); - } else { - SkyBlockMayor.Perk[] allPerks = ministerMayor.getAllPerks(); - ministerPerk = allPerks[ThreadLocalRandom.current().nextInt(allPerks.length)].name(); - } - } - } - - for (CandidateData candidate : candidates) { - if (candidate.getMayorName().equals(winnerName)) { - candidateActivePerks.remove(winnerName); - failedPerkGainLastTime.remove(winnerName); - continue; - } - - SkyBlockMayor mayor = SkyBlockMayor.valueOf(candidate.getMayorName()); - if (mayor.isSpecial()) continue; - - List currentPerks = new ArrayList<>(candidate.getActivePerks()); - if (currentPerks.size() < mayor.getAllPerks().length) { - boolean failedLast = Boolean.TRUE.equals(failedPerkGainLastTime.get(candidate.getMayorName())); - boolean gainPerk = failedLast || ThreadLocalRandom.current().nextBoolean(); - - if (gainPerk) { - List available = new ArrayList<>(); - for (SkyBlockMayor.Perk perk : mayor.getAllPerks()) { - if (!currentPerks.contains(perk.name())) { - available.add(perk.name()); - } - } - if (!available.isEmpty()) { - currentPerks.add(available.get(ThreadLocalRandom.current().nextInt(available.size()))); - } - failedPerkGainLastTime.put(candidate.getMayorName(), false); - } else { - failedPerkGainLastTime.put(candidate.getMayorName(), true); - } - } - candidateActivePerks.put(candidate.getMayorName(), currentPerks); - } - - SkyBlockMayor winnerEnum = SkyBlockMayor.valueOf(winnerName); - if (!winnerEnum.isSpecial()) { - SkyBlockMayor.Perk[] allPerks = winnerEnum.getAllPerks(); - SkyBlockMayor.Perk randomPerk = allPerks[ThreadLocalRandom.current().nextInt(allPerks.length)]; - candidateActivePerks.put(winnerName, List.of(randomPerk.name())); - } - - long totalVoteCount = tally.values().stream().mapToLong(Long::longValue).sum(); - ElectionResult electionResult = new ElectionResult(); - electionResult.setYear(currentYear); - for (Map.Entry entry : sorted) { - CandidateResult cr = new CandidateResult(); - cr.setMayorName(entry.getKey()); - cr.setVotes(entry.getValue()); - cr.setPercentage(totalVoteCount > 0 ? (entry.getValue() * 100.0) / totalVoteCount : 0); - electionResult.getCandidateResults().add(cr); - } - this.lastElectionResult = electionResult; - - candidates.clear(); - votes.clear(); - voteTallies.clear(); - electionOpen = false; - } - public void startNewElection(int year) { this.electionYear = year; this.electionOpen = true; - this.votes.clear(); this.voteTallies.clear(); this.candidates.clear(); @@ -258,7 +124,7 @@ public void startNewElection(int year) { CandidateData candidate = new CandidateData(); candidate.setMayorName(specialCandidate.name()); - candidate.setIndex(selected.indexOf(specialCandidate)); + candidate.setIndex(candidates.size()); candidate.setActivePerks(Arrays.stream(specialCandidate.getAllPerks()).map(Enum::name).toList()); candidates.add(candidate); } @@ -274,7 +140,7 @@ public void startNewElection(int year) { if (!alreadyInElection) { CandidateData diazCandidate = new CandidateData(); diazCandidate.setMayorName(SkyBlockMayor.DIAZ.name()); - diazCandidate.setIndex(selected.indexOf(SkyBlockMayor.DIAZ)); + diazCandidate.setIndex(candidates.size()); diazCandidate.setActivePerks(Arrays.stream(SkyBlockMayor.DIAZ.getAllPerks()).map(Enum::name).toList()); candidates.add(diazCandidate); } @@ -287,6 +153,17 @@ public int getYearsSinceLastElected(String mayorName, int currentYear) { return currentYear - lastYear; } + public static String colorForIndex(int index) { + return switch (index) { + case 0 -> "§c"; + case 1 -> "§a"; + case 2 -> "§b"; + case 3 -> "§e"; + case 4 -> "§d"; + default -> "§f"; + }; + } + @Getter @Setter public static class CandidateData { @@ -315,14 +192,7 @@ public List getActivePerkEnums() { } public String getColor() { - return switch (index) { - case 0 -> "§c"; - case 1 -> "§a"; - case 2 -> "§b"; - case 3 -> "§e"; - case 4 -> "§d"; - default -> "§f"; - }; + return colorForIndex(index); } public String getColoredName() { diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java index f79d8e238..d98f19010 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java @@ -10,7 +10,8 @@ import net.swofty.commons.protocol.objects.election.GetCandidatesProtocolObject; import net.swofty.commons.protocol.objects.election.GetElectionDataProtocolObject; import net.swofty.commons.protocol.objects.election.GetPlayerVoteProtocolObject; -import net.swofty.commons.protocol.objects.election.SaveElectionDataProtocolObject; +import net.swofty.commons.protocol.objects.election.ResolveElectionProtocolObject; +import net.swofty.commons.protocol.objects.election.StartElectionProtocolObject; import net.swofty.proxyapi.ProxyService; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import org.tinylog.Logger; @@ -43,17 +44,15 @@ public static void loadFromService() { if (response.found() && response.serializedData() != null) { electionData = GSON.fromJson(response.serializedData(), ElectionData.class); - if (electionData.getCurrentMayor() == null || electionData.getCurrentMinister() == null) { + if (electionData.getCurrentMayor() == null) { electionData = new ElectionData(); initializeFirstElection(); - saveToService(); - Logger.info("Election data was missing mayor or minister info. Reinitialized first election."); + Logger.info("Election data was missing mayor info. Reinitialized first election."); } } else { electionData = new ElectionData(); initializeFirstElection(); - saveToService(); - Logger.info("Election data was missing mayor or minister info."); + Logger.info("No election data found. Initialized first election."); } } catch (Exception e) { Logger.error(e, "Failed to load election data from service"); @@ -64,27 +63,15 @@ public static void loadFromService() { startTallyRefreshTask(); } - public static void saveToService() { - try { - String serialized = GSON.toJson(electionData); - SERVICE.handleRequest( - new SaveElectionDataProtocolObject.SaveElectionDataMessage(serialized) - ); - } catch (Exception e) { - Logger.error(e, "Failed to save election data to service"); - } - } - private static void initializeFirstElection() { int currentYear = SkyBlockCalendar.getYear(); electionData.setCurrentMayor(SkyBlockMayor.COLE.name()); - electionData.setCurrentMayorColor("§d"); + electionData.setCurrentMayorColor(ElectionData.colorForIndex(4)); electionData.setCurrentMayorPerks(Arrays.stream(SkyBlockMayor.COLE.getAllPerks()).map(Enum::name).toList()); electionData.setMayorElectedYear(currentYear); electionData.setCurrentMinister(SkyBlockMayor.DIAZ.name()); electionData.setMinisterPerk(SkyBlockMayor.Perk.STOCK_EXCHANGE.name()); - electionData.setCurrentMinisterColor("§c"); + electionData.setCurrentMinisterColor(ElectionData.colorForIndex(0)); } public static void onElectionStart() { @@ -92,20 +79,55 @@ public static void onElectionStart() { if (electionData.isElectionOpen()) return; electionData.startNewElection(currentYear); - saveToService(); - Logger.info("Election started for Year {}", currentYear); + String serialized = GSON.toJson(electionData); + + try { + StartElectionProtocolObject.StartElectionResponse response = + SERVICE.handleRequest( + new StartElectionProtocolObject.StartElectionMessage(currentYear, serialized) + ).join(); + + if (response.serializedData() != null) { + electionData = GSON.fromJson(response.serializedData(), ElectionData.class); + } + + if (response.started()) { + Logger.info("Election started for Year {}", currentYear); + } else { + Logger.info("Election for Year {} was already started by another server", currentYear); + } + } catch (Exception e) { + Logger.error(e, "Failed to start election via service"); + } } public static void onElectionEnd() { if (!electionData.isElectionOpen()) return; - refreshTalliesSync(); - int currentYear = SkyBlockCalendar.getYear(); - electionData.resolveElection(currentYear); + + try { + ResolveElectionProtocolObject.ResolveElectionResponse response = + SERVICE.handleRequest( + new ResolveElectionProtocolObject.ResolveElectionMessage(currentYear) + ).join(); + + if (response.serializedData() != null) { + electionData = GSON.fromJson(response.serializedData(), ElectionData.class); + } + + if (response.resolved()) { + Logger.info("Election resolved for Year {}. New Mayor: {}", currentYear, electionData.getCurrentMayor()); + } else { + Logger.info("Election for Year {} was already resolved by another server", currentYear); + } + } catch (Exception e) { + Logger.error(e, "Failed to resolve election via service"); + } + playerVoteCache.clear(); - saveToService(); - Logger.info("Election resolved for Year {}. New Mayor: {}", currentYear, electionData.getCurrentMayor()); } public static CompletableFuture castVote(UUID accountId, String candidateName) { @@ -115,22 +137,22 @@ public static CompletableFuture castVote(UUID accountId, String candidateN .anyMatch(c -> c.getMayorName().equals(candidateName)); if (!validCandidate) return CompletableFuture.completedFuture(null); - String previousVote = playerVoteCache.put(accountId, candidateName); - electionData.incrementTally(candidateName, previousVote); - return SERVICE.handleRequest( new CastVoteProtocolObject.CastVoteMessage(accountId, candidateName) ).thenAccept(response -> { - if (response.success() && response.talliesJson() != null) { - Map tallies = GSON.fromJson( - response.talliesJson(), - new TypeToken>(){}.getType() - ); - electionData.updateTallies(tallies); + if (response.success()) { + playerVoteCache.put(accountId, candidateName); + if (response.talliesJson() != null) { + Map tallies = GSON.fromJson( + response.talliesJson(), + new TypeToken>(){}.getType() + ); + electionData.updateTallies(tallies); + } } }).exceptionally(e -> { - Logger.error(e, "Failed to sync vote to service"); + Logger.error(e, "Failed to cast vote via service"); return null; }); } @@ -227,24 +249,4 @@ private static void refreshTalliesAsync() { return null; }); } - - private static void refreshTalliesSync() { - try { - GetCandidatesProtocolObject.GetCandidatesResponse response = - SERVICE.handleRequest( - new GetCandidatesProtocolObject.GetCandidatesMessage() - ).join(); - - if (response.electionOpen()) { - Map tallies = new HashMap<>(); - for (GetCandidatesProtocolObject.CandidateInfo info : response.candidates()) { - tallies.put(info.mayorName(), info.votes()); - } - electionData.updateTallies(tallies); - } - } catch (Exception e) { - Logger.error(e, "Failed to sync tallies before election resolution"); - } - } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java index 56134a49f..8504de883 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/SkyBlockMayor.java @@ -89,7 +89,6 @@ public enum SkyBlockMayor { private final String texture; private final String signature; private final Perk[] allPerks; - private String color; SkyBlockMayor(String displayName, boolean special, String texture, String signature, Perk[] allPerks) { this.displayName = displayName; @@ -107,23 +106,6 @@ public static List getSpecialMayors() { return Arrays.stream(values()).filter(m -> m.special).toList(); } - public SkyBlockMayor setColor(String color) { - this.color = color; - return this; - } - - public SkyBlockMayor setColorFromIndex(int index) { - String color = switch (index) { - case 0 -> "§c"; - case 1 -> "§a"; - case 2 -> "§b"; - case 3 -> "§e"; - case 4 -> "§d"; - default -> "§f"; - }; - return setColor(color); - } - @Getter public enum Perk { SLASHED_PRICING("SLASHED Pricing", "§7Starting slayer quests is §ehalf price§7."), From 7de8cda994a5a9b5303eef59faa487d1943e2d7b Mon Sep 17 00:00:00 2001 From: Swofty Date: Sat, 28 Feb 2026 03:02:01 +1100 Subject: [PATCH 13/17] refactor(elections): deduplicate NPCs with abstract bases, fix ElectionDisplay thread safety Extract AbstractCandidateNPC and AbstractCurrentMayorNPC to eliminate duplicated NPC logic. Fix ElectionDisplay HashMap to ConcurrentHashMap with player cleanup. --- .../net/swofty/type/hub/ElectionDisplay.java | 36 +++++-- .../npcs/election/AbstractCandidateNPC.java | 96 +++++++++++++++++++ .../election/AbstractCurrentMayorNPC.java | 63 ++++++++++++ .../type/hub/npcs/election/NPCCandidate1.java | 71 +------------- .../type/hub/npcs/election/NPCCandidate2.java | 71 +------------- .../type/hub/npcs/election/NPCCandidate3.java | 71 +------------- .../type/hub/npcs/election/NPCCandidate4.java | 71 +------------- .../type/hub/npcs/election/NPCCandidate5.java | 71 +------------- .../election/NPCClerkSeraphineDuplicate.java | 13 ++- .../hub/npcs/election/NPCCurrentMayor.java | 53 +--------- .../election/NPCCurrentMayorDuplicate.java | 53 +--------- .../hub/npcs/election/NPCCurrentMinister.java | 19 ++-- 12 files changed, 217 insertions(+), 471 deletions(-) create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/AbstractCandidateNPC.java create mode 100644 type.hub/src/main/java/net/swofty/type/hub/npcs/election/AbstractCurrentMayorNPC.java diff --git a/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java b/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java index 837e71340..5040dc1eb 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java +++ b/type.hub/src/main/java/net/swofty/type/hub/ElectionDisplay.java @@ -4,38 +4,54 @@ import net.swofty.commons.StringUtility; import net.swofty.type.generic.HypixelGenericLoader; import net.swofty.type.generic.entity.hologram.PlayerHolograms; +import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.calendar.CalendarEvent; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; +import net.swofty.type.skyblockgeneric.elections.ElectionData; import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; public class ElectionDisplay { - private static final Map holos = new HashMap<>(); + private static final Map holos = new ConcurrentHashMap<>(); public static void addAndUpdate() { + Set loadedUuids = HypixelGenericLoader.getLoadedPlayers().stream() + .map(HypixelPlayer::getUuid) + .collect(Collectors.toSet()); + holos.keySet().removeIf(p -> !loadedUuids.contains(p.getUuid())); + HypixelGenericLoader.getLoadedPlayers().forEach(player -> { + Locale l = player.getLocale(); long timeLeft = SkyBlockCalendar.ticksUntilEvent(CalendarEvent.ELECTION_CLOSE); String timeLeftFormatted = StringUtility.formatTimeLeft(timeLeft * 50L); List message = new ArrayList<>(List.of( - "§e§lMAYOR ELECTIONS", - "§bYear " + SkyBlockCalendar.getYear(), - "§eTime left: §a" + timeLeftFormatted + I18n.string("gui_election.display.title", l), + I18n.string("gui_election.display.year", l, Map.of("year", String.valueOf(SkyBlockCalendar.getYear()))), + I18n.string("gui_election.display.time_left", l, Map.of("time", timeLeftFormatted)) )); String vote = ElectionManager.getPlayerVote(player.getUuid()); if (vote != null) { - SkyBlockMayor mayor = SkyBlockMayor.valueOf(vote); - String colouredName = mayor.getColor() + mayor.getDisplayName(); - message.add("§eYour vote: §f" + colouredName); - message.add("§e§lCLICK TO SWITCH"); + ElectionData data = ElectionManager.getElectionData(); + ElectionData.CandidateData candidateData = data.getCandidates().stream() + .filter(c -> c.getMayorName().equals(vote)) + .findFirst().orElse(null); + if (candidateData != null) { + message.add(I18n.string("gui_election.display.your_vote", l, + Map.of("candidate", candidateData.getColoredName()))); + message.add(I18n.string("gui_election.display.click_switch", l)); + } } if (!holos.containsKey(player)) { diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/AbstractCandidateNPC.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/AbstractCandidateNPC.java new file mode 100644 index 000000000..9d5f9ef9f --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/AbstractCandidateNPC.java @@ -0,0 +1,96 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.i18n.I18n; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionData; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public abstract class AbstractCandidateNPC extends HypixelNPC { + private final int index; + + private static ElectionData.CandidateData getCandidateData(int index) { + ElectionData data = ElectionManager.getElectionData(); + if (!data.isElectionOpen()) return null; + List candidates = data.getCandidates(); + if (candidates.size() <= index) return null; + return candidates.get(index); + } + + protected AbstractCandidateNPC(int index, Pos candidatePosition) { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + ElectionData.CandidateData candidateData = getCandidateData(index); + if (candidateData == null) return new String[]{ + I18n.string("npcs_hub.election.mayor_unknown", player.getLocale()), + I18n.string("npcs_hub.election.candidate_label", player.getLocale()), + I18n.string("npcs_hub.election.click", player.getLocale()) + }; + String color = candidateData.getColor(); + SkyBlockMayor mayor = candidateData.getMayorEnum(); + String name = mayor != null ? mayor.getDisplayName() : candidateData.getMayorName(); + return new String[]{ + color + name, + color + I18n.string("npcs_hub.election.candidate_label", player.getLocale()), + I18n.string("npcs_hub.election.click", player.getLocale()) + }; + } + + @Override + public String signature(HypixelPlayer player) { + ElectionData.CandidateData candidateData = getCandidateData(index); + if (candidateData == null) return ""; + SkyBlockMayor mayor = candidateData.getMayorEnum(); + return mayor != null ? mayor.getSignature() : ""; + } + + @Override + public boolean visible(HypixelPlayer player) { + return getCandidateData(index) != null; + } + + @Override + public String texture(HypixelPlayer player) { + ElectionData.CandidateData candidateData = getCandidateData(index); + if (candidateData == null) return ""; + SkyBlockMayor mayor = candidateData.getMayorEnum(); + return mayor != null ? mayor.getTexture() : ""; + } + + @Override + public Pos position(HypixelPlayer player) { + return candidatePosition; + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public @NonNull String chatName() { + ElectionData.CandidateData candidateData = getCandidateData(index); + if (candidateData == null) return "Mayor ???"; + String color = candidateData.getColor(); + SkyBlockMayor mayor = candidateData.getMayorEnum(); + String name = mayor != null ? mayor.getDisplayName() : candidateData.getMayorName(); + return color + "Mayor " + name; + } + }); + this.index = index; + } + + @Override + public void onClick(NPCInteractEvent event) { + if (getCandidateData(index) == null) return; + sendNPCMessage(event.player(), I18n.string("npcs_hub.election.running", event.player().getLocale())); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/AbstractCurrentMayorNPC.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/AbstractCurrentMayorNPC.java new file mode 100644 index 000000000..3c8699e23 --- /dev/null +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/AbstractCurrentMayorNPC.java @@ -0,0 +1,63 @@ +package net.swofty.type.hub.npcs.election; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.i18n.I18n; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.elections.ElectionManager; +import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; +import net.swofty.type.skyblockgeneric.gui.inventories.election.MayorMenuView; + +public abstract class AbstractCurrentMayorNPC extends HypixelNPC { + + protected AbstractCurrentMayorNPC(Pos mayorPosition) { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) return new String[]{ + I18n.string("npcs_hub.election.mayor_unknown", player.getLocale()), + I18n.string("npcs_hub.election.click", player.getLocale()) + }; + return new String[]{ + "Mayor " + mayor.getDisplayName(), + I18n.string("npcs_hub.election.click", player.getLocale()) + }; + } + + @Override + public String signature(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + return mayor != null ? mayor.getSignature() : ""; + } + + @Override + public String texture(HypixelPlayer player) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + return mayor != null ? mayor.getTexture() : ""; + } + + @Override + public Pos position(HypixelPlayer player) { + return mayorPosition; + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); + if (mayor == null) { + event.player().sendMessage(I18n.string("npcs_hub.election.hello", event.player().getLocale())); + return; + } + event.player().openView(new MayorMenuView()); + } +} diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate1.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate1.java index 9b8532d0f..bcb53cb92 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate1.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate1.java @@ -1,76 +1,9 @@ package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionData; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import org.jspecify.annotations.NonNull; - -import java.util.List; - -public class NPCCandidate1 extends HypixelNPC { - private static final int INDEX = 0; - - private static SkyBlockMayor getCandidate() { - ElectionData data = ElectionManager.getElectionData(); - if (!data.isElectionOpen()) return null; - List candidates = data.getCandidates(); - if (candidates.size() <= INDEX) return null; - return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); - } +public class NPCCandidate1 extends AbstractCandidateNPC { public NPCCandidate1() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; - return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; - } - - @Override - public String signature(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getSignature() : ""; - } - - @Override - public boolean visible(HypixelPlayer player) { - return getCandidate() != null; - } - - @Override - public String texture(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getTexture() : ""; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(-11.5, 50.0625, 34.5, -90, 0); - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - - @Override - public @NonNull String chatName() { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return; - sendNPCMessage(event.player(), "Running for mayor!"); + super(0, new Pos(-11.5, 50.0625, 34.5, -90, 0)); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate2.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate2.java index 5b9afaa80..3ef60055e 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate2.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate2.java @@ -1,76 +1,9 @@ package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionData; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import org.jspecify.annotations.NonNull; - -import java.util.List; - -public class NPCCandidate2 extends HypixelNPC { - private static final int INDEX = 1; - - private static SkyBlockMayor getCandidate() { - ElectionData data = ElectionManager.getElectionData(); - if (!data.isElectionOpen()) return null; - List candidates = data.getCandidates(); - if (candidates.size() <= INDEX) return null; - return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); - } +public class NPCCandidate2 extends AbstractCandidateNPC { public NPCCandidate2() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; - return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; - } - - @Override - public String signature(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getSignature() : ""; - } - - @Override - public boolean visible(HypixelPlayer player) { - return getCandidate() != null; - } - - @Override - public String texture(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getTexture() : ""; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(-8.5, 50.0625, 25.5, -45, 0); - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - - @Override - public @NonNull String chatName() { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return; - sendNPCMessage(event.player(), "Running for mayor!"); + super(1, new Pos(-8.5, 50.0625, 25.5, -45, 0)); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate3.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate3.java index f4e8681d6..815eefd4d 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate3.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate3.java @@ -1,76 +1,9 @@ package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionData; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import org.jspecify.annotations.NonNull; - -import java.util.List; - -public class NPCCandidate3 extends HypixelNPC { - private static final int INDEX = 2; - - private static SkyBlockMayor getCandidate() { - ElectionData data = ElectionManager.getElectionData(); - if (!data.isElectionOpen()) return null; - List candidates = data.getCandidates(); - if (candidates.size() <= INDEX) return null; - return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); - } +public class NPCCandidate3 extends AbstractCandidateNPC { public NPCCandidate3() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; - return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; - } - - @Override - public String signature(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getSignature() : ""; - } - - @Override - public boolean visible(HypixelPlayer player) { - return getCandidate() != null; - } - - @Override - public String texture(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getTexture() : ""; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(0.5, 50.0625, 22.5, 0, 0); - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - - @Override - public @NonNull String chatName() { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return; - sendNPCMessage(event.player(), "Running for mayor!"); + super(2, new Pos(0.5, 50.0625, 22.5, 0, 0)); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate4.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate4.java index 8af7554fb..fb2603ea1 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate4.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate4.java @@ -1,76 +1,9 @@ package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionData; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import org.jspecify.annotations.NonNull; - -import java.util.List; - -public class NPCCandidate4 extends HypixelNPC { - private static final int INDEX = 3; - - private static SkyBlockMayor getCandidate() { - ElectionData data = ElectionManager.getElectionData(); - if (!data.isElectionOpen()) return null; - List candidates = data.getCandidates(); - if (candidates.size() <= INDEX) return null; - return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); - } +public class NPCCandidate4 extends AbstractCandidateNPC { public NPCCandidate4() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; - return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; - } - - @Override - public String signature(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getSignature() : ""; - } - - @Override - public boolean visible(HypixelPlayer player) { - return getCandidate() != null; - } - - @Override - public String texture(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getTexture() : ""; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(9.5, 50.0625, 25.5, 45, 0); - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - - @Override - public @NonNull String chatName() { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return; - sendNPCMessage(event.player(), "Running for mayor!"); + super(3, new Pos(9.5, 50.0625, 25.5, 45, 0)); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate5.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate5.java index a6d0ce717..c3aab4402 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate5.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCandidate5.java @@ -1,76 +1,9 @@ package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionData; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import org.jspecify.annotations.NonNull; - -import java.util.List; - -public class NPCCandidate5 extends HypixelNPC { - private static final int INDEX = 4; - - private static SkyBlockMayor getCandidate() { - ElectionData data = ElectionManager.getElectionData(); - if (!data.isElectionOpen()) return null; - List candidates = data.getCandidates(); - if (candidates.size() <= INDEX) return null; - return candidates.get(INDEX).getMayorEnum().setColorFromIndex(INDEX); - } +public class NPCCandidate5 extends AbstractCandidateNPC { public NPCCandidate5() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return new String[]{"Mayor ???", "Candidate", "§e§lCLICK"}; - return new String[]{mayor.getColor() + mayor.getDisplayName(), mayor.getColor() + "Candidate", "§e§lCLICK"}; - } - - @Override - public String signature(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getSignature() : ""; - } - - @Override - public boolean visible(HypixelPlayer player) { - return getCandidate() != null; - } - - @Override - public String texture(HypixelPlayer player) { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getTexture() : ""; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(12.5, 50.0625, 34.5, 90, 0); - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - - @Override - public @NonNull String chatName() { - SkyBlockMayor mayor = getCandidate(); - return mayor != null ? mayor.getColor() + "Mayor " + mayor.getDisplayName() : "Mayor ???"; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - SkyBlockMayor mayor = getCandidate(); - if (mayor == null) return; - sendNPCMessage(event.player(), "Running for mayor!"); + super(4, new Pos(12.5, 50.0625, 34.5, 90, 0)); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCClerkSeraphineDuplicate.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCClerkSeraphineDuplicate.java index 169cecdf5..5566ef1ea 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCClerkSeraphineDuplicate.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCClerkSeraphineDuplicate.java @@ -4,6 +4,7 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import java.util.stream.Stream; @@ -14,7 +15,10 @@ public NPCClerkSeraphineDuplicate() { super(new HumanConfiguration() { @Override public String[] holograms(HypixelPlayer player) { - return new String[]{"Clerk Seraphine", "§e§lCLICK"}; + return new String[]{ + I18n.string("npcs_hub.election.clerk_seraphine", player.getLocale()), + I18n.string("npcs_hub.election.click", player.getLocale()) + }; } @Override @@ -48,12 +52,7 @@ public void onClick(NPCInteractEvent e) { @Override public DialogueSet[] dialogues(HypixelPlayer player) { return Stream.of( - DialogueSet.builder() - .key("hello").lines(new String[]{ - "Welcome to the §bCommunity Center§f!", - "Contribute to community projects, upgrade your account, and more by talking to §dElizabeth§f!", - "You can also vote in the §bmayor elections §fby heading through the warp behind me!" - }).build() + DialogueSet.ofTranslation("hello", "npcs_hub.clerk_seraphine.dialogue.hello", player) ).toArray(DialogueSet[]::new); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayor.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayor.java index 3debc5f06..cb645bf6d 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayor.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayor.java @@ -1,58 +1,9 @@ package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import net.swofty.type.skyblockgeneric.gui.inventories.election.MayorMenuView; - -public class NPCCurrentMayor extends HypixelNPC { +public class NPCCurrentMayor extends AbstractCurrentMayorNPC { public NPCCurrentMayor() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) return new String[]{"Mayor ???", "§e§lCLICK"}; - return new String[]{"Mayor " + mayor.getDisplayName(), "§e§lCLICK"}; - } - - @Override - public String signature(HypixelPlayer player) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) return ""; - return mayor.getSignature(); - } - - @Override - public String texture(HypixelPlayer player) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) return ""; - return mayor.getTexture(); - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(6.5, 79, 19.5, 135, 0); - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) { - event.player().sendMessage("§cHello!!"); - return; - } - event.player().openView(new MayorMenuView()); + super(new Pos(6.5, 79, 19.5, 135, 0)); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayorDuplicate.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayorDuplicate.java index dc43ef856..88a846a0f 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayorDuplicate.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMayorDuplicate.java @@ -1,58 +1,9 @@ package net.swofty.type.hub.npcs.election; import net.minestom.server.coordinate.Pos; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skyblockgeneric.elections.ElectionManager; -import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; -import net.swofty.type.skyblockgeneric.gui.inventories.election.MayorMenuView; - -public class NPCCurrentMayorDuplicate extends HypixelNPC { +public class NPCCurrentMayorDuplicate extends AbstractCurrentMayorNPC { public NPCCurrentMayorDuplicate() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) return new String[]{"Mayor ???", "§e§lCLICK"}; - return new String[]{"Mayor " + mayor.getDisplayName(), "§e§lCLICK"}; - } - - @Override - public String signature(HypixelPlayer player) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) return ""; - return mayor.getSignature(); - } - - @Override - public String texture(HypixelPlayer player) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) return ""; - return mayor.getTexture(); - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(-3.5, 49, 34.5, 0, 0); - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) { - event.player().sendMessage("§cHello!!"); - return; - } - event.player().openView(new MayorMenuView()); + super(new Pos(-3.5, 49, 34.5, 0, 0)); } } diff --git a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMinister.java b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMinister.java index 47d5a486f..14c7816a9 100644 --- a/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMinister.java +++ b/type.hub/src/main/java/net/swofty/type/hub/npcs/election/NPCCurrentMinister.java @@ -4,6 +4,7 @@ import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.i18n.I18n; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; @@ -16,22 +17,26 @@ public NPCCurrentMinister() { @Override public String[] holograms(HypixelPlayer player) { SkyBlockMayor minister = ElectionManager.getCurrentMinister(); - if (minister == null) return new String[]{"Minister ????", "§e§lCLICK"}; - return new String[]{"Minister " + minister.getDisplayName(), "§e§lCLICK"}; + if (minister == null) return new String[]{ + I18n.string("npcs_hub.election.minister_unknown", player.getLocale()), + I18n.string("npcs_hub.election.click", player.getLocale()) + }; + return new String[]{ + "Minister " + minister.getDisplayName(), + I18n.string("npcs_hub.election.click", player.getLocale()) + }; } @Override public String signature(HypixelPlayer player) { SkyBlockMayor minister = ElectionManager.getCurrentMinister(); - if (minister == null) return ""; - return minister.getSignature(); + return minister != null ? minister.getSignature() : ""; } @Override public String texture(HypixelPlayer player) { SkyBlockMayor minister = ElectionManager.getCurrentMinister(); - if (minister == null) return ""; - return minister.getTexture(); + return minister != null ? minister.getTexture() : ""; } @Override @@ -50,7 +55,7 @@ public boolean looking(HypixelPlayer player) { public void onClick(NPCInteractEvent event) { SkyBlockMayor minister = ElectionManager.getCurrentMinister(); if (minister == null) { - event.player().sendMessage("§cHello!!"); + event.player().sendMessage(I18n.string("npcs_hub.election.hello", event.player().getLocale())); return; } event.player().openView(new MinisterMenuView()); From 032575cec6e966f01c5701bf3e6f2062f0d3b7c7 Mon Sep 17 00:00:00 2001 From: Swofty Date: Sat, 28 Feb 2026 03:02:21 +1100 Subject: [PATCH 14/17] feat(i18n): migrate election GUIs, NPCs, and holograms to translation system Add gui_election.properties for GUI strings and election NPC keys to npcs_hub. Migrate ElectionView, ElectionViewStatsView, MayorMenuView, MinisterMenuView, ElectionDisplay holograms, and all election NPCs to use I18n.string() with per-player locale. --- .../i18n/en_US/gui/gui_election.properties | 57 +++++++++++++ .../i18n/en_US/npcs/npcs_hub.properties | 9 +++ .../inventories/election/ElectionView.java | 68 +++++++++------- .../election/ElectionViewStatsView.java | 80 ++++++++++++------- .../inventories/election/MayorMenuView.java | 53 +++++++----- .../election/MinisterMenuView.java | 53 +++++++----- 6 files changed, 226 insertions(+), 94 deletions(-) create mode 100644 configuration/i18n/en_US/gui/gui_election.properties diff --git a/configuration/i18n/en_US/gui/gui_election.properties b/configuration/i18n/en_US/gui/gui_election.properties new file mode 100644 index 000000000..f2f36c71e --- /dev/null +++ b/configuration/i18n/en_US/gui/gui_election.properties @@ -0,0 +1,57 @@ +# ============================================================================= +# Election GUI Translations +# ============================================================================= + +# --- ElectionView (Voting GUI) --- +gui_election.view.title = Election +gui_election.view.no_election = §cNo Active Election +gui_election.view.no_election.lore = §7There is no active election\n§7at this time. +gui_election.view.candidate.year = §8Year {year} Candidate +gui_election.view.candidate.votes = §7Votes: {color}{votes} §7({color}{percentage}§7) +gui_election.view.candidate.last_elected = §7Last elected: {color}{years}y ago +gui_election.view.candidate.last_elected_never = §7Last elected: {color}Never +gui_election.view.candidate.minister_note_1 = §6✯ {color}Minister Perks §7are also granted if +gui_election.view.candidate.minister_note_2 = §7this mayor wins second place! +gui_election.view.candidate.voted = §aYou voted for this candidate! +gui_election.view.candidate.change_vote_1 = §8You may change your vote at any +gui_election.view.candidate.change_vote_2 = §8time until the election ends! +gui_election.view.candidate.click_vote = §eClick to vote for {name}! +gui_election.view.vote_divider = §c----------------------------------------------------- +gui_election.view.vote_cast = §eYou cast §c1 vote §efor {candidate} §ein the §bYear {year} Elections§e! +gui_election.view.vote_fame = §bNew player §eFame Rank §a+1 vote +gui_election.view.vote_result = {candidate} §enow has §c{percentage} §eof votes with §c{votes} votes§e! +gui_election.view.already_voted = §aYou voted for this candidate. + +# --- ElectionViewStatsView --- +gui_election.stats.title = Election, Year {year} +gui_election.stats.leader = {color}Leading in votes! + +# --- MayorMenuView --- +gui_election.mayor.title = Mayor {name} +gui_election.mayor.title_fallback = Mayor +gui_election.mayor.perks_label = §8Perks List +gui_election.mayor.perks_footer_1 = §7The listed perks are available to +gui_election.mayor.perks_footer_2 = §7all players until the closing of +gui_election.mayor.perks_footer_3 = §7the next elections. +gui_election.mayor.results_title = §bMayor Election Results +gui_election.mayor.results_no_data_1 = §7No previous election data +gui_election.mayor.results_no_data_2 = §7available. +gui_election.mayor.results_year = §8Year {year} +gui_election.mayor.results_footer_1 = §7These are the votes for the +gui_election.mayor.results_footer_2 = §7last election in which {name} +gui_election.mayor.results_footer_3 = §7was elected. + +# --- MinisterMenuView --- +gui_election.minister.title = Minister {name} +gui_election.minister.title_fallback = Minister +gui_election.minister.perk_label = §8Active Perk +gui_election.minister.perk_footer_1 = §7The Minister is who came in 2nd Place +gui_election.minister.perk_footer_2 = §7during the election. They have one +gui_election.minister.perk_footer_3 = §7of their perks active. + +# --- ElectionDisplay (Holograms) --- +gui_election.display.title = §e§lMAYOR ELECTIONS +gui_election.display.year = §bYear {year} +gui_election.display.time_left = §eTime left: §a{time} +gui_election.display.your_vote = §eYour vote: §f{candidate} +gui_election.display.click_switch = §e§lCLICK TO SWITCH diff --git a/configuration/i18n/en_US/npcs/npcs_hub.properties b/configuration/i18n/en_US/npcs/npcs_hub.properties index 4a962acd0..0a0f7472c 100644 --- a/configuration/i18n/en_US/npcs/npcs_hub.properties +++ b/configuration/i18n/en_US/npcs/npcs_hub.properties @@ -78,6 +78,15 @@ npcs_hub.elizabeth.dialogue.hello = Hello! Welcome to SkyBlockCommunity Center!|Contribute to community projects, upgrade your account, and more by talking to Elizabeth!|You can also vote in the mayor elections by heading through the warp behind me! +# --- Election NPCs --- +npcs_hub.election.clerk_seraphine = Clerk Seraphine +npcs_hub.election.candidate_label = Candidate +npcs_hub.election.click = §e§lCLICK +npcs_hub.election.running = Running for mayor! +npcs_hub.election.mayor_unknown = Mayor ??? +npcs_hub.election.minister_unknown = Minister ???? +npcs_hub.election.hello = §cHello!! + # --- Gladiator --- npcs_hub.gladiator.dialogue.hello = Welcome to the Colosseum!|Oh...wait. Nevermind.|Here you can join me in drinking away your sorrows. diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java index 7a2567e4f..da4b33241 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionView.java @@ -11,6 +11,7 @@ import net.swofty.type.generic.gui.v2.ViewConfiguration; import net.swofty.type.generic.gui.v2.ViewLayout; import net.swofty.type.generic.gui.v2.context.ViewContext; +import net.swofty.type.generic.i18n.I18n; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import net.swofty.type.skyblockgeneric.elections.ElectionData; import net.swofty.type.skyblockgeneric.elections.ElectionManager; @@ -18,13 +19,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class ElectionView extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>("Election", InventoryType.CHEST_3_ROW); + return ViewConfiguration.translatable("gui_election.view.title", InventoryType.CHEST_3_ROW); } @Override @@ -35,13 +37,15 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont ElectionData data = ElectionManager.getElectionData(); if (!data.isElectionOpen() || data.getCandidates().isEmpty()) { - layout.slot(13, (s, c) -> ItemStackCreator.getStack( - "§cNo Active Election", - Material.BARRIER, - 1, - "§7There is no active election", - "§7at this time." - )); + layout.slot(13, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack( + I18n.string("gui_election.view.no_election", l), + Material.BARRIER, + 1, + I18n.lore("gui_election.view.no_election.lore", l) + ); + }); return; } @@ -66,11 +70,12 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont String candidateName = candidate.getMayorName(); layout.slot(slot, (s, c) -> { + Locale l = c.player().getLocale(); String playerVote = ElectionManager.getPlayerVote(c.player().getUuid()); boolean isVotedFor = candidateName.equals(playerVote); List lore = buildCandidateLore( - mayor, candidate, data.getElectionYear(), + l, mayor, candidate, data.getElectionYear(), yearsSince, voteStr, pctStr, isVotedFor ); return ItemStackCreator.getStackHead( @@ -80,28 +85,37 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont lore ); }, (_, c) -> { + Locale l = c.player().getLocale(); ElectionManager.castVote(c.player().getUuid(), candidateName); - c.player().sendMessage("§c-----------------------------------------------------"); - c.player().sendMessage("§eYou cast §c1 vote §efor " + candidate.getColoredName() + " §ein the §bYear " + data.getElectionYear() + " Elections§e!"); - c.player().sendMessage(" §bNew player §eFame Rank §a+1 vote"); - c.player().sendMessage(candidate.getColoredName() + " §enow has §c" + pctStr + " §eof votes with §c" + voteStr + " votes§e!"); - c.player().sendMessage("§c-----------------------------------------------------"); + c.player().sendMessage(I18n.string("gui_election.view.vote_divider", l)); + c.player().sendMessage(I18n.string("gui_election.view.vote_cast", l, Map.of( + "candidate", candidate.getColoredName(), + "year", String.valueOf(data.getElectionYear())))); + c.player().sendMessage(" " + I18n.string("gui_election.view.vote_fame", l)); + c.player().sendMessage(I18n.string("gui_election.view.vote_result", l, Map.of( + "candidate", candidate.getColoredName(), + "percentage", pctStr, + "votes", voteStr))); + c.player().sendMessage(I18n.string("gui_election.view.vote_divider", l)); c.replace(new ElectionViewStatsView()); }); } } - private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.CandidateData candidate, + private List buildCandidateLore(Locale l, SkyBlockMayor mayor, ElectionData.CandidateData candidate, int electionYear, int yearsSince, String voteStr, String pctStr, boolean votedFor) { + String color = candidate.getColor(); List lore = new ArrayList<>(); - lore.add("§8Year " + electionYear + " Candidate"); + lore.add(I18n.string("gui_election.view.candidate.year", l, Map.of("year", String.valueOf(electionYear)))); lore.add(""); - lore.add("§7Votes: " + candidate.getColor() + voteStr + " §7(" + candidate.getColor() + pctStr + "§7)"); + lore.add(I18n.string("gui_election.view.candidate.votes", l, Map.of( + "color", color, "votes", voteStr, "percentage", pctStr))); if (yearsSince >= 0) { - lore.add("§7Last elected: " + candidate.getColor() + yearsSince + "y ago"); + lore.add(I18n.string("gui_election.view.candidate.last_elected", l, Map.of( + "color", color, "years", String.valueOf(yearsSince)))); } else { - lore.add("§7Last elected: " + candidate.getColor() + "Never"); + lore.add(I18n.string("gui_election.view.candidate.last_elected_never", l, Map.of("color", color))); } lore.add(""); lore.add("§8§m--------------------------"); @@ -110,10 +124,10 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid for (int j = 0; j < activePerks.size(); j++) { SkyBlockMayor.Perk perk = activePerks.get(j); if (j == 0) { - lore.add("§6✯ " + candidate.getColor() + perk.getDisplayName()); + lore.add("§6✯ " + color + perk.getDisplayName()); } else { lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor( - candidate.getColor() + perk.getDisplayName(), 35)); + color + perk.getDisplayName(), 35)); } lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor( perk.getDescription(), 35)); @@ -124,18 +138,18 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid if (!mayor.isSpecial()) { lore.add(""); - lore.add("§6✯ " + candidate.getColor() + "Minister Perks §7are also granted if"); - lore.add("§7this mayor wins second place!"); + lore.add(I18n.string("gui_election.view.candidate.minister_note_1", l, Map.of("color", color))); + lore.add(I18n.string("gui_election.view.candidate.minister_note_2", l)); } lore.add(""); if (votedFor) { - lore.add("§aYou voted for this candidate!"); + lore.add(I18n.string("gui_election.view.candidate.voted", l)); } else { - lore.add("§8You may change your vote at any"); - lore.add("§8time until the election ends!"); + lore.add(I18n.string("gui_election.view.candidate.change_vote_1", l)); + lore.add(I18n.string("gui_election.view.candidate.change_vote_2", l)); lore.add(""); - lore.add("§eClick to vote for " + mayor.getDisplayName() + "!"); + lore.add(I18n.string("gui_election.view.candidate.click_vote", l, Map.of("name", mayor.getDisplayName()))); } return lore; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java index 55f5183a5..6b4c31b84 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/ElectionViewStatsView.java @@ -11,6 +11,7 @@ import net.swofty.type.generic.gui.v2.ViewConfiguration; import net.swofty.type.generic.gui.v2.ViewLayout; import net.swofty.type.generic.gui.v2.context.ViewContext; +import net.swofty.type.generic.i18n.I18n; import net.swofty.type.skyblockgeneric.calendar.SkyBlockCalendar; import net.swofty.type.skyblockgeneric.elections.ElectionData; import net.swofty.type.skyblockgeneric.elections.ElectionManager; @@ -18,13 +19,17 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class ElectionViewStatsView extends StatelessView { @Override public ViewConfiguration configuration() { - return new ViewConfiguration<>("Election, Year " + SkyBlockCalendar.getYear(), InventoryType.CHEST_6_ROW); + return ViewConfiguration.withString( + (s, ctx) -> I18n.string("gui_election.stats.title", ctx.player().getLocale(), + Map.of("year", String.valueOf(SkyBlockCalendar.getYear()))), + InventoryType.CHEST_6_ROW); } @Override @@ -34,13 +39,15 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont ElectionData data = ElectionManager.getElectionData(); if (!data.isElectionOpen() || data.getCandidates().isEmpty()) { - layout.slot(22, (s, c) -> ItemStackCreator.getStack( - "§cNo Active Election", - Material.BARRIER, - 1, - "§7There is no active election", - "§7at this time." - )); + layout.slot(22, (s, c) -> { + Locale l = c.player().getLocale(); + return ItemStackCreator.getStack( + I18n.string("gui_election.view.no_election", l), + Material.BARRIER, + 1, + I18n.lore("gui_election.view.no_election.lore", l) + ); + }); return; } @@ -60,7 +67,12 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } } - for (int i = 0; i < candidates.size() && i < 5; i++) { + int candidateCount = Math.min(candidates.size(), 6); + int[] cols = candidateCount <= 5 + ? new int[]{0, 2, 4, 6, 8} + : new int[]{0, 1, 3, 5, 7, 8}; + + for (int i = 0; i < candidateCount; i++) { ElectionData.CandidateData candidate = candidates.get(i); SkyBlockMayor mayor = candidate.getMayorEnum(); if (mayor == null) continue; @@ -74,18 +86,19 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont boolean isLeader = candidateName.equals(leaderName) && votes > 0; Material glassMaterial = isLeader ? Material.ORANGE_STAINED_GLASS_PANE : Material.GRAY_STAINED_GLASS_PANE; - int col = i * 2; + int col = cols[i]; for (int row = 0; row < 6; row++) { int slot = row * 9 + col; int finalRow = row; layout.slot(slot, (s, c) -> { + Locale l = c.player().getLocale(); String playerVote = ElectionManager.getPlayerVote(c.player().getUuid()); boolean isVotedFor = candidateName.equals(playerVote); List lore = buildCandidateLore( - mayor, candidate, data.getElectionYear(), + l, mayor, candidate, data.getElectionYear(), yearsSince, voteStr, pctStr, isVotedFor, isLeader ); @@ -104,38 +117,47 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont lore ); }, (_, c) -> { + Locale l = c.player().getLocale(); String playerVote = ElectionManager.getPlayerVote(c.player().getUuid()); if (candidateName.equals(playerVote)) { - c.player().sendMessage("§aYou voted for this candidate."); + c.player().sendMessage(I18n.string("gui_election.view.already_voted", l)); return; } ElectionManager.castVote(c.player().getUuid(), candidateName); - c.player().sendMessage("§c-----------------------------------------------------"); - c.player().sendMessage("§eYou cast §c1 vote §efor " + candidate.getColoredName() + " §ein the §bYear " + data.getElectionYear() + " Elections§e!"); - c.player().sendMessage(" §bNew player §eFame Rank §a+1 vote"); - c.player().sendMessage(candidate.getColoredName() + " §enow has §c" + pctStr + " §eof votes with §c" + voteStr + " votes§e!"); - c.player().sendMessage("§c-----------------------------------------------------"); + c.player().sendMessage(I18n.string("gui_election.view.vote_divider", l)); + c.player().sendMessage(I18n.string("gui_election.view.vote_cast", l, Map.of( + "candidate", candidate.getColoredName(), + "year", String.valueOf(data.getElectionYear())))); + c.player().sendMessage(" " + I18n.string("gui_election.view.vote_fame", l)); + c.player().sendMessage(I18n.string("gui_election.view.vote_result", l, Map.of( + "candidate", candidate.getColoredName(), + "percentage", pctStr, + "votes", voteStr))); + c.player().sendMessage(I18n.string("gui_election.view.vote_divider", l)); c.replace(new ElectionViewStatsView()); }); } } } - private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.CandidateData candidate, + private List buildCandidateLore(Locale l, SkyBlockMayor mayor, ElectionData.CandidateData candidate, int electionYear, int yearsSince, String voteStr, String pctStr, boolean votedFor, boolean isLeader) { + String color = candidate.getColor(); List lore = new ArrayList<>(); - lore.add("§8Year " + electionYear + " Candidate"); + lore.add(I18n.string("gui_election.view.candidate.year", l, Map.of("year", String.valueOf(electionYear)))); lore.add(""); - lore.add("§7Votes: " + candidate.getColor() + voteStr + " §7(" + candidate.getColor() + pctStr + "§7)"); + lore.add(I18n.string("gui_election.view.candidate.votes", l, Map.of( + "color", color, "votes", voteStr, "percentage", pctStr))); if (isLeader) { - lore.add(candidate.getColor() + "Leading in votes!"); + lore.add(I18n.string("gui_election.stats.leader", l, Map.of("color", color))); } if (yearsSince >= 0) { - lore.add("§7Last elected: " + candidate.getColor() + yearsSince + "y ago"); + lore.add(I18n.string("gui_election.view.candidate.last_elected", l, Map.of( + "color", color, "years", String.valueOf(yearsSince)))); } else { - lore.add("§7Last elected: " + candidate.getColor() + "Never"); + lore.add(I18n.string("gui_election.view.candidate.last_elected_never", l, Map.of("color", color))); } lore.add(""); lore.add("§8§m--------------------------"); @@ -144,10 +166,10 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid for (int j = 0; j < activePerks.size(); j++) { SkyBlockMayor.Perk perk = activePerks.get(j); if (j == 0) { - lore.add("§6✯ " + candidate.getColor() + perk.getDisplayName()); + lore.add("§6✯ " + color + perk.getDisplayName()); } else { lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor( - candidate.getColor() + perk.getDisplayName(), 35)); + color + perk.getDisplayName(), 35)); } lore.addAll(StringUtility.splitByWordAndLengthKeepLegacyColor( perk.getDescription(), 35)); @@ -158,15 +180,15 @@ private List buildCandidateLore(SkyBlockMayor mayor, ElectionData.Candid if (!mayor.isSpecial()) { lore.add(""); - lore.add("§6✯ " + candidate.getColor() + "Minister Perks §7are also granted if"); - lore.add("§7this mayor wins second place!"); + lore.add(I18n.string("gui_election.view.candidate.minister_note_1", l, Map.of("color", color))); + lore.add(I18n.string("gui_election.view.candidate.minister_note_2", l)); } lore.add(""); if (votedFor) { - lore.add("§aYou voted for this candidate!"); + lore.add(I18n.string("gui_election.view.candidate.voted", l)); } else { - lore.add("§eClick to vote for " + mayor.getDisplayName() + "!"); + lore.add(I18n.string("gui_election.view.candidate.click_vote", l, Map.of("name", mayor.getDisplayName()))); } return lore; diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java index da0bc131c..b92f8bfe0 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MayorMenuView.java @@ -11,20 +11,28 @@ import net.swofty.type.generic.gui.v2.ViewConfiguration; import net.swofty.type.generic.gui.v2.ViewLayout; import net.swofty.type.generic.gui.v2.context.ViewContext; +import net.swofty.type.generic.i18n.I18n; import net.swofty.type.skyblockgeneric.elections.ElectionData; import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import java.util.Map; public class MayorMenuView extends StatelessView { @Override public ViewConfiguration configuration() { SkyBlockMayor mayor = ElectionManager.getCurrentMayor(); - if (mayor == null) return new ViewConfiguration<>("Mayor", InventoryType.CHEST_4_ROW); - return new ViewConfiguration<>("Mayor " + mayor.getDisplayName(), InventoryType.CHEST_4_ROW); + if (mayor == null) { + return ViewConfiguration.translatable("gui_election.mayor.title_fallback", InventoryType.CHEST_4_ROW); + } + return ViewConfiguration.withString( + (s, ctx) -> I18n.string("gui_election.mayor.title", ctx.player().getLocale(), + Map.of("name", mayor.getDisplayName())), + InventoryType.CHEST_4_ROW); } @Override @@ -36,16 +44,18 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (mayor == null) return; ElectionData data = ElectionManager.getElectionData(); + String mayorColor = data.getCurrentMayorColor(); List activePerks = data.getCurrentMayorPerkEnums(); layout.slot(11, (s, c) -> { + Locale l = c.player().getLocale(); List lore = new ArrayList<>(); - lore.add("§8Perks List"); + lore.add(I18n.string("gui_election.mayor.perks_label", l)); lore.add(""); lore.add("§8§m--------------------------"); for (SkyBlockMayor.Perk perk : activePerks) { - lore.add(mayor.getColor() + perk.getDisplayName()); + lore.add(mayorColor + perk.getDisplayName()); for (String line : StringUtility.splitByWordAndLengthKeepLegacyColor(perk.getDescription(), 50)) { lore.add("§7" + line); } @@ -54,12 +64,12 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont lore.add("§8§m--------------------------"); lore.add(""); - lore.add("§7The listed perks are available to"); - lore.add("§7all players until the closing of"); - lore.add("§7the next elections."); + lore.add(I18n.string("gui_election.mayor.perks_footer_1", l)); + lore.add(I18n.string("gui_election.mayor.perks_footer_2", l)); + lore.add(I18n.string("gui_election.mayor.perks_footer_3", l)); return ItemStackCreator.getStackHead( - mayor.getColor() + "Mayor " + mayor.getDisplayName(), + mayorColor + "Mayor " + mayor.getDisplayName(), new PlayerSkin(mayor.getTexture(), mayor.getSignature()), 1, lore @@ -67,25 +77,29 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont }); layout.slot(15, (s, c) -> { + Locale l = c.player().getLocale(); ElectionData.ElectionResult lastResult = data.getLastElectionResult(); if (lastResult == null) { return ItemStackCreator.getStack( - "§bMayor Election Results", + I18n.string("gui_election.mayor.results_title", l), Material.JUKEBOX, 1, - "§7No previous election data", - "§7available." + I18n.string("gui_election.mayor.results_no_data_1", l), + I18n.string("gui_election.mayor.results_no_data_2", l) ); } List resultLore = new ArrayList<>(); - resultLore.add("§8Year " + lastResult.getYear()); + resultLore.add(I18n.string("gui_election.mayor.results_year", l, + Map.of("year", String.valueOf(lastResult.getYear())))); resultLore.add(""); - for (ElectionData.CandidateResult cr : lastResult.getCandidateResults()) { + List results = lastResult.getCandidateResults(); + for (int i = 0; i < results.size(); i++) { + ElectionData.CandidateResult cr = results.get(i); + String clr = ElectionData.colorForIndex(i); SkyBlockMayor m = null; try { m = SkyBlockMayor.valueOf(cr.getMayorName()); } catch (IllegalArgumentException ignored) {} - String clr = m != null ? m.getColor() : "§7"; String name = m != null ? m.getDisplayName() : cr.getMayorName(); resultLore.add(clr + String.format("%.1f%%", cr.getPercentage()) + "§8 ○ " + clr + String.format("%,d", cr.getVotes()) @@ -93,12 +107,13 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } resultLore.add(""); - resultLore.add("§7These are the votes for the"); - resultLore.add("§7last election in which " + mayor.getDisplayName()); - resultLore.add("§7was elected."); + resultLore.add(I18n.string("gui_election.mayor.results_footer_1", l)); + resultLore.add(I18n.string("gui_election.mayor.results_footer_2", l, + Map.of("name", mayor.getDisplayName()))); + resultLore.add(I18n.string("gui_election.mayor.results_footer_3", l)); - return ItemStackCreator.getStack("§bMayor Election Results", Material.JUKEBOX, 1, - resultLore.toArray(new String[0])); + return ItemStackCreator.getStack(I18n.string("gui_election.mayor.results_title", l), + Material.JUKEBOX, 1, resultLore.toArray(new String[0])); }); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java index 5313e1e26..b6d990755 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/gui/inventories/election/MinisterMenuView.java @@ -11,20 +11,28 @@ import net.swofty.type.generic.gui.v2.ViewConfiguration; import net.swofty.type.generic.gui.v2.ViewLayout; import net.swofty.type.generic.gui.v2.context.ViewContext; +import net.swofty.type.generic.i18n.I18n; import net.swofty.type.skyblockgeneric.elections.ElectionData; import net.swofty.type.skyblockgeneric.elections.ElectionManager; import net.swofty.type.skyblockgeneric.elections.SkyBlockMayor; import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import java.util.Map; public class MinisterMenuView extends StatelessView { @Override public ViewConfiguration configuration() { SkyBlockMayor minister = ElectionManager.getCurrentMinister(); - if (minister == null) return new ViewConfiguration<>("Minister", InventoryType.CHEST_4_ROW); - return new ViewConfiguration<>("Minister " + minister.getDisplayName(), InventoryType.CHEST_4_ROW); + if (minister == null) { + return ViewConfiguration.translatable("gui_election.minister.title_fallback", InventoryType.CHEST_4_ROW); + } + return ViewConfiguration.withString( + (s, ctx) -> I18n.string("gui_election.minister.title", ctx.player().getLocale(), + Map.of("name", minister.getDisplayName())), + InventoryType.CHEST_4_ROW); } @Override @@ -36,16 +44,18 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont if (minister == null) return; ElectionData data = ElectionManager.getElectionData(); + String ministerColor = data.getCurrentMinisterColor(); SkyBlockMayor.Perk activePerk = data.getMinisterPerkEnum(); layout.slot(11, (s, c) -> { + Locale l = c.player().getLocale(); List lore = new ArrayList<>(); - lore.add("§8Active Perk"); + lore.add(I18n.string("gui_election.minister.perk_label", l)); lore.add(""); lore.add("§8§m--------------------------"); if (activePerk != null) { - lore.add(minister.getColor() + activePerk.getDisplayName()); + lore.add(ministerColor + activePerk.getDisplayName()); for (String line : StringUtility.splitByWordAndLengthKeepLegacyColor(activePerk.getDescription(), 50)) { lore.add("§7" + line); } @@ -53,12 +63,12 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont lore.add("§8§m--------------------------"); lore.add(""); - lore.add("§7The Minister is who came in 2nd Place"); - lore.add("§7during the election. They have one"); - lore.add("§7of their perks active."); + lore.add(I18n.string("gui_election.minister.perk_footer_1", l)); + lore.add(I18n.string("gui_election.minister.perk_footer_2", l)); + lore.add(I18n.string("gui_election.minister.perk_footer_3", l)); return ItemStackCreator.getStackHead( - minister.getColor() + "Minister " + minister.getDisplayName(), + ministerColor + "Minister " + minister.getDisplayName(), new PlayerSkin(minister.getTexture(), minister.getSignature()), 1, lore @@ -66,26 +76,31 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont }); layout.slot(15, (s, c) -> { + Locale l = c.player().getLocale(); ElectionData.ElectionResult lastResult = data.getLastElectionResult(); if (lastResult == null) { return ItemStackCreator.getStack( - "§bMayor Election Results", + I18n.string("gui_election.mayor.results_title", l), Material.JUKEBOX, 1, - "§7No previous election data", - "§7available." + I18n.string("gui_election.mayor.results_no_data_1", l), + I18n.string("gui_election.mayor.results_no_data_2", l) ); } SkyBlockMayor currentMayor = ElectionManager.getCurrentMayor(); + String mayorName = currentMayor != null ? currentMayor.getDisplayName() : "???"; List resultLore = new ArrayList<>(); - resultLore.add("§8Year " + lastResult.getYear()); + resultLore.add(I18n.string("gui_election.mayor.results_year", l, + Map.of("year", String.valueOf(lastResult.getYear())))); resultLore.add(""); - for (ElectionData.CandidateResult cr : lastResult.getCandidateResults()) { + List results = lastResult.getCandidateResults(); + for (int i = 0; i < results.size(); i++) { + ElectionData.CandidateResult cr = results.get(i); + String clr = ElectionData.colorForIndex(i); SkyBlockMayor m = null; try { m = SkyBlockMayor.valueOf(cr.getMayorName()); } catch (IllegalArgumentException ignored) {} - String clr = m != null ? m.getColor() : "§7"; String name = m != null ? m.getDisplayName() : cr.getMayorName(); resultLore.add(clr + String.format("%.1f%%", cr.getPercentage()) + "§8 ○ " + clr + String.format("%,d", cr.getVotes()) @@ -93,12 +108,12 @@ public void layout(ViewLayout layout, DefaultState state, ViewCont } resultLore.add(""); - resultLore.add("§7These are the votes for the"); - resultLore.add("§7last election in which " + (currentMayor != null ? currentMayor.getDisplayName() : "???")); - resultLore.add("§7was elected."); + resultLore.add(I18n.string("gui_election.mayor.results_footer_1", l)); + resultLore.add(I18n.string("gui_election.mayor.results_footer_2", l, Map.of("name", mayorName))); + resultLore.add(I18n.string("gui_election.mayor.results_footer_3", l)); - return ItemStackCreator.getStack("§bMayor Election Results", Material.JUKEBOX, 1, - resultLore.toArray(new String[0])); + return ItemStackCreator.getStack(I18n.string("gui_election.mayor.results_title", l), + Material.JUKEBOX, 1, resultLore.toArray(new String[0])); }); } } From 0b9d44af547185331d46407bed3a11e1a39747ad Mon Sep 17 00:00:00 2001 From: Swofty Date: Sat, 28 Feb 2026 03:05:53 +1100 Subject: [PATCH 15/17] =?UTF-8?q?chore(i18n):=20convert=20election=20trans?= =?UTF-8?q?lation=20strings=20from=20legacy=20=C2=A7=20codes=20to=20MiniMe?= =?UTF-8?q?ssage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../i18n/en_US/gui/gui_election.properties | 74 +++++++++---------- .../i18n/en_US/npcs/npcs_hub.properties | 4 +- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/configuration/i18n/en_US/gui/gui_election.properties b/configuration/i18n/en_US/gui/gui_election.properties index f2f36c71e..be604cc1a 100644 --- a/configuration/i18n/en_US/gui/gui_election.properties +++ b/configuration/i18n/en_US/gui/gui_election.properties @@ -4,23 +4,23 @@ # --- ElectionView (Voting GUI) --- gui_election.view.title = Election -gui_election.view.no_election = §cNo Active Election -gui_election.view.no_election.lore = §7There is no active election\n§7at this time. -gui_election.view.candidate.year = §8Year {year} Candidate -gui_election.view.candidate.votes = §7Votes: {color}{votes} §7({color}{percentage}§7) -gui_election.view.candidate.last_elected = §7Last elected: {color}{years}y ago -gui_election.view.candidate.last_elected_never = §7Last elected: {color}Never -gui_election.view.candidate.minister_note_1 = §6✯ {color}Minister Perks §7are also granted if -gui_election.view.candidate.minister_note_2 = §7this mayor wins second place! -gui_election.view.candidate.voted = §aYou voted for this candidate! -gui_election.view.candidate.change_vote_1 = §8You may change your vote at any -gui_election.view.candidate.change_vote_2 = §8time until the election ends! -gui_election.view.candidate.click_vote = §eClick to vote for {name}! -gui_election.view.vote_divider = §c----------------------------------------------------- -gui_election.view.vote_cast = §eYou cast §c1 vote §efor {candidate} §ein the §bYear {year} Elections§e! -gui_election.view.vote_fame = §bNew player §eFame Rank §a+1 vote -gui_election.view.vote_result = {candidate} §enow has §c{percentage} §eof votes with §c{votes} votes§e! -gui_election.view.already_voted = §aYou voted for this candidate. +gui_election.view.no_election = No Active Election +gui_election.view.no_election.lore = There is no active election\nat this time. +gui_election.view.candidate.year = Year {year} Candidate +gui_election.view.candidate.votes = Votes: {color}{votes} ({color}{percentage}) +gui_election.view.candidate.last_elected = Last elected: {color}{years}y ago +gui_election.view.candidate.last_elected_never = Last elected: {color}Never +gui_election.view.candidate.minister_note_1 = ✯ {color}Minister Perks are also granted if +gui_election.view.candidate.minister_note_2 = this mayor wins second place! +gui_election.view.candidate.voted = You voted for this candidate! +gui_election.view.candidate.change_vote_1 = You may change your vote at any +gui_election.view.candidate.change_vote_2 = time until the election ends! +gui_election.view.candidate.click_vote = Click to vote for {name}! +gui_election.view.vote_divider = ----------------------------------------------------- +gui_election.view.vote_cast = You cast 1 vote for {candidate} in the Year {year} Elections! +gui_election.view.vote_fame = New player Fame Rank +1 vote +gui_election.view.vote_result = {candidate} now has {percentage} of votes with {votes} votes! +gui_election.view.already_voted = You voted for this candidate. # --- ElectionViewStatsView --- gui_election.stats.title = Election, Year {year} @@ -29,29 +29,29 @@ gui_election.stats.leader = {color}Leading in votes! # --- MayorMenuView --- gui_election.mayor.title = Mayor {name} gui_election.mayor.title_fallback = Mayor -gui_election.mayor.perks_label = §8Perks List -gui_election.mayor.perks_footer_1 = §7The listed perks are available to -gui_election.mayor.perks_footer_2 = §7all players until the closing of -gui_election.mayor.perks_footer_3 = §7the next elections. -gui_election.mayor.results_title = §bMayor Election Results -gui_election.mayor.results_no_data_1 = §7No previous election data -gui_election.mayor.results_no_data_2 = §7available. -gui_election.mayor.results_year = §8Year {year} -gui_election.mayor.results_footer_1 = §7These are the votes for the -gui_election.mayor.results_footer_2 = §7last election in which {name} -gui_election.mayor.results_footer_3 = §7was elected. +gui_election.mayor.perks_label = Perks List +gui_election.mayor.perks_footer_1 = The listed perks are available to +gui_election.mayor.perks_footer_2 = all players until the closing of +gui_election.mayor.perks_footer_3 = the next elections. +gui_election.mayor.results_title = Mayor Election Results +gui_election.mayor.results_no_data_1 = No previous election data +gui_election.mayor.results_no_data_2 = available. +gui_election.mayor.results_year = Year {year} +gui_election.mayor.results_footer_1 = These are the votes for the +gui_election.mayor.results_footer_2 = last election in which {name} +gui_election.mayor.results_footer_3 = was elected. # --- MinisterMenuView --- gui_election.minister.title = Minister {name} gui_election.minister.title_fallback = Minister -gui_election.minister.perk_label = §8Active Perk -gui_election.minister.perk_footer_1 = §7The Minister is who came in 2nd Place -gui_election.minister.perk_footer_2 = §7during the election. They have one -gui_election.minister.perk_footer_3 = §7of their perks active. +gui_election.minister.perk_label = Active Perk +gui_election.minister.perk_footer_1 = The Minister is who came in 2nd Place +gui_election.minister.perk_footer_2 = during the election. They have one +gui_election.minister.perk_footer_3 = of their perks active. # --- ElectionDisplay (Holograms) --- -gui_election.display.title = §e§lMAYOR ELECTIONS -gui_election.display.year = §bYear {year} -gui_election.display.time_left = §eTime left: §a{time} -gui_election.display.your_vote = §eYour vote: §f{candidate} -gui_election.display.click_switch = §e§lCLICK TO SWITCH +gui_election.display.title = MAYOR ELECTIONS +gui_election.display.year = Year {year} +gui_election.display.time_left = Time left: {time} +gui_election.display.your_vote = Your vote: {candidate} +gui_election.display.click_switch = CLICK TO SWITCH diff --git a/configuration/i18n/en_US/npcs/npcs_hub.properties b/configuration/i18n/en_US/npcs/npcs_hub.properties index 0a0f7472c..354ee65b2 100644 --- a/configuration/i18n/en_US/npcs/npcs_hub.properties +++ b/configuration/i18n/en_US/npcs/npcs_hub.properties @@ -81,11 +81,11 @@ npcs_hub.clerk_seraphine.dialogue.hello = Welcome to the Community Center< # --- Election NPCs --- npcs_hub.election.clerk_seraphine = Clerk Seraphine npcs_hub.election.candidate_label = Candidate -npcs_hub.election.click = §e§lCLICK +npcs_hub.election.click = CLICK npcs_hub.election.running = Running for mayor! npcs_hub.election.mayor_unknown = Mayor ??? npcs_hub.election.minister_unknown = Minister ???? -npcs_hub.election.hello = §cHello!! +npcs_hub.election.hello = Hello!! # --- Gladiator --- npcs_hub.gladiator.dialogue.hello = Welcome to the Colosseum!|Oh...wait. Nevermind.|Here you can join me in drinking away your sorrows. From 1cf4f15d193a2edae0eb9bb7a37f643e20c63a75 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:58:47 +0300 Subject: [PATCH 16/17] fix: correct class names --- ...eboard.java => SkyWarsLobbyScoreboard.java} | 4 ++-- ...Loader.java => TypeSkyWarsLobbyLoader.java} | 18 +++++++++++------- .../events/ActionPlayerDisconnect.java | 4 ++-- .../skywarslobby/events/ActionPlayerSpawn.java | 6 +++--- ...ywarsLobbyMap.java => SkyWarsLobbyMap.java} | 2 +- 5 files changed, 19 insertions(+), 15 deletions(-) rename type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/{SkywarsLobbyScoreboard.java => SkyWarsLobbyScoreboard.java} (98%) rename type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/{TypeSkywarsLobbyLoader.java => TypeSkyWarsLobbyLoader.java} (93%) rename type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/util/{SkywarsLobbyMap.java => SkyWarsLobbyMap.java} (99%) diff --git a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkywarsLobbyScoreboard.java b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkyWarsLobbyScoreboard.java similarity index 98% rename from type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkywarsLobbyScoreboard.java rename to type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkyWarsLobbyScoreboard.java index 6afa4821a..9103eca39 100644 --- a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkywarsLobbyScoreboard.java +++ b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/SkyWarsLobbyScoreboard.java @@ -24,7 +24,7 @@ import java.util.List; import java.util.Locale; -public class SkywarsLobbyScoreboard { +public class SkyWarsLobbyScoreboard { private static final HypixelScoreboard scoreboard = new HypixelScoreboard(); private static Integer animationFrame = 0; @@ -65,7 +65,7 @@ public static void start() { List lines = new ArrayList<>(); lines.add("§7" + new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()) + " §8" + HypixelConst.getServerName()); lines.add("§7 "); - lines.add(I18n.string("scoreboard.skywars_lobby.your_level_label", l) + " " + SkywarsLevelColor.getLevelDisplay(level)); + lines.add(I18n.string("scoreboard.skywars_lobby.your_level_label", l) + " " + SkyWarsLevelColor.getLevelDisplay(level)); lines.add("§7 "); lines.add(I18n.string("scoreboard.skywars_lobby.solo_kills_label", l) + soloKills); lines.add(I18n.string("scoreboard.skywars_lobby.solo_wins_label", l) + soloWins); diff --git a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/TypeSkywarsLobbyLoader.java b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/TypeSkyWarsLobbyLoader.java similarity index 93% rename from type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/TypeSkywarsLobbyLoader.java rename to type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/TypeSkyWarsLobbyLoader.java index 940328d0b..b69d024f0 100644 --- a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/TypeSkywarsLobbyLoader.java +++ b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/TypeSkyWarsLobbyLoader.java @@ -11,16 +11,20 @@ import net.swofty.proxyapi.redis.ServiceToClient; import net.swofty.type.generic.HypixelConst; import net.swofty.type.generic.HypixelGenericLoader; +import net.swofty.type.generic.command.HypixelCommand; import net.swofty.type.generic.data.GameDataHandler; import net.swofty.type.generic.data.handlers.SkywarsDataHandler; -import net.swofty.type.generic.command.HypixelCommand; import net.swofty.type.generic.entity.hologram.PlayerHolograms; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.event.HypixelEventClass; import net.swofty.type.generic.tab.TablistManager; import net.swofty.type.generic.tab.TablistModule; import net.swofty.type.lobby.LobbyTypeLoader; -import net.swofty.type.lobby.events.*; +import net.swofty.type.lobby.events.LobbyBlockBreak; +import net.swofty.type.lobby.events.LobbyItemEvents; +import net.swofty.type.lobby.events.LobbyLaunchPadEvents; +import net.swofty.type.lobby.events.LobbyPlayerJoinEvents; +import net.swofty.type.lobby.events.LobbyPlayerMove; import net.swofty.type.lobby.item.LobbyItem; import net.swofty.type.lobby.item.LobbyItemHandler; import net.swofty.type.lobby.item.impl.HidePlayers; @@ -32,14 +36,14 @@ import net.swofty.type.lobby.parkour.Parkour; import net.swofty.type.skywarslobby.hologram.LeaderboardHologramManager; import net.swofty.type.skywarslobby.hologram.SoulWellHologramManager; -import net.swofty.type.skywarslobby.parkour.SkywarsLobbyParkour; import net.swofty.type.skywarslobby.item.SkywarsMenuItem; import net.swofty.type.skywarslobby.kit.SkywarsKitRegistry; import net.swofty.type.skywarslobby.level.SkywarsLevelRegistry; +import net.swofty.type.skywarslobby.parkour.SkywarsLobbyParkour; import net.swofty.type.skywarslobby.perk.SkywarsPerkRegistry; import net.swofty.type.skywarslobby.soulwell.SoulWellParticleManager; import net.swofty.type.skywarslobby.soulwell.SoulWellUpgradeRegistry; -import net.swofty.type.skywarslobby.util.SkywarsLobbyMap; +import net.swofty.type.skywarslobby.util.SkyWarsLobbyMap; import org.jetbrains.annotations.Nullable; import org.tinylog.Logger; @@ -47,7 +51,7 @@ import java.util.List; import java.util.Map; -public class TypeSkywarsLobbyLoader implements LobbyTypeLoader { +public class TypeSkyWarsLobbyLoader implements LobbyTypeLoader { @Getter private final LobbyItemHandler itemHandler = new LobbyItemHandler(); @Getter @@ -73,10 +77,10 @@ public void afterInitialize(MinecraftServer server) { SoulWellUpgradeRegistry.initialize(); Logger.info("Initialized SkyWars kit, perk, level, and soul well upgrade registries"); - SkywarsLobbyScoreboard.start(); + SkyWarsLobbyScoreboard.start(); // Place map item frames in the lobby - SkywarsLobbyMap skywarsLobbyMap = new SkywarsLobbyMap(); + SkyWarsLobbyMap skywarsLobbyMap = new SkyWarsLobbyMap(); skywarsLobbyMap.placeItemFrames(HypixelConst.getInstanceContainer()); // Initialize parkour manager diff --git a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/events/ActionPlayerDisconnect.java b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/events/ActionPlayerDisconnect.java index b98e4cd8f..6d88e4a17 100644 --- a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/events/ActionPlayerDisconnect.java +++ b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/events/ActionPlayerDisconnect.java @@ -5,14 +5,14 @@ import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; import net.swofty.type.generic.user.HypixelPlayer; -import net.swofty.type.skywarslobby.SkywarsLobbyScoreboard; +import net.swofty.type.skywarslobby.SkyWarsLobbyScoreboard; public class ActionPlayerDisconnect implements HypixelEventClass { @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) public void run(PlayerDisconnectEvent event) { HypixelPlayer player = (HypixelPlayer) event.getPlayer(); - SkywarsLobbyScoreboard.removeCache(player); + SkyWarsLobbyScoreboard.removeCache(player); } } diff --git a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/events/ActionPlayerSpawn.java b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/events/ActionPlayerSpawn.java index d6acba9d1..cf263d087 100644 --- a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/events/ActionPlayerSpawn.java +++ b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/events/ActionPlayerSpawn.java @@ -1,15 +1,15 @@ package net.swofty.type.skywarslobby.events; import lombok.SneakyThrows; -import net.minestom.server.event.player.PlayerSpawnEvent; import net.minestom.server.entity.GameMode; +import net.minestom.server.event.player.PlayerSpawnEvent; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; import net.swofty.type.generic.user.HypixelPlayer; import net.swofty.type.skywarslobby.hologram.LeaderboardHologramManager; import net.swofty.type.skywarslobby.hologram.SoulWellHologramManager; -import net.swofty.type.skywarslobby.util.SkywarsLobbyMap; +import net.swofty.type.skywarslobby.util.SkyWarsLobbyMap; public class ActionPlayerSpawn implements HypixelEventClass { @@ -20,7 +20,7 @@ public void run(PlayerSpawnEvent event) { player.setGameMode(GameMode.SURVIVAL); // Send map data to player - SkywarsLobbyMap skywarsLobbyMap = new SkywarsLobbyMap(); + SkyWarsLobbyMap skywarsLobbyMap = new SkyWarsLobbyMap(); skywarsLobbyMap.sendMapData(player); // Spawn leaderboard holograms for this player diff --git a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/util/SkywarsLobbyMap.java b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/util/SkyWarsLobbyMap.java similarity index 99% rename from type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/util/SkywarsLobbyMap.java rename to type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/util/SkyWarsLobbyMap.java index 321410f4d..a524c804f 100644 --- a/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/util/SkywarsLobbyMap.java +++ b/type.skywarslobby/src/main/java/net/swofty/type/skywarslobby/util/SkyWarsLobbyMap.java @@ -3,7 +3,7 @@ import net.minestom.server.coordinate.Pos; import net.swofty.type.generic.utility.AbstractMapSystem; -public class SkywarsLobbyMap extends AbstractMapSystem { +public class SkyWarsLobbyMap extends AbstractMapSystem { @Override protected MapConfiguration getConfiguration() { From 5353092f4deb4211b1ee88c69d782712d0bb6b8c Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Mon, 6 Apr 2026 13:06:47 +0300 Subject: [PATCH 17/17] fix: make code make more sense --- .../election/CastVoteProtocolObject.java | 17 ++++++++++++++--- .../election/GetCandidatesProtocolObject.java | 7 ++++--- .../election/GetElectionDataProtocolObject.java | 2 +- .../election/endpoints/CastVoteEndpoint.java | 6 ++---- .../elections/ElectionManager.java | 9 ++------- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java index 6420771d8..3889b23a1 100644 --- a/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/CastVoteProtocolObject.java @@ -4,6 +4,8 @@ import net.swofty.commons.protocol.Serializer; import org.json.JSONObject; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; public class CastVoteProtocolObject @@ -44,16 +46,24 @@ public Serializer getReturnSerializer() { public String serialize(CastVoteResponse value) { JSONObject json = new JSONObject(); json.put("success", value.success()); - json.put("talliesJson", value.talliesJson()); + json.put("tallies", value.tallies() == null ? null : new JSONObject(value.tallies())); return json.toString(); } @Override public CastVoteResponse deserialize(String json) { JSONObject obj = new JSONObject(json); + Map tallies = null; + if (!obj.isNull("tallies")) { + tallies = new HashMap<>(); + JSONObject talliesObject = obj.getJSONObject("tallies"); + for (String key : talliesObject.keySet()) { + tallies.put(key, talliesObject.getLong(key)); + } + } return new CastVoteResponse( obj.getBoolean("success"), - obj.optString("talliesJson", null) + tallies ); } @@ -66,5 +76,6 @@ public CastVoteResponse clone(CastVoteResponse value) { public record CastVoteMessage(UUID accountId, String candidateName) {} - public record CastVoteResponse(boolean success, String talliesJson) {} + public record CastVoteResponse(boolean success, Map tallies) { + } } diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetCandidatesProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetCandidatesProtocolObject.java index ed1a13ef3..b3bffd042 100644 --- a/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetCandidatesProtocolObject.java +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetCandidatesProtocolObject.java @@ -4,6 +4,7 @@ import com.google.gson.reflect.TypeToken; import net.swofty.commons.protocol.ProtocolObject; import net.swofty.commons.protocol.Serializer; +import org.json.JSONArray; import org.json.JSONObject; import java.util.List; @@ -17,7 +18,7 @@ public Serializer getSerializer() { return new Serializer<>() { @Override public String serialize(GetCandidatesMessage value) { - return new JSONObject().put("_", true).toString(); + return ""; } @Override @@ -41,7 +42,7 @@ public Serializer getReturnSerializer() { public String serialize(GetCandidatesResponse value) { JSONObject json = new JSONObject(); json.put("electionOpen", value.electionOpen()); - json.put("candidates", gson.toJson(value.candidates())); + json.put("candidates", value.candidates() == null ? null : new JSONArray(gson.toJson(value.candidates()))); return json.toString(); } @@ -52,7 +53,7 @@ public GetCandidatesResponse deserialize(String json) { List candidates = List.of(); if (!obj.isNull("candidates")) { candidates = gson.fromJson( - obj.getString("candidates"), + obj.getJSONArray("candidates").toString(), new TypeToken>() {}.getType() ); } diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetElectionDataProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetElectionDataProtocolObject.java index 4e604498b..381dd1f3f 100644 --- a/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetElectionDataProtocolObject.java +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/election/GetElectionDataProtocolObject.java @@ -13,7 +13,7 @@ public Serializer getSerializer() { return new Serializer<>() { @Override public String serialize(GetElectionDataMessage value) { - return new JSONObject().put("_", true).toString(); + return ""; } @Override diff --git a/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java b/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java index 9da7af8dc..afc54eab5 100644 --- a/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java +++ b/service.elections/src/main/java/net/swofty/service/election/endpoints/CastVoteEndpoint.java @@ -15,8 +15,6 @@ public class CastVoteEndpoint implements ServiceEndpoint { - private static final Gson GSON = new Gson(); - @Override public ProtocolObject associatedProtocolObject() { @@ -34,7 +32,7 @@ public CastVoteProtocolObject.CastVoteResponse onMessage( return new CastVoteProtocolObject.CastVoteResponse(false, null); } - Map data = GSON.fromJson(rawData, Map.class); + Map data = new Gson().fromJson(rawData, Map.class); Boolean electionOpen = (Boolean) data.get("electionOpen"); if (electionOpen == null || !electionOpen) { return new CastVoteProtocolObject.CastVoteResponse(false, null); @@ -60,7 +58,7 @@ public CastVoteProtocolObject.CastVoteResponse onMessage( ); Map tallies = ElectionDatabase.getTallies(electionYear); - return new CastVoteProtocolObject.CastVoteResponse(true, GSON.toJson(tallies)); + return new CastVoteProtocolObject.CastVoteResponse(true, tallies); } catch (Exception e) { Logger.error(e, "Failed to cast vote"); return new CastVoteProtocolObject.CastVoteResponse(false, null); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java index d98f19010..b8f988daf 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/elections/ElectionManager.java @@ -1,7 +1,6 @@ package net.swofty.type.skyblockgeneric.elections; import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; import lombok.Getter; import net.minestom.server.MinecraftServer; import net.minestom.server.timer.TaskSchedule; @@ -143,12 +142,8 @@ public static CompletableFuture castVote(UUID accountId, String candidateN ).thenAccept(response -> { if (response.success()) { playerVoteCache.put(accountId, candidateName); - if (response.talliesJson() != null) { - Map tallies = GSON.fromJson( - response.talliesJson(), - new TypeToken>(){}.getType() - ); - electionData.updateTallies(tallies); + if (response.tallies() != null) { + electionData.updateTallies(response.tallies()); } } }).exceptionally(e -> {