Compare commits

...
2 Commits
Author SHA1 Message Date
dmg be8870502f fix(session): prioritize native door interaction
Release / release (push) Successful in 9m57s
2026-09-21 11:57:22 -04:00
dmg 8b5461753c fix(book): shorten gear summary labels
Release / release (push) Successful in 9m45s
2026-09-21 11:49:45 -04:00
6 changed files with 48 additions and 5 deletions

No files matched your search

@@ -205,7 +205,7 @@ public final class CharacterBookController implements Consumer<ControlInput>, Au
return item;
}
private Component gearPage(CharacterRecord record){return Component.text("Current gear\n\nHead: Cosmetic\nonly\nChestplate: "+tier(record.gear().chestplate())+"\nLeggings: "+tier(record.gear().leggings())+"\nBoots: "+tier(record.gear().boots()));}
private Component gearPage(CharacterRecord record){return Component.text("Gear\n\nHead: Cosmetic\nChestplate: "+tier(record.gear().chestplate())+"\nLeggings: "+tier(record.gear().leggings())+"\nBoots: "+tier(record.gear().boots()));}
private static String tier(games.dmg.fantasystick.persistence.GearTier tier){String value=tier.name().toLowerCase(java.util.Locale.ROOT);return Character.toUpperCase(value.charAt(0))+value.substring(1);}
private java.util.List<Component> overviewPages(CharacterRecord record, ControlInput input, StatView view) {
@@ -41,7 +41,7 @@ public final class TailBooks {
.append("\nCoins: ").append(character.coins());
for (Stat stat : Stat.values()) summary.append('\n').append(stat).append(": ").append(character.stats().get(stat));
pages.addAll(BookPagination.pages(summary.toString()));
pages.addAll(BookPagination.pages("Current gear\nHead: Cosmetic only\nChestplate: "+tier(character.gear().chestplate())+"\nLeggings: "+tier(character.gear().leggings())+"\nBoots: "+tier(character.gear().boots())));
pages.addAll(BookPagination.pages("Gear\nHead: Cosmetic\nChestplate: "+tier(character.gear().chestplate())+"\nLeggings: "+tier(character.gear().leggings())+"\nBoots: "+tier(character.gear().boots())));
if (character.learned().isEmpty()) pages.addAll(BookPagination.pages("Abilities: None"));
character.learned().stream().sorted().forEach(ability -> {
var slots = new ArrayList<String>();
@@ -353,6 +353,7 @@ public final class EquipmentSessionEvents implements Listener, AutoCloseable {
if (allowed && event.getHand() == EquipmentSlot.HAND && (event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_AIR
|| event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK)) {
var selected = sessions.selectedControl(event.getPlayer(), event.getItem()).orElse(null);
if (selected != null && !selected.ability().isEmpty() && doorInteraction(event)) return;
if (selected != null && useGesture(selected)) {
org.bukkit.entity.Entity target = selected.ability().equals("hex")
|| selected.ability().equals("mending_light")
@@ -367,6 +368,12 @@ public final class EquipmentSessionEvents implements Listener, AutoCloseable {
}
}
private boolean doorInteraction(org.bukkit.event.player.PlayerInteractEvent event) {
var block = event.getClickedBlock();
return event.getAction() == org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK && block != null
&& block.getBlockData() instanceof org.bukkit.block.data.type.Door;
}
private void beginDraw(Player player, ItemStack item, EquipmentSessions.SelectedControl selected) {
UUID owner = player.getUniqueId();
if (closed || draws.containsKey(owner) || player.hasActiveItem()) return;
@@ -327,8 +327,9 @@ class CharacterBookNativeTest {
assertTrue(pages.size() <= 100, "Keep each native linked-book view bounded");
assertTrue(pages.get(0).getString().contains("STR: 0 [+1 STR]"));
assertTrue(pages.get(0).getString().contains("INT: 12 [+1 INT]"));
assertTrue(pages.get(1).getString().startsWith("Current gear"));
assertTrue(pages.get(1).getString().contains("Head: Cosmetic"));
assertTrue(pages.get(1).getString().startsWith("Gear\n\nHead: Cosmetic\nChestplate:"));
assertFalse(pages.get(1).getString().contains("Current gear"));
assertFalse(pages.get(1).getString().contains("Cosmetic\nonly"));
assertTrue(pages.get(2).getString().startsWith("Active abilities"));
assertTrue(pages.get(2).getString().contains("3: No Ability"));
int index = firstPageStarting(pages, "Ability index");
@@ -1283,6 +1283,40 @@ class EquipmentSessionEventsNativeTest {
}
}
@Test void nativeDoorInteractionTakesPrecedenceOverAbilityUseAndLongbowDraw() throws Exception {
try (var f = new Fixture()) {
f.loadout("quickstep", "longbow");
var a = f.actor; f.core.activate(a);
var door = org.mockito.Mockito.mock(org.bukkit.block.Block.class);
org.mockito.Mockito.doReturn(org.mockito.Mockito.mock(org.bukkit.block.data.type.Door.class)).when(door).getBlockData();
for (int slot : new int[]{2, 3}) {
a.inventory.getInventory().setSelectedSlot(slot);
var event = new org.bukkit.event.player.PlayerInteractEvent(a.player,
org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, a.inventory.getItem(slot), door,
org.bukkit.block.BlockFace.UP, org.bukkit.inventory.EquipmentSlot.HAND);
event.setUseInteractedBlock(org.bukkit.event.Event.Result.ALLOW);
int beforeInputs = f.inputs.size(); int beforeDraws = a.useStarts;
f.dispatcher.accept(event);
assertEquals(org.bukkit.event.Event.Result.ALLOW, event.useInteractedBlock());
assertEquals(org.bukkit.event.Event.Result.DENY, event.useItemInHand());
assertEquals(beforeInputs, f.inputs.size(), "A door click is not an ability input");
assertEquals(beforeDraws, a.useStarts, "A door click does not begin Longbow drawing");
}
var stone = org.mockito.Mockito.mock(org.bukkit.block.Block.class);
org.mockito.Mockito.doReturn(org.mockito.Mockito.mock(org.bukkit.block.data.BlockData.class)).when(stone).getBlockData();
a.inventory.getInventory().setSelectedSlot(2);
var ordinaryBlock = new org.bukkit.event.player.PlayerInteractEvent(a.player,
org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, a.inventory.getItem(2), stone,
org.bukkit.block.BlockFace.UP, org.bukkit.inventory.EquipmentSlot.HAND);
f.dispatcher.accept(ordinaryBlock); assertEquals(1, f.inputs.size(), "Non-door ability use remains active");
a.inventory.getInventory().setSelectedSlot(3);
var air = new org.bukkit.event.player.PlayerInteractEvent(a.player,
org.bukkit.event.block.Action.RIGHT_CLICK_AIR, a.inventory.getItem(3), null,
org.bukkit.block.BlockFace.SELF, org.bukkit.inventory.EquipmentSlot.HAND);
f.dispatcher.accept(air); assertEquals(1, a.useStarts, "Air use still begins Longbow drawing");
}
}
@Test void selectedAbilityUseReachesItsHandlerWithoutVanillaThrowDrinkEquipBlockOrPlacement() throws Exception {
try (var f = new Fixture()) {
String[] abilities = {"chain_lightning", "purify", "guardian_bond", "shield_bash", "rallying_cry", "frost_nova", "revive"};
@@ -100,8 +100,9 @@ class TailBooksNativeTest {
for (String expected : List.of("Tail of Ari", "Level: 2", "XP: 100", "Unspent points: 30", "Coins: 123",
"STR: 0", "DEX: 0", "CON: 10", "INT: 0", "WIS: 0", "CHR: 0")) assertTrue(summary.contains(expected), expected);
String complete = String.join("", pages).replace("\n", "");
for (String expected : List.of("Current gear", "Head: Cosmetic only", "Chestplate: Diamond", "Leggings: Gold", "Boots: Leather"))
for (String expected : List.of("GearHead: Cosmetic", "Chestplate: Diamond", "Leggings: Gold", "Boots: Leather"))
assertTrue(complete.contains(expected), expected);
assertFalse(complete.contains("Current gear")); assertFalse(complete.contains("Cosmetic only"));
String wind = pages.stream().map(p -> p.replace("\n", "")).filter(p -> p.contains("Ability: second_wind")).findFirst().orElseThrow();
assertTrue(wind.contains("Slots: 1, 3")); assertTrue(wind.contains(expiry.toString()));
assertFalse(wind.contains("unknown:雪"), "Each learned ability starts its own page/section");