diff --git a/src/main/java/net/tfminecraft/simplefactions/managers/inventory/InstallationCreator.java b/src/main/java/net/tfminecraft/simplefactions/managers/inventory/InstallationCreator.java index faa0a413..6ad8c670 100644 --- a/src/main/java/net/tfminecraft/simplefactions/managers/inventory/InstallationCreator.java +++ b/src/main/java/net/tfminecraft/simplefactions/managers/inventory/InstallationCreator.java @@ -73,7 +73,7 @@ public ItemStack createSummary(Faction f) { // Keep the existing legacy text representation, formatting, and exact-string comparisons. @SuppressWarnings("deprecation") public ItemStack createInstallationIcon(Installation installation) { - ItemStack item = new ItemStack(iconFor(installation.getKind()), 1); + ItemStack item = iconFor(installation.getKind()); ItemMeta meta = item.getItemMeta(); meta.setDisplayName(installation.getName()); meta.setLore(createOperationalLore(installation)); @@ -125,7 +125,7 @@ public ItemStack createDetailItem(Installation installation) { @SuppressWarnings("deprecation") public ItemStack createDetailItem( Installation installation, InstallationConstruction pendingUpgrade) { - ItemStack item = new ItemStack(iconFor(installation.getKind()), 1); + ItemStack item = iconFor(installation.getKind()); ItemMeta meta = item.getItemMeta(); meta.setDisplayName(installation.getName()); meta.setLore(createOperationalLore(installation, pendingUpgrade)); @@ -272,15 +272,23 @@ static String categoryDisplayName(String categoryId) { return categoryId.replace('_', ' '); } - private Material iconFor(InstallationKind kind) { - return kind == InstallationKind.TRAIN_STATION ? Material.MINECART : Material.GREEN_CONCRETE; + static ItemStack iconFor(InstallationKind kind) { + Material fallback = kind == InstallationKind.TRAIN_STATION ? Material.MINECART : Material.GREEN_CONCRETE; + return IconGetter.getIconOrDefault("installation_" + kind.getCommandName(), fallback); + } + + static ItemStack vehicleIcon(String vehicleTypeId) { + if (vehicleTypeId == null || vehicleTypeId.isBlank()) { + return new ItemStack(Material.MINECART, 1); + } + return IconGetter.getIconOrDefault("vehicle_" + vehicleTypeId.trim(), Material.MINECART); } // Keep the existing legacy text representation, formatting, and exact-string comparisons. @SuppressWarnings("deprecation") public ItemStack createBerthedVehicleIcon( PlayerVehicleRecord record, Optional location, boolean leader) { - ItemStack item = new ItemStack(Material.MINECART, 1); + ItemStack item = vehicleIcon(record.getVehicleTypeId()); ItemMeta meta = item.getItemMeta(); String displayName = VehicleFindMessages.resolveVehicleName(record.getVehicleUuid()); meta.setDisplayName("§e" + displayName); diff --git a/src/main/java/net/tfminecraft/simplefactions/managers/inventory/MilitaryCreator.java b/src/main/java/net/tfminecraft/simplefactions/managers/inventory/MilitaryCreator.java index 0083c30e..465869dc 100644 --- a/src/main/java/net/tfminecraft/simplefactions/managers/inventory/MilitaryCreator.java +++ b/src/main/java/net/tfminecraft/simplefactions/managers/inventory/MilitaryCreator.java @@ -190,7 +190,7 @@ public ItemStack createRegimentDecreaseButton(Faction f, Regiment r) { @SuppressWarnings("deprecation") public ItemStack createVehiclePoolIcon(Faction f) { - ItemStack item = new ItemStack(Material.MINECART, 1); + ItemStack item = IconGetter.getIconOrDefault("vehicle_pool", Material.MINECART); ItemMeta meta = item.getItemMeta(); meta.setDisplayName("§eVehicle Pool"); PlayerVehicleRegistry registry = SimpleFactions.plugin == null diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index e884c74e..5c75799e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -243,6 +243,32 @@ icons: - guild_elevate(black_dye.4) - guild_loans(black_dye.17) - muster(black_dye.11) + - vehicle_aa_turret(coal.7400) + - vehicle_anti_air(coal.7401) + - vehicle_behemoth(coal.7402) + - vehicle_biplane(coal.7403) + - vehicle_bomber(coal.7404) + - vehicle_cloudskimmer(coal.7405) + - vehicle_coal_car(coal.7406) + - vehicle_cruiser(coal.7407) + - vehicle_field_artillery(coal.7408) + - vehicle_fixed_artillery(coal.7409) + - vehicle_flat_car(coal.7410) + - vehicle_gunboat(coal.7411) + - vehicle_gyrobomber(coal.7412) + - vehicle_horse_cart(coal.7413) + - vehicle_ironclad(coal.7414) + - vehicle_monoplane(coal.7415) + - vehicle_passenger_car(coal.7416) + - vehicle_simple_locomotive(coal.7417) + - vehicle_sloop(coal.7418) + - vehicle_small_car(coal.7419) + - vehicle_torpedoboat(coal.7420) + - vehicle_wooden_cart(coal.7421) + - vehicle_pool(coal.7414) + - installation_port(coal.7418) + - installation_airport(coal.7403) + - installation_train_station(coal.7417) base-effects: favoured_guilds: diff --git a/src/main/resources/regiments.yml b/src/main/resources/regiments.yml index 5ce0a879..accd0755 100644 --- a/src/main/resources/regiments.yml +++ b/src/main/resources/regiments.yml @@ -17,8 +17,8 @@ artillery: upkeep: 6.0 expansion-time: 21600 item: - material: BLACK_DYE - model-data: 12 + material: COAL + model-data: 7408 description: - "#c4a35aField Artillery #a89977slots hold guns." - "#a89977Each slot lets the faction keep one" diff --git a/src/test/java/net/tfminecraft/simplefactions/managers/inventory/ArmyMenusCoverageTest.java b/src/test/java/net/tfminecraft/simplefactions/managers/inventory/ArmyMenusCoverageTest.java index 7af1e2df..34ac871b 100644 --- a/src/test/java/net/tfminecraft/simplefactions/managers/inventory/ArmyMenusCoverageTest.java +++ b/src/test/java/net/tfminecraft/simplefactions/managers/inventory/ArmyMenusCoverageTest.java @@ -73,6 +73,7 @@ class ArmyMenusCoverageTest { private MilitaryView military; private java.util.Map oldForming; private final List> scopes = new ArrayList<>(); + private MockedStatic icons; private MockedStatic scoped(Class type) { MockedStatic s = mockStatic(type); @@ -95,7 +96,10 @@ void setup() { military = new MilitaryView(navigation); oldForming = TitleManager.isFormingTitle; TitleManager.isFormingTitle = new HashMap<>(); - scoped(IconGetter.class); + icons = scoped(IconGetter.class); + icons + .when(() -> IconGetter.getIconOrDefault(anyString(), any())) + .thenAnswer(call -> new ItemStack((Material) call.getArgument(1))); ItemAPI api = mock(ItemAPI.class); ItemCreator items = mock(ItemCreator.class); when(api.getCreator()).thenReturn(items); @@ -579,7 +583,11 @@ void vehiclePoolIconShowsTheRegistryAndOutstandingMaintenance() { try (MockedStatic plugin = mockStatic(SimpleFactions.class, CALLS_REAL_METHODS)) { plugin.when(SimpleFactions::getVehicleRegistry).thenReturn(registry); + icons + .when(() -> IconGetter.getIconOrDefault("vehicle_pool", Material.MINECART)) + .thenAnswer(call -> new ItemStack(Material.COAL)); ItemStack item = military.creator.createVehiclePoolIcon(faction); + assertEquals(Material.COAL, item.getType()); assertEquals("Vehicle Pool", name(item)); assertTrue(lore(item).contains("Unpaid: 1 of 1")); assertTrue(lore(item).contains("wagon")); diff --git a/src/test/java/net/tfminecraft/simplefactions/managers/inventory/InstallationCreatorTest.java b/src/test/java/net/tfminecraft/simplefactions/managers/inventory/InstallationCreatorTest.java index 7b9c3e5b..cc87a328 100644 --- a/src/test/java/net/tfminecraft/simplefactions/managers/inventory/InstallationCreatorTest.java +++ b/src/test/java/net/tfminecraft/simplefactions/managers/inventory/InstallationCreatorTest.java @@ -1,10 +1,14 @@ package net.tfminecraft.simplefactions.managers.inventory; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; + +import org.bukkit.configuration.file.YamlConfiguration; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -42,4 +46,24 @@ void categoryDisplayNameUsesConfiguredNameOrReadableId() { assertEquals("Static Emplacements", InstallationCreator.categoryDisplayName("static_emplacements")); assertEquals("land vehicles", InstallationCreator.categoryDisplayName("land_vehicles")); } + + @Test + void everyVehicleHasItsResourcePackIcon() { + List icons = YamlConfiguration + .loadConfiguration(Path.of("src/main/resources/config.yml").toFile()) + .getStringList("icons"); + // The pack draws one icon per vehicle on COAL 7400-7421, in vehicle id order. + List vehicles = List.of( + "aa_turret", "anti_air", "behemoth", "biplane", + "bomber", "cloudskimmer", "coal_car", "cruiser", + "field_artillery", "fixed_artillery", "flat_car", "gunboat", + "gyrobomber", "horse_cart", "ironclad", "monoplane", + "passenger_car", "simple_locomotive", "sloop", "small_car", + "torpedoboat", "wooden_cart"); + for (int n = 0; n < vehicles.size(); n++) { + String icon = "vehicle_" + vehicles.get(n) + "(coal." + (7400 + n) + ")"; + assertTrue(icons.contains(icon), icon); + } + assertTrue(icons.contains("vehicle_pool(coal.7414)")); + } } diff --git a/src/test/java/net/tfminecraft/simplefactions/managers/inventory/InstallationMenusCoverageTest.java b/src/test/java/net/tfminecraft/simplefactions/managers/inventory/InstallationMenusCoverageTest.java index 94d2df54..e7b14fcb 100644 --- a/src/test/java/net/tfminecraft/simplefactions/managers/inventory/InstallationMenusCoverageTest.java +++ b/src/test/java/net/tfminecraft/simplefactions/managers/inventory/InstallationMenusCoverageTest.java @@ -13,6 +13,7 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; +import net.tfminecraft.simplefactions.Cache; import net.tfminecraft.simplefactions.SimpleFactions; import net.tfminecraft.simplefactions.enums.SFGUI; import net.tfminecraft.simplefactions.espionage.EspionageService; @@ -26,6 +27,7 @@ import net.tfminecraft.simplefactions.managers.InventoryManager; import net.tfminecraft.simplefactions.managers.holder.SFInventoryHolder; import net.tfminecraft.simplefactions.objects.Faction; +import net.tfminecraft.simplefactions.util.LegacyModelData; import net.tfminecraft.simplefactions.testsupport.FactionDomainFixture; import net.tfminecraft.simplefactions.vehicles.berth.InstallationVehicleUnberthService; import net.tfminecraft.simplefactions.vehicles.registry.OwnershipMode; @@ -184,6 +186,44 @@ void installationListSummarizesAllKindsAndSortsOperationalRecords() { assertEquals("AIRPORT", ((SFInventoryHolder) top().getHolder()).getSecondaryId()); } + @Test + void configuredIconsDressInstallationsAndBerthedVehiclesWithoutChangingTheirData() { + HashMap previous = Cache.icons; + Cache.icons = new HashMap<>(); + Cache.icons.put("installation_train_station", "coal.7417"); + Cache.icons.put("vehicle_sloop", "coal.7418"); + try { + InstallationCreator creator = new InstallationCreator(); + Installation station = installation("station", InstallationKind.TRAIN_STATION); + ItemStack listed = creator.createInstallationIcon(station); + assertEquals(Material.COAL, listed.getType()); + assertEquals(7417, LegacyModelData.get(listed.getItemMeta())); + assertEquals("station", name(listed)); + assertEquals("station", data(listed, Keys.STRING_KEY)); + ItemStack detail = creator.createDetailItem(station); + assertEquals(Material.COAL, detail.getType()); + assertEquals("station", data(detail, Keys.STRING_KEY)); + assertEquals( + Material.GREEN_CONCRETE, InstallationCreator.iconFor(InstallationKind.PORT).getType()); + Cache.icons.remove("installation_train_station"); + assertEquals( + Material.MINECART, InstallationCreator.iconFor(InstallationKind.TRAIN_STATION).getType()); + + PlayerVehicleRecord sloop = berth("boat-1", "Sloop", station); + ItemStack vehicle = creator.createBerthedVehicleIcon(sloop, Optional.empty(), true); + assertEquals(Material.COAL, vehicle.getType()); + assertEquals(7418, LegacyModelData.get(vehicle.getItemMeta())); + assertEquals("boat-1", data(vehicle, Keys.STRING_KEY)); + assertTrue(lore(vehicle).contains("Type: Sloop")); + assertTrue(lore(vehicle).contains("Click to take")); + assertEquals(Material.MINECART, InstallationCreator.vehicleIcon("unknown").getType()); + assertEquals(Material.MINECART, InstallationCreator.vehicleIcon(null).getType()); + assertEquals(Material.MINECART, InstallationCreator.vehicleIcon(" ").getType()); + } finally { + Cache.icons = previous; + } + } + @Test void listCapacityAndRefreshKeepControlsAndRemoveVanishedInstallations() { for (int n = 0; n < 35; n++) {