This commit is contained in:
1 parent
fa917e57ba
commit
ae741496b3
3 files changed
+81
-6
No files matched your search
@@ -17,15 +17,20 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||
import org.bukkit.event.vehicle.VehicleEnterEvent;
|
||||
import org.bukkit.event.vehicle.VehicleExitEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
/** Captures immutable generic native action context without changing event cancellation or gameplay. */
|
||||
public final class EventCaptureListener implements Listener {
|
||||
@@ -53,7 +58,10 @@ public final class EventCaptureListener implements Listener {
|
||||
var details = new LinkedHashMap<String, Object>();
|
||||
details.put("entry_point", "PlayerInteractEvent");
|
||||
details.put("native_action", event.getAction().name());
|
||||
details.put("hand", event.getHand().name());
|
||||
details.put("initially_cancelled", event.isCancelled());
|
||||
details.putAll(item(event.getItem()));
|
||||
downing(event.getPlayer(), details, event.isCancelled());
|
||||
if (event.getClickedBlock() != null) {details.put("target_type", event.getClickedBlock().getType().name());var target=event.getClickedBlock().getLocation();if(target!=null&&target.getWorld()!=null)details.put("target_location",locationMap(target));}
|
||||
var value = new Captured(UUID.randomUUID(), snapshot, kind, Map.copyOf(details));
|
||||
captured.put(event, value);
|
||||
@@ -63,17 +71,35 @@ public final class EventCaptureListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
|
||||
public void resolve(PlayerInteractEvent event) { resolveCaptured(event, event); }
|
||||
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerInteractEntityEvent event){if(event.getHand()!=EquipmentSlot.HAND)return;capture(event,event.getPlayer(),"interact_entity",entity(event.getRightClicked(),"PlayerInteractEntityEvent"),event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerInteractEntityEvent event){if(event.getHand()!=EquipmentSlot.HAND)return;var details=new LinkedHashMap<>(entity(event.getRightClicked(),"PlayerInteractEntityEvent"));details.put("hand",event.getHand().name());capture(event,event.getPlayer(),"interact_entity",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(PlayerInteractEntityEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(InventoryClickEvent event){if(event.getWhoClicked() instanceof Player player)capture(event,player,"inventory_click",Map.of("entry_point","InventoryClickEvent","slot",event.getRawSlot(),"click",event.getClick().name(),"inventory_action",event.getAction().name()),event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(InventoryClickEvent event){if(event.getWhoClicked() instanceof Player player){var details=new LinkedHashMap<String,Object>();details.put("entry_point",event.getClass().getSimpleName());details.put("slot",event.getRawSlot());if(event.getView()!=null)details.put("container",event.getView().getType().name());details.put("click",event.getClick().name());details.put("inventory_action",event.getAction().name());details.putAll(item(event.getCurrentItem()));capture(event,player,"inventory_click",details,event);}}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(InventoryClickEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerDropItemEvent event){capture(event,event.getPlayer(),"drop_item",Map.of("entry_point","PlayerDropItemEvent","item_type",event.getItemDrop().getItemStack().getType().name()),event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(InventoryDragEvent event){if(event.getWhoClicked() instanceof Player player){var details=new LinkedHashMap<String,Object>();details.put("entry_point","InventoryDragEvent");if(event.getView()!=null)details.put("container",event.getView().getType().name());details.put("slots",event.getNewItems().keySet().stream().sorted().toList());details.putAll(item(event.getOldCursor()));capture(event,player,"inventory_drag",details,event);}}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(InventoryDragEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerDropItemEvent event){var details=new LinkedHashMap<String,Object>();details.put("entry_point","PlayerDropItemEvent");details.putAll(item(event.getItemDrop().getItemStack()));capture(event,event.getPlayer(),"drop_item",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(PlayerDropItemEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(EntityPickupItemEvent event){if(event.getEntity() instanceof Player player)capture(event,player,"pickup_item",Map.of("entry_point","EntityPickupItemEvent","item_type",event.getItem().getItemStack().getType().name(),"remaining",event.getRemaining()),event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(EntityPickupItemEvent event){if(event.getEntity() instanceof Player player){var details=new LinkedHashMap<String,Object>();details.put("entry_point","EntityPickupItemEvent");details.put("remaining",event.getRemaining());details.putAll(item(event.getItem().getItemStack()));capture(event,player,"pickup_item",details,event);}}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(EntityPickupItemEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerItemConsumeEvent event){var details=new LinkedHashMap<String,Object>();details.put("entry_point","PlayerItemConsumeEvent");details.putAll(item(event.getItem()));capture(event,event.getPlayer(),"consume_item",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(PlayerItemConsumeEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event){capture(event,event.getPlayer(),"recipe_autofill",Map.of("entry_point","PlayerRecipeBookClickEvent","recipe",event.getRecipe().asString()),event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(org.bukkit.event.player.PlayerArmorStandManipulateEvent event){var details=new LinkedHashMap<String,Object>();details.put("entry_point","PlayerArmorStandManipulateEvent");details.put("target_id",event.getRightClicked().getUniqueId().toString());details.putAll(item(event.getPlayerItem()));capture(event,event.getPlayer(),"armor_stand",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(org.bukkit.event.player.PlayerArmorStandManipulateEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(org.bukkit.event.block.BlockPlaceEvent event){var details=new LinkedHashMap<String,Object>();details.put("entry_point","BlockPlaceEvent");details.putAll(item(event.getItemInHand()));capture(event,event.getPlayer(),"place_item",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(org.bukkit.event.block.BlockPlaceEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event){var details=new LinkedHashMap<String,Object>();details.put("entry_point","PlayerLaunchProjectileEvent");details.putAll(item(event.getItemStack()));capture(event,event.getPlayer(),"launch_projectile",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(org.bukkit.event.entity.EntityShootBowEvent event){if(event.getEntity() instanceof Player player){var details=new LinkedHashMap<String,Object>();details.put("entry_point","EntityShootBowEvent");details.putAll(item(event.getBow()));capture(event,player,"shoot_bow",details,event);}}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(org.bukkit.event.entity.EntityShootBowEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(org.bukkit.event.block.BlockDispenseArmorEvent event){if(event.getTargetEntity() instanceof Player player){var details=new LinkedHashMap<String,Object>();details.put("entry_point","BlockDispenseArmorEvent");details.putAll(item(event.getItem()));capture(event,player,"dispense_armor",details,event);}}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(org.bukkit.event.block.BlockDispenseArmorEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(io.papermc.paper.event.player.PrePlayerAttackEntityEvent event){var details=new LinkedHashMap<String,Object>();details.put("entry_point","PrePlayerAttackEntityEvent");details.put("target_id",event.getAttacked().getUniqueId().toString());details.put("will_attack",event.willAttack());details.putAll(item(event.getPlayer().getInventory().getItemInMainHand()));capture(event,event.getPlayer(),"attack_entity",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(io.papermc.paper.event.player.PrePlayerAttackEntityEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerItemHeldEvent event){capture(event,event.getPlayer(),"held_slot",Map.of("entry_point","PlayerItemHeldEvent","previous_slot",event.getPreviousSlot(),"new_slot",event.getNewSlot()),event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(PlayerItemHeldEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerSwapHandItemsEvent event){capture(event,event.getPlayer(),"swap_hands",Map.of("entry_point","PlayerSwapHandItemsEvent"),event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerSwapHandItemsEvent event){var details=new LinkedHashMap<String,Object>();details.put("entry_point","PlayerSwapHandItemsEvent");details.putAll(item(event.getOffHandItem()));capture(event,event.getPlayer(),"swap_hands",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(PlayerSwapHandItemsEvent event){resolveCaptured(event,event);}
|
||||
@EventHandler(priority=EventPriority.LOWEST,ignoreCancelled=false) public void observe(PlayerTeleportEvent event){var details=new LinkedHashMap<String,Object>();details.put("entry_point","PlayerTeleportEvent");details.put("cause",event.getCause().name());details.put("from_location",locationMap(event.getFrom()));if(event.getTo()!=null)details.put("to_location",locationMap(event.getTo()));capture(event,event.getPlayer(),"teleport",details,event);}
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(PlayerTeleportEvent event){resolveCaptured(event,event);}
|
||||
@@ -83,14 +109,39 @@ public final class EventCaptureListener implements Listener {
|
||||
@EventHandler(priority=EventPriority.MONITOR,ignoreCancelled=false) public void resolve(VehicleExitEvent event){resolveCaptured(event,event);}
|
||||
|
||||
private Map<String,Object> entity(Entity entity,String entry){var details=new LinkedHashMap<String,Object>();details.put("entry_point",entry);details.put("target_id",entity.getUniqueId().toString());details.put("target_type",entity.getType().name());var target=entity.getLocation();if(target!=null&&target.getWorld()!=null)details.put("target_location",locationMap(target));return details;}
|
||||
private void capture(Object event,Player player,String kind,Map<String,Object> details,Cancellable cancellation){var snapshot=context(player).orElse(null);if(snapshot==null)return;var copied=new LinkedHashMap<>(details);copied.put("initially_cancelled",cancellation.isCancelled());var value=new Captured(UUID.randomUUID(),snapshot,kind,Map.copyOf(copied));captured.put(event,value);emit("action.observed",value,"observed",cancellation.isCancelled());}
|
||||
private void capture(Object event,Player player,String kind,Map<String,Object> details,Cancellable cancellation){var snapshot=context(player).orElse(null);if(snapshot==null)return;var copied=new LinkedHashMap<>(details);copied.put("initially_cancelled",cancellation.isCancelled());downing(player,copied,cancellation.isCancelled());var value=new Captured(UUID.randomUUID(),snapshot,kind,Map.copyOf(copied));captured.put(event,value);emit("action.observed",value,"observed",cancellation.isCancelled());}
|
||||
private void resolveCaptured(Object event,Cancellable cancellation){var value=captured.remove(event);if(value!=null)emit("action.resolved",value,cancellation.isCancelled()?"cancelled":"accepted",cancellation.isCancelled());}
|
||||
|
||||
private void downing(Player player,Map<String,Object> details,boolean initiallyCancelled){
|
||||
var found=sessions.downed(player.getUniqueId());
|
||||
if(found!=null&&found.isPresent()){details.put("downing_id",found.orElseThrow().id().toString());details.put("guard_reason","downed");return;}
|
||||
var kind=details.get("item_kind");
|
||||
if(kind!=null&&!kind.equals("ordinary")&&!kind.equals("empty")){details.put("guard_reason","protected_item");return;}
|
||||
details.put("guard_reason",initiallyCancelled?"prior_cancellation":"none");
|
||||
}
|
||||
|
||||
private static Map<String,Object> item(ItemStack item){
|
||||
var details=new LinkedHashMap<String,Object>();
|
||||
if(item==null||item.getType().isAir()){details.put("item_kind","empty");return details;}
|
||||
details.put("item_type",item.getType().name());
|
||||
if(!item.hasItemMeta()){details.put("item_kind","ordinary");return details;}
|
||||
var data=item.getItemMeta().getPersistentDataContainer();var keys=data.getKeys().stream().filter(key->key.getNamespace().equals("fantasystick")).map(NamespacedKey::getKey).collect(java.util.stream.Collectors.toSet());
|
||||
String kind=keys.contains("sheet_version")?"character_sheet":keys.contains("storage_version")?"storage_box":keys.contains("fishing_quest")?"quest_fishing_rod":keys.contains("control_version")?"control":keys.contains("character_gear")?"character_gear":keys.contains("tail_version")?"tail":"ordinary";
|
||||
details.put("item_kind",kind);
|
||||
copy(data,details,"control_kind","control_kind");copy(data,details,"control_owner_id","item_owner_id");copy(data,details,"control_session_id","item_session_id");copy(data,details,"storage_owner_id","item_owner_id");copy(data,details,"storage_session_id","item_session_id");copy(data,details,"character_gear_owner","item_owner_id");copy(data,details,"character_gear_session","item_session_id");copy(data,details,"character_gear_slot","gear_slot");copy(data,details,"character_gear_tier","gear_tier");copy(data,details,"character_id","item_character_id");copy(data,details,"sheet_generation","sheet_generation");copy(data,details,"death_id","death_id");copy(data,details,"fishing_quest","quest_id");copy(data,details,"fishing_site","site_id");
|
||||
return details;
|
||||
}
|
||||
private static void copy(org.bukkit.persistence.PersistentDataContainer data,Map<String,Object> details,String key,String output){var value=data.get(new NamespacedKey("fantasystick",key),PersistentDataType.STRING);if(value!=null&&value.length()<=128)details.put(output,value);}
|
||||
|
||||
private void emit(String type, Captured capturedAction, String outcome, boolean cancelled) {
|
||||
var data = new LinkedHashMap<>(capturedAction.details());
|
||||
data.put("action_kind", capturedAction.kind());
|
||||
data.put("outcome", outcome);
|
||||
data.put("cancelled", cancelled);
|
||||
if (type.equals("action.resolved")) {
|
||||
if (!cancelled) data.put("guard_reason", "accepted");
|
||||
else if (Objects.equals(data.get("guard_reason"), "none")) data.put("guard_reason", "native_cancellation");
|
||||
}
|
||||
events.emit(new EventInput(UUID.randomUUID(), capturedAction.action(), clock.instant(), type,
|
||||
capturedAction.context(), data));
|
||||
}
|
||||
|
||||
@@ -46,6 +46,21 @@ final class EventCaptureNativeTest {
|
||||
assertTrue(joined.contains("\"from_location\""));assertTrue(joined.contains("\"to_location\""));assertTrue(java.util.Arrays.stream(EventCaptureListener.class.getDeclaredMethods()).noneMatch(method->java.util.Arrays.asList(method.getParameterTypes()).contains(org.bukkit.event.player.PlayerMoveEvent.class)));
|
||||
}
|
||||
|
||||
@Test void protectedDragAndConsumeCaptureExactItemDowningAndFinalCancellationContext() throws Exception {
|
||||
var clock=Clock.fixed(Instant.parse("2026-09-25T01:20:00Z"),ZoneOffset.UTC);var sessions=mock(EquipmentSessions.class);var player=mock(Player.class);var world=mock(World.class);var playerId=UUID.randomUUID();var active=new EquipmentSessions.Active(playerId,UUID.randomUUID(),UUID.randomUUID());var character=mock(CharacterRecord.class);var episode=mock(games.dmg.fantasystick.session.DownedEpisode.class);var episodeId=UUID.randomUUID();when(player.getUniqueId()).thenReturn(playerId);when(player.getName()).thenReturn("Guarded");when(world.getUID()).thenReturn(UUID.randomUUID());when(world.getName()).thenReturn("world");when(player.getLocation()).thenReturn(new Location(world,2,70,3));when(sessions.active(playerId)).thenReturn(Optional.of(active));when(sessions.currentRecord(active)).thenReturn(Optional.of(character));when(character.name()).thenReturn("Frozen Hero");when(sessions.downed(playerId)).thenReturn(Optional.of(episode));when(episode.id()).thenReturn(episodeId);
|
||||
var control=new org.bukkit.inventory.ItemStack(org.bukkit.Material.STICK);var meta=control.getItemMeta();meta.getPersistentDataContainer().set(new org.bukkit.NamespacedKey("fantasystick","control_version"),org.bukkit.persistence.PersistentDataType.INTEGER,1);meta.getPersistentDataContainer().set(new org.bukkit.NamespacedKey("fantasystick","control_kind"),org.bukkit.persistence.PersistentDataType.STRING,"basic_attack");meta.getPersistentDataContainer().set(new org.bukkit.NamespacedKey("fantasystick","control_owner_id"),org.bukkit.persistence.PersistentDataType.STRING,playerId.toString());meta.getPersistentDataContainer().set(new org.bukkit.NamespacedKey("fantasystick","control_session_id"),org.bukkit.persistence.PersistentDataType.STRING,active.session().toString());control.setItemMeta(meta);
|
||||
try(var log=LocalEventLog.open(data,clock,new LocalEventLog.RuntimeInfo("Season 4","26.2","test"),16,134_217_728L,message->fail(message))){log.ready().toCompletableFuture().get();var listener=new EventCaptureListener(log,sessions,clock);
|
||||
var drag=mock(org.bukkit.event.inventory.InventoryDragEvent.class);when(drag.getWhoClicked()).thenReturn(player);when(drag.getOldCursor()).thenReturn(control);when(drag.getNewItems()).thenReturn(java.util.Map.of(4,control));listener.observe(drag);when(drag.isCancelled()).thenReturn(true);listener.resolve(drag);
|
||||
var consume=mock(org.bukkit.event.player.PlayerItemConsumeEvent.class);when(consume.getPlayer()).thenReturn(player);when(consume.getItem()).thenReturn(control);listener.observe(consume);when(consume.isCancelled()).thenReturn(true);listener.resolve(consume);
|
||||
var craft=mock(org.bukkit.event.inventory.CraftItemEvent.class);when(craft.getWhoClicked()).thenReturn(player);when(craft.getRawSlot()).thenReturn(0);when(craft.getClick()).thenReturn(org.bukkit.event.inventory.ClickType.LEFT);when(craft.getAction()).thenReturn(org.bukkit.event.inventory.InventoryAction.PICKUP_ALL);when(craft.getCurrentItem()).thenReturn(control);listener.observe(craft);when(craft.isCancelled()).thenReturn(true);listener.resolve(craft);
|
||||
var armor=mock(org.bukkit.event.block.BlockDispenseArmorEvent.class);when(armor.getTargetEntity()).thenReturn(player);when(armor.getItem()).thenReturn(control);listener.observe(armor);when(armor.isCancelled()).thenReturn(true);listener.resolve(armor);
|
||||
var rod=control.clone();rod.setType(org.bukkit.Material.FISHING_ROD);var rodMeta=rod.getItemMeta();rodMeta.getPersistentDataContainer().set(games.dmg.fantasystick.adventure.AdventureQuestNavigation.FISHING_QUEST,org.bukkit.persistence.PersistentDataType.STRING,UUID.randomUUID().toString());rod.setItemMeta(rodMeta);var launch=mock(com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent.class);when(launch.getPlayer()).thenReturn(player);when(launch.getItemStack()).thenReturn(rod);listener.observe(launch);when(launch.isCancelled()).thenReturn(true);listener.resolve(launch);
|
||||
var duplicate=mock(PlayerInteractEvent.class);when(duplicate.getPlayer()).thenReturn(player);when(duplicate.getHand()).thenReturn(EquipmentSlot.OFF_HAND);listener.observe(duplicate);listener.resolve(duplicate);
|
||||
}
|
||||
var records=new java.util.ArrayList<com.google.gson.JsonObject>();try(var files=Files.walk(data.resolve("events"))){for(var file:files.filter(path->path.getFileName().toString().endsWith(".jsonl")).toList())for(var line:Files.readAllLines(file))if(!line.isBlank())records.add(com.google.gson.JsonParser.parseString(line).getAsJsonObject());}
|
||||
var guarded=records.stream().filter(event->event.get("type").getAsString().contains("action.")).toList();assertEquals(10,guarded.size());for(var event:guarded){var value=event.getAsJsonObject("data");assertEquals(episodeId.toString(),value.get("downing_id").getAsString());assertEquals("downed",value.get("guard_reason").getAsString());}assertEquals(java.util.Set.of("inventory_drag","consume_item","inventory_click","dispense_armor","launch_projectile"),guarded.stream().map(event->event.getAsJsonObject("data").get("action_kind").getAsString()).collect(java.util.stream.Collectors.toSet()));assertTrue(guarded.stream().map(event->event.getAsJsonObject("data")).anyMatch(value->value.get("item_kind").getAsString().equals("quest_fishing_rod")));assertTrue(guarded.stream().map(event->event.getAsJsonObject("data")).filter(value->value.get("item_kind").getAsString().equals("control")).allMatch(value->value.get("control_kind").getAsString().equals("basic_attack")));
|
||||
}
|
||||
|
||||
private static int count(String value,String sought){int count=0;for(int at=0;(at=value.indexOf(sought,at))>=0;at+=sought.length())count++;return count;}
|
||||
|
||||
@Test void activeCharacterNativeInteractionProducesCorrelatedObservedAndCancelledRecords() throws Exception {
|
||||
|
||||
@@ -105,6 +105,10 @@ class FantasyStickLifecycleNativeTest {
|
||||
org.bukkit.event.block.Action.LEFT_CLICK_AIR, actor.core.inventory.getItem(0), null,
|
||||
org.bukkit.block.BlockFace.SELF, org.bukkit.inventory.EquipmentSlot.HAND);
|
||||
f.dispatcher.accept(event);
|
||||
var duplicate = new org.bukkit.event.player.PlayerInteractEvent(actor.player,
|
||||
org.bukkit.event.block.Action.LEFT_CLICK_AIR, actor.core.inventory.getItem(0), null,
|
||||
org.bukkit.block.BlockFace.SELF, org.bukkit.inventory.EquipmentSlot.OFF_HAND);
|
||||
f.dispatcher.accept(duplicate);
|
||||
f.plugin.setEnabled(false);
|
||||
String records;
|
||||
try (var files = java.nio.file.Files.walk(data.resolve("events"))) {
|
||||
@@ -119,6 +123,11 @@ class FantasyStickLifecycleNativeTest {
|
||||
assertTrue(records.contains("games.dmg.minecraft.fantasystick.action.resolved"));
|
||||
assertTrue(records.contains("games.dmg.minecraft.fantasystick.game.stopped"));
|
||||
assertTrue(records.contains("\"characterid\":\"" + actor.core.record.id() + "\""));
|
||||
assertTrue(records.contains("\"item_kind\":\"control\""));
|
||||
assertTrue(records.contains("\"control_kind\":\"book\""));
|
||||
assertTrue(records.contains("\"guard_reason\":\"protected_item\""));
|
||||
assertEquals(1, records.split("games.dmg.minecraft.fantasystick.action.observed", -1).length - 1,
|
||||
"The duplicate offhand callback must not create another logical observation");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user