diff --git a/.github/dependencies.sha256 b/.github/dependencies.sha256 index 1888689..e878548 100644 --- a/.github/dependencies.sha256 +++ b/.github/dependencies.sha256 @@ -4,3 +4,4 @@ a37f7789fcdcd11c9e5890a2fac742aa4501749588af23182991953e06ee1d17 libs/MMOItems- 225aa7f75d4e6e6ae6b3ad87a7ca678c025c027f00374ab1062275d24f3a73c9 libs/MythicLib-1.7.1-SNAPSHOT.jar 81d511d0830951f988615b6533cc93e82d00a83fb31e8ccbb36441ae3e8157ef libs/MMOCore-1.13.1-SNAPSHOT.jar 5a01b37bd7442fb0f2c809cadac82ba70f75173956e04efac3336595cc070368 libs/ItemsAdder-4.0.18.jar +c571502e768640c7cff10c49b3eef904ccf3fd95bd81803913abfe43cfc09746 libs/NBTAPI-2.16.1.jar diff --git a/.github/scripts/install-local-dependencies.sh b/.github/scripts/install-local-dependencies.sh index 8ee4873..23f32f8 100644 --- a/.github/scripts/install-local-dependencies.sh +++ b/.github/scripts/install-local-dependencies.sh @@ -22,3 +22,6 @@ mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1. mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \ -Dfile="libs/ItemsAdder-4.0.18.jar" -DgroupId="local" -DartifactId="ItemsAdder" \ -Dversion="4.0.18-tfmc-5a01b37bd744" -Dpackaging=jar -DgeneratePom=true "$@" +mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \ + -Dfile="libs/NBTAPI-2.16.1.jar" -DgroupId="local" -DartifactId="item-nbt-api-plugin" \ + -Dversion="2.16.1-tfmc-c571502e7686" -Dpackaging=jar -DgeneratePom=true "$@" diff --git a/.github/scripts/prepare-release.sh b/.github/scripts/prepare-release.sh index 1dd1106..89d025c 100644 --- a/.github/scripts/prepare-release.sh +++ b/.github/scripts/prepare-release.sh @@ -9,4 +9,5 @@ curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/225aa7f75d4e/MythicLib-1.7.1-SNAPSHOT.jar?ref=$ref" > "libs/MythicLib-1.7.1-SNAPSHOT.jar" curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/81d511d08309/MMOCore-1.13.1-SNAPSHOT.jar?ref=$ref" > "libs/MMOCore-1.13.1-SNAPSHOT.jar" curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/5a01b37bd744/ItemsAdder-4.0.18.jar?ref=$ref" > "libs/ItemsAdder-4.0.18.jar" +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/c571502e7686/NBTAPI-2.16.1.jar?ref=$ref" > "libs/NBTAPI-2.16.1.jar" bash .github/scripts/install-local-dependencies.sh "$@" diff --git a/pom.xml b/pom.xml index b0143e8..1441572 100644 --- a/pom.xml +++ b/pom.xml @@ -88,6 +88,13 @@ + + + local + item-nbt-api-plugin + 2.16.1-tfmc-c571502e7686 + provided + local MMOItems diff --git a/src/main/java/net/tfminecraft/magic/gear/GearItemBuilder.java b/src/main/java/net/tfminecraft/magic/gear/GearItemBuilder.java index 7c23500..5675a4c 100644 --- a/src/main/java/net/tfminecraft/magic/gear/GearItemBuilder.java +++ b/src/main/java/net/tfminecraft/magic/gear/GearItemBuilder.java @@ -46,7 +46,7 @@ public static ItemStack rewriteSockets(ItemStack stack, int band) { List parts = GearProvenance.resolveParts(stack); List colours = SocketLayout.colours(archetype, parts, band); ItemStack rewritten = applyMmoData(stack, colours, parts); - rewritten = GearModelResolver.apply(rewritten, type, parts); + rewritten = GearSkin.keep(stack, GearModelResolver.apply(rewritten, type, parts)); copyGearPdc(stack, rewritten); GearProvenance.lockSockets(rewritten); WeaponRequirement.fromItem(stack).persist(rewritten); diff --git a/src/main/java/net/tfminecraft/magic/gear/GearRefresher.java b/src/main/java/net/tfminecraft/magic/gear/GearRefresher.java index 7ba3765..eaaca55 100644 --- a/src/main/java/net/tfminecraft/magic/gear/GearRefresher.java +++ b/src/main/java/net/tfminecraft/magic/gear/GearRefresher.java @@ -134,7 +134,7 @@ private static ItemStack rewrite(ItemStack stack, List colours, List i.getArgument(1)); var lore = mockStatic(WeaponLore.class)) { models .when(() -> GearModelResolver.apply(any(), any(), any())) .thenAnswer(i -> i.getArgument(0)); lore.when(() -> WeaponLore.updateItem(any())).thenAnswer(i -> i.getArgument(0)); assertSame(stack, GearItemBuilder.rewriteSockets(stack, 1)); + skin.verify(() -> GearSkin.keep(same(stack), same(stack))); assertTrue(GearProvenance.socketsLocked(stack)); assertEquals("core:1", GearProvenance.partsRaw(stack)); } diff --git a/src/test/java/net/tfminecraft/magic/GearRefresherCoverageTest.java b/src/test/java/net/tfminecraft/magic/GearRefresherCoverageTest.java index 314bb9a..f853f7e 100644 --- a/src/test/java/net/tfminecraft/magic/GearRefresherCoverageTest.java +++ b/src/test/java/net/tfminecraft/magic/GearRefresherCoverageTest.java @@ -101,6 +101,7 @@ void rebuildPreservesGearPdcAmountsAndExistingGems() { try (var nbt = mockStatic(NBTItem.class); var stats = mockStatic(GearStatApplicator.class); var model = mockStatic(GearModelResolver.class); + var skin = mockStatic(GearSkin.class, i -> i.getArgument(1)); var lore = mockStatic(WeaponLore.class); var items = mockConstruction( @@ -130,6 +131,7 @@ void rebuildPreservesGearPdcAmountsAndExistingGems() { var captured = org.mockito.ArgumentCaptor.forClass(GemSocketsData.class); verify(items.constructed().getFirst()).setData(eq(ItemStats.GEM_SOCKETS), captured.capture()); assertEquals(List.of(good), captured.getValue().getGems()); + skin.verify(() -> GearSkin.keep(same(item), same(built))); } } @@ -143,6 +145,7 @@ void outdatedRunesRebuildCurrentGearAndStampTheirRevisions() { try (var nbt = mockStatic(NBTItem.class); var stats = mockStatic(GearStatApplicator.class); var model = mockStatic(GearModelResolver.class); + var skin = mockStatic(GearSkin.class, i -> i.getArgument(1)); var lore = mockStatic(WeaponLore.class); var runes = mockStatic(RuneRefresher.class); var items = @@ -183,6 +186,7 @@ void incompatibleGemsAreHeldAndFailuresNeverReplaceOriginals() { try (var nbt = mockStatic(NBTItem.class); var stats = mockStatic(GearStatApplicator.class); var model = mockStatic(GearModelResolver.class); + var skin = mockStatic(GearSkin.class, i -> i.getArgument(1)); var lore = mockStatic(WeaponLore.class); var broken = mockStatic(GearBrokenMarker.class); var items = diff --git a/src/test/java/net/tfminecraft/magic/GearSkinTest.java b/src/test/java/net/tfminecraft/magic/GearSkinTest.java new file mode 100644 index 0000000..a5b2cf4 --- /dev/null +++ b/src/test/java/net/tfminecraft/magic/GearSkinTest.java @@ -0,0 +1,66 @@ +package net.tfminecraft.magic; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import io.lumine.mythic.lib.api.item.NBTItem; +import net.tfminecraft.magic.gear.GearSkin; +import net.tfminecraft.magic.util.LegacyModelData; +import net.tfminecraft.tlibs.objects.api.subapi.ItemSkinPreserver; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.junit.jupiter.api.*; +import org.mockito.MockedStatic; + +class GearSkinTest { + MockedStatic preserver; + MockedStatic nbt; + MockedStatic models; + + @BeforeEach + void mockStatics() { + preserver = mockStatic(ItemSkinPreserver.class); + nbt = mockStatic(NBTItem.class); + models = mockStatic(LegacyModelData.class); + } + + @AfterEach + void closeStatics() { + preserver.close(); + nbt.close(); + models.close(); + } + + /** A weapon with skin data, an {@code amodel} tag and an optional current model. */ + ItemStack weapon(boolean skinData, String amodel, Integer model, boolean hasMeta) { + var stack = mock(ItemStack.class); + var meta = hasMeta ? mock(ItemMeta.class) : null; + when(stack.getItemMeta()).thenReturn(meta); + preserver.when(() -> ItemSkinPreserver.hasSkinData(same(stack))).thenReturn(skinData); + var tags = mock(NBTItem.class); + when(tags.getString("amodel")).thenReturn(amodel); + nbt.when(() -> NBTItem.get(same(stack))).thenReturn(tags); + if (meta != null) { + models.when(() -> LegacyModelData.has(same(meta))).thenReturn(model != null); + if (model != null) models.when(() -> LegacyModelData.get(same(meta))).thenReturn(model); + } + return stack; + } + + @Test + void rebuildsKeepAWornSkinAndDropAStaleTag() { + var rebuilt = mock(ItemStack.class); + var dressed = mock(ItemStack.class); + preserver.when(() -> ItemSkinPreserver.apply(any(), same(rebuilt))).thenReturn(dressed); + + assertSame(dressed, GearSkin.keep(weapon(true, "66", 66, true), rebuilt)); + assertSame(dressed, GearSkin.keep(weapon(true, null, null, true), rebuilt)); + assertSame(dressed, GearSkin.keep(weapon(true, "", null, true), rebuilt)); + + assertSame(rebuilt, GearSkin.keep(weapon(true, "66", 2, true), rebuilt)); + assertSame(rebuilt, GearSkin.keep(weapon(true, "66", null, true), rebuilt)); + assertSame(rebuilt, GearSkin.keep(weapon(true, "66", null, false), rebuilt)); + assertSame(rebuilt, GearSkin.keep(weapon(false, "66", 66, true), rebuilt)); + assertNull(GearSkin.keep(weapon(true, "66", 66, true), null)); + } +}