@Override @Deprecated public Optional<ItemStackSnapshot> getOriginalItemStack() { return Optional.ofNullable(this.getTransaction().getOriginal()); }
/** * Applies the provided {@link Predicate} to the {@link List} of * {@link Transaction}s from {@link #getTransactions()} such that * any time that {@link Predicate#test(Object)} returns <code>false</code> * on a {@link Transaction}, the {@link Transaction} is * marked as "invalid" and will not apply post event. * * <p>{@link Transaction#getFinal()} is used to construct * the {@link ItemStack} to pass to the predicate</p> * * @param predicate The predicate to use for filtering * @return The transactions for which the predicate returned * <code>false</code> */ default List<? extends Transaction<ItemStackSnapshot>> filter(Predicate<ItemStack> predicate) { List<Transaction<ItemStackSnapshot>> invalidatedTransactions = Lists.newArrayList(); this.getTransactions().stream().filter(transaction -> !predicate.test(transaction.getFinal().createStack())).forEach(transaction -> { transaction.setValid(false); invalidatedTransactions.add(transaction); }); return invalidatedTransactions; }
@Test public void testChangeBlockEvent_filter() { Transaction<BlockSnapshot> transaction = new Transaction<>(mockParam(BlockSnapshot.class), mockParam(BlockSnapshot.class)); when(transaction.getOriginal().getLocation()).thenReturn(Optional.of(new Location<>(mockParam(World.class), Vector3d.ZERO))); ChangeBlockEvent.Break event = SpongeEventFactory.createChangeBlockEventBreak( Cause.of(EventContext.empty(), "none"), Lists.newArrayList(transaction)); event.filter(location -> false); assertThat(transaction.isValid(), is(false)); }
/** * Applies the provided {@link Predicate} to the {@link List} of * {@link Transaction}s from {@link #getTransactions()} such that * any time that {@link Predicate#test(Object)} returns <code>false</code> * on the location of the {@link Transaction}, the {@link Transaction} is * marked as "invalid" and will not apply post event. * * <p>{@link Transaction#getOriginal()} is used to get the {@link Location}</p> * * @param predicate The predicate to use for filtering * @return The transactions for which the predicate returned * <code>false</code> */ default List<Transaction<BlockSnapshot>> filter(Predicate<Location<World>> predicate) { List<Transaction<BlockSnapshot>> invalidatedTransactions = Lists.newArrayList(); for (Transaction<BlockSnapshot> transaction: this.getTransactions()) { if (!predicate.test(transaction.getOriginal().getLocation().get())) { transaction.setValid(false); invalidatedTransactions.add(transaction); } } return invalidatedTransactions; }
/** * Helper method for formatting item container data. * * @param transaction */ private void writeItemTransaction(Transaction<ItemStackSnapshot> transaction) { checkNotNull(transaction); String itemId = transaction.getFinal().getType().getId(); int itemQuantity = transaction.getFinal().getQuantity(); if (transaction.getOriginal().getType() != ItemTypes.NONE) { itemQuantity -= transaction.getOriginal().getQuantity(); } data.set(DataQueries.Target, itemId); data.set(DataQueries.Quantity, itemQuantity); }
if (!transaction.isValid()) { continue; BlockType original = transaction.getOriginal().getState().getType(); BlockType finalBlock = transaction.getFinal().getState().getType();
@Listener public void placeBlock(ChangeBlockEvent.Place e, @Root Player player) { if (isOnPipe(player.getUniqueId())) { Location loc = e.getTransactions().get(0).getFinal().getLocation().get(); getUserConnection(player.getUniqueId()) .get(EntityTracker.class) .addBlockInteraction(new Position((long) loc.getX(), (long) loc.getY(), (long) loc.getZ())); } } }
@Override public ActionableResult rollback() throws Exception { DataView entityData = formatEntityData(); Optional<EntitySnapshot> snapshot = Sponge.getRegistry().createBuilder(Builder.class).build(entityData); if (!snapshot.isPresent()) { return ActionableResult.skipped(SkipReason.INVALID); } Optional<Entity> entity = snapshot.get().restore(); if (!entity.isPresent()) { return ActionableResult.skipped(SkipReason.INVALID); } // Don't let it burn to death (again?) entity.get().get(IgniteableData.class).ifPresent(data -> entity.get().offer(data.fireTicks().set(0))); // Heal, it was probably killed. entity.get().get(HealthData.class).ifPresent(data -> entity.get().offer(data.health().set(data.maxHealth().get()))); return ActionableResult.success(new Transaction<>(new SerializableNonExistent(), entity.get())); }
/** * Invalidates the list as such that all {@link Transaction}s are * marked as "invalid" and will not apply post event. */ default void filterAll() { for (Transaction<BlockSnapshot> transaction: this.getTransactions()) { transaction.setValid(false); } }
@Override public DataContainer toContainer() { final DataContainer container = DataContainer.createNew() .set(Queries.CONTENT_VERSION, getContentVersion()) .set(Queries.TYPE_CLASS, this.original.getClass().getName()) .set(Queries.ORIGINAL, this.original) .set(Queries.DEFAULT_REPLACEMENT, this.defaultReplacement) .set(Queries.VALID, this.valid); if (this.custom != null) { container.set(Queries.CUSTOM_REPLACEMENT, this.custom); } return container; } }
/** * Helper method for writing block transaction data, using only * the final replacement value. We must alter the data structure * slightly to avoid duplication, decoupling location from blocks, etc. * * @param transaction BlockTransaction representing a block change in the world. */ private void writeBlockTransaction(Transaction<BlockSnapshot> transaction) { checkNotNull(transaction); // Location DataContainer location = transaction.getOriginal().getLocation().get().toContainer(); location.remove(DataQueries.BlockType); location.remove(DataQueries.WorldName); location.remove(DataQueries.ContentVersion); data.set(DataQueries.Location, location); // Storing the state only, so we don't also get location data.set(DataQueries.OriginalBlock, formatBlockDataContainer(transaction.getOriginal())); data.set(DataQueries.ReplacementBlock, formatBlockDataContainer(transaction.getFinal())); // Use the transaction data directly, so we never worry about different data formats if (this.eventName.equals("place")) { data.set(DataQueries.Target, transaction.getFinal().getState().getType().getId().replace("_", " ")); } else { data.set(DataQueries.Target, transaction.getOriginal().getState().getType().getId().replace("_", " ")); } }
/** * Applies the provided {@link Predicate} to the {@link List} of * {@link Transaction}s from {@link #getTransactions()} such that * any time that {@link Predicate#test(Object)} returns <code>false</code> * on the location of the {@link Transaction}, the {@link Transaction} is * marked as "invalid" and will not apply post event. * * <p>{@link Transaction#getOriginal()} is used to get the {@link Location}</p> * * @param predicate The predicate to use for filtering * @return The transactions for which the predicate returned <code>false</code> */ default List<Transaction<BlockSnapshot>> filter(Predicate<Location<World>> predicate) { List<Transaction<BlockSnapshot>> invalidatedTransactions = Lists.newArrayList(); for (Transaction<BlockSnapshot> transaction: this.getTransactions()) { if (!predicate.test(transaction.getOriginal().getLocation().get())) { transaction.setValid(false); invalidatedTransactions.add(transaction); } } return invalidatedTransactions; }
@Listener public void onInventoryClick(ClickInventoryEvent e, @Root Player player) { for (SlotTransaction transaction : e.getTransactions()) { if (ArmorType.isArmor(transaction.getFinal().getType().getId()) || ArmorType.isArmor(e.getCursorTransaction().getFinal().getType().getId())) { sendDelayedArmorUpdate(player); break; } } }
return ActionableResult.success(new Transaction<>(original, resultingBlock));
/** * Invalidates the list as such that all {@link Transaction}s are * marked as "invalid" and will not apply post event. */ default void filterAll() { for (Transaction<BlockSnapshot> transaction: this.getTransactions()) { transaction.setValid(false); } }
@Override public DataContainer toContainer() { final DataContainer container = new MemoryDataContainer() .set(Queries.CONTENT_VERSION, getContentVersion()) .set(Queries.TYPE_CLASS, this.original.getClass().getName()) .set(Queries.ORIGINAL, this.original) .set(Queries.DEFAULT_REPLACEMENT, this.defaultReplacement) .set(Queries.VALID, this.valid); if (this.custom != null) { container.set(Queries.CUSTOM_REPLACEMENT, this.custom); } return container; } }
@Listener public void onBlockChange(ChangeBlockEvent.Post event) { event.getTransactions().forEach(blockSnapshotTransaction -> { Location<World> baseLocation = blockSnapshotTransaction.getFinal().getLocation().get(); BlockState originalState = blockSnapshotTransaction.getOriginal().getExtendedState(); List<Location<World>> icCheckSpots = new ArrayList<>(); boolean wasPowered = false; icCheckSpots.addAll(blockSnapshotTransaction.getFinal().get(Keys.WIRE_ATTACHMENTS).map(Map::keySet).orElse(EnumSet.noneOf(Direction.class)) .stream().map(baseLocation::getRelative) .collect(Collectors.toList()));
@Listener public void onBlockBreak(ChangeBlockEvent.Break event) { event.getTransactions().stream().map(transaction -> transaction.getOriginal().getLocation().get()).forEach(location -> { if (loadedICs.containsKey(location)) { IC ic = loadedICs.remove(location); ic.unload(); if (ic instanceof SelfTriggeringIC) { ((SpongeSelfTriggerManager) CraftBookPlugin.inst().getSelfTriggerManager().get()).unregister(this, location); } } }); }
/** * Applies the provided {@link Predicate} to the {@link List} of * {@link Transaction}s from {@link #getTransactions()} such that * any time that {@link Predicate#test(Object)} returns <code>false</code> * on a {@link Transaction}, the {@link Transaction} is * marked as "invalid" and will not apply post event. * * <p>{@link Transaction#getFinal()} is used to construct * the {@link ItemStack} to pass to the predicate</p> * * @param predicate The predicate to use for filtering * @return The transactions for which the predicate returned <code>false</code> */ default List<? extends Transaction<ItemStackSnapshot>> filter(Predicate<ItemStack> predicate) { List<Transaction<ItemStackSnapshot>> invalidatedTransactions = Lists.newArrayList(); this.getTransactions().stream().filter(transaction -> !predicate.test(transaction.getFinal().createStack())).forEach(transaction -> { transaction.setValid(false); invalidatedTransactions.add(transaction); }); return invalidatedTransactions; }
@Listener public void onInventoryClick(ClickInventoryEvent e, @Root Player player) { for (SlotTransaction transaction : e.getTransactions()) { if (ArmorType.isArmor(transaction.getFinal().getType().getId()) || ArmorType.isArmor(e.getCursorTransaction().getFinal().getType().getId())) { sendDelayedArmorUpdate(player); break; } } }