Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0536d4c717 |
No files matched your search
@@ -18,6 +18,7 @@ import org.bukkit.persistence.PersistentDataType;
|
||||
* The caller must enforce session custody and suppress vanilla item uses; this class registers no events.
|
||||
*/
|
||||
public final class SessionControls {
|
||||
public static final NamespacedKey COOLDOWN_MODEL = new NamespacedKey("fantasystick", "cooldown_control");
|
||||
private final games.dmg.fantasystick.ability.AbilityRegistry registry;
|
||||
private final Clock clock;
|
||||
private static final NamespacedKey VERSION = key("control_version");
|
||||
@@ -92,6 +93,7 @@ public final class SessionControls {
|
||||
var meta = item.getItemMeta();
|
||||
meta.displayName(Component.text(icon.name()));
|
||||
meta.setMaxStackSize(1);
|
||||
if (cooling) meta.setItemModel(COOLDOWN_MODEL);
|
||||
var data = meta.getPersistentDataContainer();
|
||||
data.set(VERSION, PersistentDataType.INTEGER, 1);
|
||||
data.set(OWNER, PersistentDataType.STRING, owner.toString());
|
||||
|
||||
@@ -172,6 +172,8 @@ class AbilityEngineNativeTest {
|
||||
assertTrue(cooled.cooldowns().get("test_focus").isAfter(java.time.Instant.now()));
|
||||
var cooling = a.core.inventory.getItem(2);
|
||||
assertEquals(Material.GRAY_STAINED_GLASS_PANE, cooling.getType());
|
||||
assertEquals(games.dmg.fantasystick.items.SessionControls.COOLDOWN_MODEL,
|
||||
cooling.getItemMeta().getItemModel());
|
||||
assertEquals(net.kyori.adventure.text.Component.text("Test Focus — Cooling Down"), cooling.getItemMeta().displayName());
|
||||
assertEquals("test_focus", new games.dmg.fantasystick.items.SessionControls(registry).ability(cooling).orElseThrow());
|
||||
|
||||
@@ -189,6 +191,8 @@ class AbilityEngineNativeTest {
|
||||
a.core.inventory.setItemInOffHand(sheet); f.activate(a);
|
||||
a.core.inventory.getInventory().setSelectedSlot(2);
|
||||
assertEquals(Material.GRAY_STAINED_GLASS_PANE, a.core.inventory.getItem(2).getType());
|
||||
assertEquals(games.dmg.fantasystick.items.SessionControls.COOLDOWN_MODEL,
|
||||
a.core.inventory.getItem(2).getItemMeta().getItemModel());
|
||||
assertEquals("test_focus", new games.dmg.fantasystick.items.SessionControls(registry)
|
||||
.ability(a.core.inventory.getItem(2)).orElseThrow());
|
||||
f.dispatcher.accept(new org.bukkit.event.player.PlayerInteractEvent(a.player, Action.RIGHT_CLICK_AIR,
|
||||
|
||||
@@ -1078,13 +1078,22 @@ class EquipmentSessionsNativeTest {
|
||||
assertTrue(f.sessions.acknowledgeProgress(active, learned.revision(), cooled));
|
||||
var pane = actor.inventory.getItem(2).clone();
|
||||
assertEquals(Material.GRAY_STAINED_GLASS_PANE, pane.getType());
|
||||
assertEquals(SessionControls.COOLDOWN_MODEL, pane.getItemMeta().getItemModel(),
|
||||
"Only the acknowledged persisted cooldown control selects the cosmetic model");
|
||||
assertFalse(f.sessions.acknowledgeProgress(active, current.revision(), learned),
|
||||
"A stale pre-cooldown acknowledgment cannot replace the current presentation");
|
||||
assertEquals(SessionControls.COOLDOWN_MODEL,
|
||||
actor.inventory.getItem(2).getItemMeta().getItemModel());
|
||||
|
||||
f.sessions.exit(actor.player); f.state(actor); f.activate(actor);
|
||||
assertEquals(Material.GRAY_STAINED_GLASS_PANE, actor.inventory.getItem(2).getType(),
|
||||
"Resume reconstructs the future persisted deadline");
|
||||
assertEquals(SessionControls.COOLDOWN_MODEL, actor.inventory.getItem(2).getItemMeta().getItemModel());
|
||||
clock.advance(Duration.ofSeconds(30));
|
||||
f.sessions.refreshCooldownControls(1);
|
||||
assertEquals(Material.SNOWBALL, actor.inventory.getItem(2).getType());
|
||||
assertNull(actor.inventory.getItem(2).getItemMeta().getItemModel(),
|
||||
"Exact-deadline restoration replaces the whole control without stale cosmetic metadata");
|
||||
assertNotEquals(pane, actor.inventory.getItem(2), "The retired pane is no longer installed");
|
||||
assertEquals(deadline, f.sessions.currentRecord(f.sessions.active(actor.id).orElseThrow()).orElseThrow()
|
||||
.cooldowns().get("fireball"), "Visual restoration does not rewrite the deadline");
|
||||
|
||||
@@ -88,11 +88,15 @@ class FireballNativeTest {
|
||||
assertTrue(a.messages.stream().anyMatch(message -> message.contains("ready in")));
|
||||
var deadline = storage.find(a.core.record.id()).get().orElseThrow().cooldowns().get("fireball");
|
||||
assertTrue(deadline.isAfter(java.time.Instant.now()));
|
||||
assertEquals(games.dmg.fantasystick.items.SessionControls.COOLDOWN_MODEL,
|
||||
a.core.inventory.getItem(2).getItemMeta().getItemModel());
|
||||
|
||||
var sheet = a.core.inventory.getItemInOffHand().clone();
|
||||
a.core.inventory.setItemInOffHand(null); f.changed(a); PartyBookNativeTest.drain(f); f.awaitCharacterAndReceipt(a);
|
||||
a.core.inventory.setItemInOffHand(sheet); f.activate(a);
|
||||
a.core.inventory.getInventory().setSelectedSlot(2);
|
||||
assertEquals(games.dmg.fantasystick.items.SessionControls.COOLDOWN_MODEL,
|
||||
a.core.inventory.getItem(2).getItemMeta().getItemModel());
|
||||
assertEquals("fireball", new games.dmg.fantasystick.items.SessionControls(
|
||||
(games.dmg.fantasystick.ability.AbilityRegistry) FantasyStickLifecycleNativeTest.Fixture.field(f.plugin, "abilityRegistry"))
|
||||
.ability(a.core.inventory.getItem(2)).orElseThrow());
|
||||
@@ -145,6 +149,8 @@ class FireballNativeTest {
|
||||
assertTrue(new games.dmg.fantasystick.items.SessionControls(
|
||||
(games.dmg.fantasystick.ability.AbilityRegistry) FantasyStickLifecycleNativeTest.Fixture.field(f.plugin, "abilityRegistry"))
|
||||
.ability(a.core.inventory.getItem(2)).isEmpty());
|
||||
assertNull(a.core.inventory.getItem(2).getItemMeta().getItemModel(),
|
||||
"Unlearning replaces the cooling control and leaves no stale invisible model");
|
||||
|
||||
PartyBookNativeTest.click(f, a, PartyBookNativeTest.button(a, "[+1 WIS]"));
|
||||
PartyBookNativeTest.drain(f); PartyBookNativeTest.drain(f);
|
||||
@@ -154,6 +160,9 @@ class FireballNativeTest {
|
||||
PartyBookNativeTest.click(f, a, PartyBookNativeTest.button(a, "[Learn]"));
|
||||
PartyBookNativeTest.drain(f); PartyBookNativeTest.drain(f);
|
||||
assertEquals(deadline, storage.find(a.core.record.id()).get().orElseThrow().cooldowns().get("fireball"));
|
||||
assertEquals(games.dmg.fantasystick.items.SessionControls.COOLDOWN_MODEL,
|
||||
a.core.inventory.getItem(2).getItemMeta().getItemModel(),
|
||||
"Relearning reconstructs the retained future cooldown model");
|
||||
cast(f, a); assertEquals(1, launches.get());
|
||||
assertTrue(a.messages.stream().anyMatch(message -> message.contains("ready in")));
|
||||
|
||||
@@ -164,6 +173,8 @@ class FireballNativeTest {
|
||||
b.core.inventory.getInventory().setSelectedSlot(2);
|
||||
assertEquals(org.bukkit.Material.GRAY_STAINED_GLASS_PANE, b.core.inventory.getItem(2).getType(),
|
||||
"The transferred character reconstructs its retained cooldown pane");
|
||||
assertEquals(games.dmg.fantasystick.items.SessionControls.COOLDOWN_MODEL,
|
||||
b.core.inventory.getItem(2).getItemMeta().getItemModel());
|
||||
assertEquals("fireball", new games.dmg.fantasystick.items.SessionControls(
|
||||
(games.dmg.fantasystick.ability.AbilityRegistry) FantasyStickLifecycleNativeTest.Fixture.field(f.plugin, "abilityRegistry"))
|
||||
.ability(b.core.inventory.getItem(2)).orElseThrow());
|
||||
|
||||
@@ -48,6 +48,7 @@ class SessionControlsNativeTest {
|
||||
item.getItemMeta().displayName());
|
||||
assertEquals(1, item.getAmount());
|
||||
assertEquals(1, item.getMaxStackSize());
|
||||
assertNull(item.getItemMeta().getItemModel(), "Book, basic attack and No Ability remain unaffected");
|
||||
var expected = new SessionControls.Identity(owner, session, slot);
|
||||
assertEquals(expected, controls.identify(item).orElseThrow());
|
||||
assertTrue(controls.owned(item, owner, session));
|
||||
@@ -82,6 +83,7 @@ class SessionControlsNativeTest {
|
||||
var item = roundTrip(items[abilitySlot + 2]);
|
||||
assertEquals(materials.get(index), item.getType(), ids.get(index));
|
||||
assertEquals(Component.text(names.get(index)), item.getItemMeta().displayName());
|
||||
assertNull(item.getItemMeta().getItemModel(), "Ready ability icons remain unaffected");
|
||||
assertEquals(ids.get(index), item.getItemMeta().getPersistentDataContainer()
|
||||
.get(key("control_ability_id"), PersistentDataType.STRING));
|
||||
assertEquals(1, item.getAmount());
|
||||
@@ -113,9 +115,24 @@ class SessionControlsNativeTest {
|
||||
assertEquals("cooldown", pane.getPersistentDataContainer().get(key("control_kind"), PersistentDataType.STRING));
|
||||
assertEquals(java.util.Optional.of("fireball"), timed.ability(pane));
|
||||
assertEquals(new SessionControls.Identity(owner, session, slot), timed.identify(pane).orElseThrow());
|
||||
assertEquals(SessionControls.COOLDOWN_MODEL, pane.getItemMeta().getItemModel());
|
||||
}
|
||||
assertEquals(Material.ECHO_SHARD, items[4].getType(), "A deadline equal to now is ready");
|
||||
assertNull(items[4].getItemMeta().getItemModel(), "An exact-deadline ready icon retains no stale model");
|
||||
assertEquals(Material.PAPER, items[5].getType(), "Unknown saved IDs remain unavailable, not cooling panes");
|
||||
assertNull(items[5].getItemMeta().getItemModel(), "Unknown controls remain visible and unaffected");
|
||||
|
||||
var genuineWithoutModel = items[2].clone();
|
||||
var genuineMeta = genuineWithoutModel.getItemMeta();
|
||||
genuineMeta.setItemModel(null);
|
||||
genuineWithoutModel.setItemMeta(genuineMeta);
|
||||
assertEquals(java.util.Optional.of("fireball"), timed.ability(genuineWithoutModel),
|
||||
"Cosmetic model metadata is not casting or session authority");
|
||||
var ordinaryPane = new ItemStack(Material.GRAY_STAINED_GLASS_PANE);
|
||||
var ordinaryMeta = ordinaryPane.getItemMeta();
|
||||
ordinaryMeta.setItemModel(SessionControls.COOLDOWN_MODEL);
|
||||
ordinaryPane.setItemMeta(ordinaryMeta);
|
||||
assertRejected(ordinaryPane);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"model": {
|
||||
"type": "minecraft:select",
|
||||
"property": "minecraft:display_context",
|
||||
"cases": [
|
||||
{
|
||||
"when": [
|
||||
"firstperson_lefthand",
|
||||
"firstperson_righthand"
|
||||
],
|
||||
"model": {
|
||||
"type": "minecraft:empty"
|
||||
}
|
||||
}
|
||||
],
|
||||
"fallback": {
|
||||
"type": "minecraft:model",
|
||||
"model": "minecraft:item/gray_stained_glass_pane"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "Fantasy Stick ${version} sheet presentation",
|
||||
"description": "Fantasy Stick ${version} first-person presentation",
|
||||
"min_format": [88, 0],
|
||||
"max_format": [88, 0]
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ class DistributionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test void packagesVersionedContextSensitiveSheetResourcePackAndMatchingRuntimeMetadata() throws Exception {
|
||||
@Test void packagesVersionedContextSensitiveResourcePackAndMatchingRuntimeMetadata() throws Exception {
|
||||
Path artifact = Path.of(System.getProperty("distribution.jar"));
|
||||
Path pack = Path.of(System.getProperty("resource.pack.zip"));
|
||||
String version = System.getProperty("distribution.version");
|
||||
@@ -129,6 +129,19 @@ class DistributionTest {
|
||||
assertTrue(json.contains("firstperson_righthand"));
|
||||
assertTrue(json.contains("minecraft:empty"));
|
||||
assertTrue(json.contains("minecraft:item/paper"), "Inventory and other contexts retain Paper presentation");
|
||||
var cooldownModel = zip.getEntry("assets/fantasystick/items/cooldown_control.json");
|
||||
assertNotNull(cooldownModel, "The single pack includes the dedicated cooldown-control model");
|
||||
String cooldownJson;
|
||||
try (var input = zip.getInputStream(cooldownModel)) {
|
||||
cooldownJson = new String(input.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
|
||||
}
|
||||
assertTrue(cooldownJson.contains("minecraft:select"));
|
||||
assertTrue(cooldownJson.contains("minecraft:display_context"));
|
||||
assertTrue(cooldownJson.contains("firstperson_lefthand"));
|
||||
assertTrue(cooldownJson.contains("firstperson_righthand"));
|
||||
assertTrue(cooldownJson.contains("minecraft:empty"));
|
||||
assertTrue(cooldownJson.contains("minecraft:item/gray_stained_glass_pane"),
|
||||
"Hotbar, inventory and all other contexts retain gray-pane presentation");
|
||||
}
|
||||
try (var jar = new JarFile(artifact.toFile())) {
|
||||
var metadata = jar.getJarEntry("sheet-resource-pack.properties"); assertNotNull(metadata);
|
||||
|
||||
Reference in new issue
Block a user