diff --git a/README.md b/README.md index 054b477..924d742 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,13 @@ finished item. it, never the count); a natural 20 always succeeds and a natural 1 always fails. The roll never changes the piece: 100% hits is always a Masterwork. +## Requirements + +Paper 1.21.10 with MMOCore, MMOItems, MythicLib and **TLibs 2.3.0 or newer** +(builds pin 2.6.1). The item refresh listens for TLibs' character session +event, so on an older TLibs its listener cannot register. `plugin.yml` cannot +declare a minimum version, so update TLibs before or together with this plugin. + ## Credits Originally authored by **Drefvelin**. diff --git a/pom.xml b/pom.xml index 36d1c83..bec1f95 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ UTF-8 full 2026-09-22T00:00:00Z - 2.0.0 + 2.6.1 diff --git a/src/main/java/net/tfminecraft/advancedcrafting/managers/CraftRefreshListener.java b/src/main/java/net/tfminecraft/advancedcrafting/managers/CraftRefreshListener.java index fa8c2a1..1c20151 100644 --- a/src/main/java/net/tfminecraft/advancedcrafting/managers/CraftRefreshListener.java +++ b/src/main/java/net/tfminecraft/advancedcrafting/managers/CraftRefreshListener.java @@ -21,6 +21,7 @@ import net.tfminecraft.tlibs.armour.ArmorEquipEvent; import net.tfminecraft.tlibs.armour.ArmorType; +import net.tfminecraft.tlibs.character.CharacterSessionStartEvent; import net.tfminecraft.advancedcrafting.AdvancedCrafting; import net.tfminecraft.advancedcrafting.utils.AcItemRefresher; @@ -88,7 +89,16 @@ public void onArmorEquip(ArmorEquipEvent event) { /** After a restart every player rejoins, so this brings their carried items up to date without anyone acting. */ @EventHandler(priority = EventPriority.MONITOR) public void onJoin(PlayerJoinEvent event) { - Player player = event.getPlayer(); + sweepLater(event.getPlayer()); + } + + /** A character's inventory is only put on when it is played, after the join sweep has already run. */ + @EventHandler(priority = EventPriority.MONITOR) + public void onSessionStart(CharacterSessionStartEvent event) { + sweepLater(event.getPlayer()); + } + + private void sweepLater(Player player) { Bukkit.getScheduler().runTask(AdvancedCrafting.plugin, () -> { if (!player.isOnline()) { return; diff --git a/src/test/java/net/tfminecraft/advancedcrafting/RefreshListenerCoverageTest.java b/src/test/java/net/tfminecraft/advancedcrafting/RefreshListenerCoverageTest.java index 69a5072..8e790ba 100644 --- a/src/test/java/net/tfminecraft/advancedcrafting/RefreshListenerCoverageTest.java +++ b/src/test/java/net/tfminecraft/advancedcrafting/RefreshListenerCoverageTest.java @@ -7,6 +7,7 @@ import net.tfminecraft.advancedcrafting.managers.*; import net.tfminecraft.advancedcrafting.utils.*; import net.tfminecraft.tlibs.armour.*; +import net.tfminecraft.tlibs.character.CharacterSessionStartEvent; import net.tfminecraft.tlibs.event.MMOItemRebuildEvent; import org.bukkit.Material; import org.bukkit.block.DoubleChest; @@ -158,6 +159,33 @@ void joinSweepRefreshesInventoryArmourOffhandAndEnderChestOneTickLater() throws verify(gone, never()).getInventory(); } + @Test + void characterSessionStartSweepsTheCharacterInventoryOneTickLater() throws Exception { + when(plugin.isEnabled()).thenReturn(true); + var p = server.addPlayer(); + var iron = ingredient("iron", ""); + iron.setRevision(1); + var stale = iron.build(); + iron.setRevision(2); + // The character's body is put on after the join sweep, so the join tick finds nothing to refresh. + var join = mock(PlayerJoinEvent.class); + when(join.getPlayer()).thenReturn(p); + var listener = new CraftRefreshListener(); + listener.onJoin(join); + server.getScheduler().performOneTick(); + p.getInventory().setChestplate(stale.clone()); + p.getInventory().setItem(5, stale.clone()); + p.getEnderChest().setItem(1, stale.clone()); + var start = mock(CharacterSessionStartEvent.class); + when(start.getPlayer()).thenReturn(p); + listener.onSessionStart(start); + assertEquals(1, AcItemTags.getStoredRevision(p.getInventory().getChestplate())); + server.getScheduler().performOneTick(); + assertEquals(2, AcItemTags.getStoredRevision(p.getInventory().getChestplate())); + assertEquals(2, AcItemTags.getStoredRevision(p.getInventory().getItem(5))); + assertEquals(2, AcItemTags.getStoredRevision(p.getEnderChest().getItem(1))); + } + @Test void aBrokenItemIsLoggedAndTheSweepCarriesOn() { when(plugin.isEnabled()).thenReturn(true);