diff --git a/src/main/java/net/tfminecraft/simplefactions/guild/hub/SupplyHubCommands.java b/src/main/java/net/tfminecraft/simplefactions/guild/hub/SupplyHubCommands.java index 1920438c..f139564a 100644 --- a/src/main/java/net/tfminecraft/simplefactions/guild/hub/SupplyHubCommands.java +++ b/src/main/java/net/tfminecraft/simplefactions/guild/hub/SupplyHubCommands.java @@ -373,6 +373,13 @@ private static double reachableTrade(Guild guild, Installation installation) { /** Hub changes move trade power, so the map and incomes are brought up to date at once. */ private static void recalculateTrade() { + if (FactionManager.getMap() != null && FactionManager.factions != null) { + for (Faction faction : FactionManager.factions) { + if (faction != null && faction.getRGB() != null) { + FactionManager.getMap().enqueue("nation", faction.getRGB()); + } + } + } SimpleFactions plugin = SimpleFactions.getInstance(); if (plugin == null || plugin.getProvinceManager() == null) { return; diff --git a/src/main/java/net/tfminecraft/simplefactions/map/export/Markers.java b/src/main/java/net/tfminecraft/simplefactions/map/export/Markers.java index 50d6d7db..735f182e 100644 --- a/src/main/java/net/tfminecraft/simplefactions/map/export/Markers.java +++ b/src/main/java/net/tfminecraft/simplefactions/map/export/Markers.java @@ -5,12 +5,20 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.time.Instant; +import java.util.List; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import net.md_5.bungee.api.ChatColor; import net.tfminecraft.simplefactions.Cache; +import net.tfminecraft.simplefactions.guild.Guild; +import net.tfminecraft.simplefactions.guild.hub.HubNetwork; +import net.tfminecraft.simplefactions.guild.hub.HubTransport.Link; +import net.tfminecraft.simplefactions.guild.hub.SupplyHub; +import net.tfminecraft.simplefactions.guild.hub.SupplyHubService; +import net.tfminecraft.simplefactions.loaders.InstallationConfigLoader; import net.tfminecraft.simplefactions.managers.FactionManager; import net.tfminecraft.simplefactions.managers.WarManager; import net.tfminecraft.simplefactions.objects.Faction; @@ -67,11 +75,21 @@ public static void export(File out) throws IOException { JsonArray installations = new JsonArray(); for (Faction faction : FactionManager.factions) { for (Installation installation : faction.getInstallationHandler().getAll()) { - installations.add(installationRow(installation, faction.getId())); + installations.add(installationRow( + installation, + faction.getId(), + InstallationConfigLoader.getHubSlots(installation.getKind(), installation.getLevel()), + SupplyHubService.countAt(faction.getId(), installation.getId(), SupplyHubService.allGuilds()))); } } root.add("installations", installations); + JsonArray hubLinks = new JsonArray(); + for (Guild guild : SupplyHubService.allGuilds()) { + hubLinks.addAll(hubLinkRows(guild, HubNetwork.linksFor(guild))); + } + root.add("hub_links", hubLinks); + JsonArray forts = new JsonArray(); for (Faction faction : FactionManager.factions) { for (Installation installation : faction.getInstallationHandler().getAll()) { @@ -115,6 +133,14 @@ public static void export(File out) throws IOException { } static JsonObject installationRow(Installation installation, String factionId) { + return installationRow( + installation, + factionId, + SupplyHubService.defaultHubSlots(installation.getKind(), installation.getLevel()), + 0); + } + + static JsonObject installationRow(Installation installation, String factionId, int hubSlots, int hubs) { JsonObject row = new JsonObject(); row.addProperty("id", installation.getId()); row.addProperty("name", installation.getName()); @@ -124,9 +150,136 @@ static JsonObject installationRow(Installation installation, String factionId) { row.addProperty("center_x", installation.getCenterX()); row.addProperty("center_z", installation.getCenterZ()); row.addProperty("level", installation.getLevel()); + row.addProperty("hub_slots", hubSlots); + row.addProperty("hubs", hubs); + return row; + } + + static JsonArray hubLinkRows(Guild guild, List links) { + JsonArray rows = new JsonArray(); + if (guild == null || guild.getFaction() == null || guild.getFaction().getId() == null || links == null) { + return rows; + } + for (Link link : links) { + if (link == null || link.fromProvince() >= link.toProvince()) { + continue; + } + Installation from = activeHubAt(guild, link.fromProvince(), link.mode().getKind()); + Installation to = activeHubAt(guild, link.toProvince(), link.mode().getKind()); + if (from == null || to == null) { + continue; + } + Faction fromFaction = hubOwner(guild, from); + Faction toFaction = hubOwner(guild, to); + if (fromFaction == null || toFaction == null) { + continue; + } + rows.add(hubLinkRow( + guild.getId(), + stripColor(guild.getName()), + guild.getFaction().getId(), + link, + hubEndpoint(from, fromFaction), + hubEndpoint(to, toFaction))); + } + return rows; + } + + static JsonObject hubLinkRow( + String guildId, + String guildName, + String factionId, + Link link, + HubEndpoint from, + HubEndpoint to) { + JsonObject row = new JsonObject(); + row.addProperty("guild_id", guildId); + row.addProperty("guild_name", stripColor(guildName)); + row.addProperty("faction_id", factionId); + row.addProperty("mode", link.mode().getKey()); + row.addProperty("distance", link.distance()); + row.addProperty("trade_share", roundShare(link.tradeFactor())); + row.addProperty("production_share", roundShare(link.productionFactor())); + row.add("from", hubEndpointRow(from)); + row.add("to", hubEndpointRow(to)); + return row; + } + + static JsonObject hubEndpointRow(HubEndpoint endpoint) { + JsonObject row = new JsonObject(); + row.addProperty("installation_id", endpoint.installationId()); + row.addProperty("faction_id", endpoint.factionId()); + row.addProperty("name", stripColor(endpoint.name())); + row.addProperty("province_id", endpoint.provinceId()); + row.addProperty("center_x", endpoint.centerX()); + row.addProperty("center_z", endpoint.centerZ()); return row; } + private static Installation activeHubAt(Guild guild, int provinceId, InstallationKind kind) { + for (SupplyHub hub : guild.getSupplyHubs()) { + Installation installation = SupplyHubService.findInstallation(hub.ownerFactionId(), hub.installationId()); + if (installation == null || installation.getProvince() != provinceId || installation.getKind() != kind) { + continue; + } + Faction owner = FactionManager.getByString(hub.ownerFactionId()); + boolean permit = owner != null && owner.hasHubPermit(guild.getId()); + String guildFactionId = guild.getFaction() == null ? null : guild.getFaction().getId(); + SupplyHubService.HubStanding standing = SupplyHubService.standing( + hub, + true, + SupplyHubService.ownerAllows(guildFactionId, hub.ownerFactionId(), permit), + InstallationConfigLoader.getHubSlots(installation.getKind(), installation.getLevel()), + SupplyHubService.atInstallation( + hub.ownerFactionId(), hub.installationId(), SupplyHubService.allGuilds())); + if (standing.active()) { + return installation; + } + } + return null; + } + + private static Faction hubOwner(Guild guild, Installation installation) { + for (SupplyHub hub : guild.getSupplyHubs()) { + if (hub.installationId() == null || hub.ownerFactionId() == null) { + continue; + } + Installation hubInstallation = SupplyHubService.findInstallation( + hub.ownerFactionId(), hub.installationId()); + if (hubInstallation == installation) { + return FactionManager.getByString(hub.ownerFactionId()); + } + } + return null; + } + + private static HubEndpoint hubEndpoint(Installation installation, Faction owner) { + return new HubEndpoint( + installation.getId(), + owner.getId(), + installation.getName(), + installation.getProvince(), + installation.getCenterX(), + installation.getCenterZ()); + } + + private static String stripColor(String value) { + return ChatColor.stripColor(value == null ? "" : value); + } + + private static double roundShare(double share) { + return Math.round(share * 10000.0) / 10000.0; + } + + record HubEndpoint( + String installationId, + String factionId, + String name, + int provinceId, + int centerX, + int centerZ) { + } + static String installationKind(Installation installation) { return installation.getKind().getCommandName(); } diff --git a/src/test/java/net/tfminecraft/simplefactions/map/export/MarkersInstallationKindTest.java b/src/test/java/net/tfminecraft/simplefactions/map/export/MarkersInstallationKindTest.java index 7ae99450..8db20c84 100644 --- a/src/test/java/net/tfminecraft/simplefactions/map/export/MarkersInstallationKindTest.java +++ b/src/test/java/net/tfminecraft/simplefactions/map/export/MarkersInstallationKindTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; +import net.tfminecraft.simplefactions.guild.hub.HubTransport; import net.tfminecraft.simplefactions.installation.Installation; import net.tfminecraft.simplefactions.installation.InstallationKind; @@ -27,4 +28,40 @@ void installationMapRowIncludesLevel() { assertTrue(row.get("level").isJsonPrimitive()); assertEquals(2, row.get("level").getAsInt()); } + + @Test + void installationMapRowIncludesHubCapacityAndUsage() { + Installation station = new Installation( + "central_station", "Central Station", InstallationKind.TRAIN_STATION, 1, 0, 0, 1L, 2); + + var row = Markers.installationRow(station, "faction-a", 2, 1); + + assertEquals(2, row.get("hub_slots").getAsInt()); + assertEquals(1, row.get("hubs").getAsInt()); + } + + @Test + void hubLinkRowUsesMapShapeAndRoundsShares() { + HubTransport.Link link = new HubTransport.Link(12, 28, HubTransport.Mode.RAIL, 1234.5, 0.629876, 0.224444); + + var row = Markers.hubLinkRow( + "The_Chisels", + "§bThe Chisels", + "Thalendor", + link, + new Markers.HubEndpoint("Abrar_Station", "Khazabrar", "§aAbrar Station", 12, 740, 1344), + new Markers.HubEndpoint("Dunir_Station", "Khazabrar", "Dunir Station", 28, 572, 1340)); + + assertEquals("The_Chisels", row.get("guild_id").getAsString()); + assertEquals("The Chisels", row.get("guild_name").getAsString()); + assertEquals("Thalendor", row.get("faction_id").getAsString()); + assertEquals("rail", row.get("mode").getAsString()); + assertEquals(1234.5, row.get("distance").getAsDouble()); + assertEquals(0.6299, row.get("trade_share").getAsDouble()); + assertEquals(0.2244, row.get("production_share").getAsDouble()); + assertEquals("Abrar_Station", row.getAsJsonObject("from").get("installation_id").getAsString()); + assertEquals("Khazabrar", row.getAsJsonObject("from").get("faction_id").getAsString()); + assertEquals("Abrar Station", row.getAsJsonObject("from").get("name").getAsString()); + assertEquals(28, row.getAsJsonObject("to").get("province_id").getAsInt()); + } }