use of org.spongepowered.common.interfaces.IMixinContainer in project SpongeCommon by SpongePowered.
the class MixinSlotCrafting method afterTake.
/**
* Create CraftItemEvent.Post result is also handled by
* {@link MixinContainer#redirectTransferStackInSlot} or
* {@link MixinContainer#redirectOnTakeThrow}
*/
@Inject(method = "onTake", cancellable = true, at = @At("RETURN"))
private void afterTake(EntityPlayer thePlayer, ItemStack stack, CallbackInfoReturnable<ItemStack> cir) {
if (((IMixinWorld) thePlayer.world).isFake()) {
return;
}
((IMixinContainer) thePlayer.openContainer).detectAndSendChanges(true);
((IMixinContainer) thePlayer.openContainer).setCaptureInventory(false);
Container container = thePlayer.openContainer;
Inventory craftInv = ((Inventory) container).query(QueryOperationTypes.INVENTORY_TYPE.of(CraftingInventory.class));
if (!(craftInv instanceof CraftingInventory)) {
SpongeImpl.getLogger().warn("Detected crafting without a InventoryCrafting!? Crafting Event will not fire.");
return;
}
// retain only last slot-transactions on output slot
SlotTransaction first = null;
List<SlotTransaction> capturedTransactions = ((IMixinContainer) container).getCapturedTransactions();
for (Iterator<SlotTransaction> iterator = capturedTransactions.iterator(); iterator.hasNext(); ) {
SlotTransaction trans = iterator.next();
Optional<SlotIndex> slotIndex = trans.getSlot().getInventoryProperty(SlotIndex.class);
if (slotIndex.isPresent() && slotIndex.get().getValue() == 0) {
iterator.remove();
if (first == null) {
first = trans;
}
}
}
ItemStackSnapshot craftedItem;
// if we got a transaction on the crafting-slot use this
if (first != null) {
capturedTransactions.add(first);
craftedItem = first.getOriginal().copy();
} else {
if (stack.isEmpty()) {
// if stack is empty this was probably shift-crafting so we use the captured itemstack instead
craftedItem = ItemStackUtil.snapshotOf(this.craftedStack);
} else {
craftedItem = ItemStackUtil.snapshotOf(stack);
}
}
CraftingInventory craftingInventory = (CraftingInventory) craftInv;
CraftItemEvent.Craft event = SpongeCommonEventFactory.callCraftEventPost(thePlayer, craftingInventory, craftedItem, this.lastRecipe, container, capturedTransactions);
((IMixinContainer) container).setLastCraft(event);
((IMixinContainer) container).setFirePreview(true);
this.craftedStack = null;
SlotTransaction last = new SlotTransaction(craftingInventory.getResult(), ItemStackSnapshot.NONE, ItemStackUtil.snapshotOf(this.getStack()));
List<SlotTransaction> previewTransactions = ((IMixinContainer) container).getPreviewTransactions();
CraftingRecipe newRecipe = Sponge.getRegistry().getCraftingRecipeRegistry().findMatchingRecipe(craftingInventory.getCraftingGrid(), ((World) player.world)).orElse(null);
SpongeCommonEventFactory.callCraftEventPre(thePlayer, craftingInventory, last, newRecipe, container, previewTransactions);
previewTransactions.clear();
}
use of org.spongepowered.common.interfaces.IMixinContainer in project SpongeCommon by SpongePowered.
the class EnchantItemPacketState method unwind.
@Override
public void unwind(InventoryPacketContext context) {
// TODO - Pre changes of merging PacketFunction into the phase states, enchantments did NOT have any processing....
final EntityPlayerMP player = context.getPacketPlayer();
// The server will disable the player's crafting after receiving a
// client packet
// that did not pass validation (server click item != packet click item)
// The server then sends a SPacketConfirmTransaction and waits for a
// CPacketConfirmTransaction to re-enable crafting confirming that the
// client
// acknowledged the denied transaction.
// To detect when this happens, we turn off capturing so we can avoid
// firing
// invalid events.
// See MixinNetHandlerPlayServer processClickWindow redirect for rest of
// fix.
// --bloodmc
final IMixinContainer mixinContainer = ContainerUtil.toMixin(player.openContainer);
if (!mixinContainer.capturingInventory()) {
mixinContainer.getCapturedTransactions().clear();
return;
}
// TODO clear this shit out of the context
final CPacketEnchantItem packetIn = context.getPacket();
final ItemStackSnapshot lastCursor = context.getCursor();
final ItemStackSnapshot newCursor = ItemStackUtil.snapshotOf(player.inventory.getItemStack());
final Transaction<ItemStackSnapshot> transaction = new Transaction<>(lastCursor, newCursor);
final net.minecraft.inventory.Container openContainer = player.openContainer;
final List<SlotTransaction> slotTransactions = mixinContainer.getCapturedTransactions();
final int usedButton = packetIn.getButton();
final List<Entity> capturedItems = new ArrayList<>();
for (EntityItem entityItem : context.getCapturedItems()) {
capturedItems.add(EntityUtil.fromNative(entityItem));
}
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(player);
Sponge.getCauseStackManager().pushCause(openContainer);
final ClickInventoryEvent inventoryEvent;
inventoryEvent = this.createInventoryEvent(player, ContainerUtil.fromNative(openContainer), transaction, Lists.newArrayList(slotTransactions), capturedItems, usedButton);
// If this happens and we captured no entities, avoid firing events
if (mixinContainer.getCapturedTransactions().isEmpty() && capturedItems.isEmpty()) {
mixinContainer.setCaptureInventory(false);
return;
}
if (inventoryEvent != null) {
// Don't fire inventory drop events when there are no entities
if (inventoryEvent instanceof AffectEntityEvent && ((AffectEntityEvent) inventoryEvent).getEntities().isEmpty()) {
slotTransactions.clear();
mixinContainer.setCaptureInventory(false);
return;
}
// packet has everything we want.
if (!(inventoryEvent instanceof ClickInventoryEvent.Drag)) {
PacketPhaseUtil.validateCapturedTransactions(packetIn.getWindowId(), openContainer, inventoryEvent.getTransactions());
}
SpongeImpl.postEvent(inventoryEvent);
if (inventoryEvent.isCancelled() || PacketPhaseUtil.allTransactionsInvalid(inventoryEvent.getTransactions())) {
if (inventoryEvent instanceof ClickInventoryEvent.Drop) {
capturedItems.clear();
}
// Restore cursor
PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getOriginal());
// Restore target slots
PacketPhaseUtil.handleSlotRestore(player, openContainer, inventoryEvent.getTransactions(), true);
} else {
PacketPhaseUtil.handleSlotRestore(player, openContainer, inventoryEvent.getTransactions(), false);
// Handle cursor
if (!inventoryEvent.getCursorTransaction().isValid()) {
PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getOriginal());
} else if (inventoryEvent.getCursorTransaction().getCustom().isPresent()) {
PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getFinal());
} else if (inventoryEvent instanceof ClickInventoryEvent.Drag) {
int increment;
increment = slotTransactions.stream().filter((t) -> !t.isValid()).mapToInt((t) -> t.getFinal().getQuantity()).sum();
final ItemStack cursor = inventoryEvent.getCursorTransaction().getFinal().createStack();
cursor.setQuantity(cursor.getQuantity() + increment);
PacketPhaseUtil.handleCustomCursor(player, cursor.createSnapshot());
} else if (inventoryEvent instanceof ClickInventoryEvent.Double && !(inventoryEvent instanceof ClickInventoryEvent.Shift)) {
int decrement;
decrement = slotTransactions.stream().filter((t) -> !t.isValid()).mapToInt((t) -> t.getOriginal().getQuantity()).sum();
final ItemStack cursor = inventoryEvent.getCursorTransaction().getFinal().createStack();
cursor.setQuantity(cursor.getQuantity() - decrement);
PacketPhaseUtil.handleCustomCursor(player, cursor.createSnapshot());
}
if (inventoryEvent instanceof SpawnEntityEvent) {
processSpawnedEntities(player, (SpawnEntityEvent) inventoryEvent);
} else if (!context.getCapturedEntitySupplier().isEmpty()) {
SpawnEntityEvent spawnEntityEvent = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), context.getCapturedEntities());
SpongeImpl.postEvent(spawnEntityEvent);
if (!spawnEntityEvent.isCancelled()) {
processSpawnedEntities(player, spawnEntityEvent);
}
}
}
}
}
slotTransactions.clear();
mixinContainer.setCaptureInventory(false);
}
use of org.spongepowered.common.interfaces.IMixinContainer in project SpongeCommon by SpongePowered.
the class InteractionPacketState method unwind.
@Override
public void unwind(BasicPacketContext phaseContext) {
final EntityPlayerMP player = phaseContext.getPacketPlayer();
final ItemStack usedStack = phaseContext.getItemUsed();
final ItemStackSnapshot usedSnapshot = ItemStackUtil.snapshotOf(usedStack);
final Entity spongePlayer = EntityUtil.fromNative(player);
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(spongePlayer);
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.DROPPED_ITEM);
final boolean hasBlocks = !phaseContext.getCapturedBlockSupplier().isEmpty();
final List<BlockSnapshot> capturedBlcoks = phaseContext.getCapturedBlocks();
@Nullable final BlockSnapshot firstBlockChange = hasBlocks ? capturedBlcoks.get(0) : null;
if (hasBlocks) {
if (!TrackingUtil.processBlockCaptures(capturedBlcoks, this, phaseContext)) {
// Stop entities like XP from being spawned
return;
}
} else {
phaseContext.getBlockItemDropSupplier().acceptIfNotEmpty(map -> {
if (ShouldFire.DROP_ITEM_EVENT_DESTRUCT) {
for (BlockSnapshot blockChange : capturedBlcoks) {
final Location<World> location = blockChange.getLocation().get();
final Vector3d position = location.getPosition();
final BlockPos blockPos = VecHelper.toBlockPos(position);
final Collection<EntityItem> entityItems = map.get(blockPos);
if (!entityItems.isEmpty()) {
final List<Entity> items = entityItems.stream().map(EntityUtil::fromNative).collect(Collectors.toList());
final DropItemEvent.Destruct event = SpongeEventFactory.createDropItemEventDestruct(Sponge.getCauseStackManager().getCurrentCause(), items);
SpongeImpl.postEvent(event);
if (!event.isCancelled()) {
processSpawnedEntities(player, event);
}
}
}
} else {
for (BlockSnapshot blockChange : capturedBlcoks) {
final Location<World> location = blockChange.getLocation().get();
final Vector3d position = location.getPosition();
final BlockPos blockPos = VecHelper.toBlockPos(position);
final Collection<EntityItem> entityItems = map.get(blockPos);
if (!entityItems.isEmpty()) {
processEntities(player, (Collection<Entity>) (Collection<?>) entityItems);
}
}
}
});
}
phaseContext.getCapturedItemsSupplier().acceptAndClearIfNotEmpty(items -> {
final ArrayList<Entity> entities = new ArrayList<>();
for (EntityItem item : items) {
entities.add(EntityUtil.fromNative(item));
}
final DropItemEvent.Dispense dispense = SpongeEventFactory.createDropItemEventDispense(Sponge.getCauseStackManager().getCurrentCause(), entities);
SpongeImpl.postEvent(dispense);
if (!dispense.isCancelled()) {
processSpawnedEntities(player, dispense);
}
});
phaseContext.getCapturedEntityDropSupplier().acceptIfNotEmpty(map -> {
if (map.isEmpty()) {
return;
}
final PrettyPrinter printer = new PrettyPrinter(80);
printer.add("Processing Interaction").centre().hr();
printer.add("The item stacks captured are: ");
for (Map.Entry<UUID, Collection<ItemDropData>> entry : map.asMap().entrySet()) {
printer.add(" - Entity with UUID: %s", entry.getKey());
for (ItemDropData stack : entry.getValue()) {
printer.add(" - %s", stack);
}
}
printer.trace(System.err);
});
phaseContext.getCapturedEntitySupplier().acceptAndClearIfNotEmpty(entities -> {
final List<Entity> projectiles = new ArrayList<>(entities.size());
final List<Entity> spawnEggs = new ArrayList<>(entities.size());
final List<Entity> xpOrbs = new ArrayList<>(entities.size());
final List<Entity> normalPlacement = new ArrayList<>(entities.size());
final List<Entity> items = new ArrayList<>(entities.size());
for (Entity entity : entities) {
if (entity instanceof Projectile || entity instanceof EntityThrowable) {
projectiles.add(entity);
} else if (usedSnapshot.getType() == ItemTypes.SPAWN_EGG) {
spawnEggs.add(entity);
} else if (entity instanceof EntityItem) {
items.add(entity);
} else if (entity instanceof EntityXPOrb) {
xpOrbs.add(entity);
} else {
normalPlacement.add(entity);
}
}
if (!projectiles.isEmpty()) {
if (ShouldFire.SPAWN_ENTITY_EVENT) {
try (CauseStackManager.StackFrame frame2 = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.PROJECTILE);
Sponge.getCauseStackManager().pushCause(usedSnapshot);
final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), projectiles);
if (!SpongeImpl.postEvent(event)) {
processSpawnedEntities(player, event);
}
}
} else {
processEntities(player, projectiles);
}
}
if (!spawnEggs.isEmpty()) {
if (ShouldFire.SPAWN_ENTITY_EVENT) {
try (CauseStackManager.StackFrame frame2 = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.PROJECTILE);
Sponge.getCauseStackManager().pushCause(usedSnapshot);
final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), spawnEggs);
if (!SpongeImpl.postEvent(event)) {
processSpawnedEntities(player, event);
}
}
} else {
processEntities(player, spawnEggs);
}
}
if (!items.isEmpty()) {
if (ShouldFire.DROP_ITEM_EVENT_DISPENSE) {
final DropItemEvent.Dispense dispense = SpongeEventFactory.createDropItemEventDispense(Sponge.getCauseStackManager().getCurrentCause(), items);
if (!SpongeImpl.postEvent(dispense)) {
processSpawnedEntities(player, dispense);
}
} else {
processEntities(player, items);
}
}
if (!xpOrbs.isEmpty()) {
if (ShouldFire.SPAWN_ENTITY_EVENT) {
try (final CauseStackManager.StackFrame stackFrame = Sponge.getCauseStackManager().pushCauseFrame()) {
if (firstBlockChange != null) {
stackFrame.pushCause(firstBlockChange);
}
stackFrame.addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.EXPERIENCE);
final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), xpOrbs);
if (!SpongeImpl.postEvent(event)) {
processSpawnedEntities(player, event);
}
}
} else {
processEntities(player, xpOrbs);
}
}
if (!normalPlacement.isEmpty()) {
if (ShouldFire.SPAWN_ENTITY_EVENT) {
try (final CauseStackManager.StackFrame stackFrame = Sponge.getCauseStackManager().pushCauseFrame()) {
if (firstBlockChange != null) {
stackFrame.pushCause(firstBlockChange);
}
final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), normalPlacement);
if (!SpongeImpl.postEvent(event)) {
processSpawnedEntities(player, event);
}
}
} else {
processEntities(player, normalPlacement);
}
}
});
final IMixinContainer mixinContainer = ContainerUtil.toMixin(player.openContainer);
mixinContainer.setCaptureInventory(false);
mixinContainer.getCapturedTransactions().clear();
}
}
use of org.spongepowered.common.interfaces.IMixinContainer in project SpongeCommon by SpongePowered.
the class PlaceBlockPacketState method unwind.
@Override
public void unwind(BasicPacketContext context) {
final Packet<?> packet = context.getPacket();
final EntityPlayerMP player = context.getPacketPlayer();
final IMixinWorldServer mixinWorld = (IMixinWorldServer) player.world;
// Note - CPacketPlayerTryUseItem is swapped with
// CPacketPlayerBlockPlacement
final ItemStack itemStack = context.getItemUsed();
final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(itemStack);
context.getCapturedEntitySupplier().acceptAndClearIfNotEmpty(entities -> {
try (@SuppressWarnings("unused") CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(player);
Sponge.getCauseStackManager().pushCause(snapshot);
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.SPAWN_EGG);
final SpawnEntityEvent spawnEntityEvent = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), entities);
SpongeImpl.postEvent(spawnEntityEvent);
if (!spawnEntityEvent.isCancelled()) {
processSpawnedEntities(player, spawnEntityEvent);
}
}
});
context.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(originalBlocks -> {
Sponge.getCauseStackManager().pushCause(player);
boolean success = TrackingUtil.processBlockCaptures(originalBlocks, this, context);
if (!success && snapshot != ItemTypeRegistryModule.NONE_SNAPSHOT) {
Sponge.getCauseStackManager().pushCause(player);
EnumHand hand = ((CPacketPlayerTryUseItemOnBlock) packet).getHand();
PacketPhaseUtil.handlePlayerSlotRestore(player, (net.minecraft.item.ItemStack) itemStack, hand);
}
Sponge.getCauseStackManager().popCause();
});
context.getCapturedItemStackSupplier().acceptAndClearIfNotEmpty(drops -> {
final List<Entity> entities = drops.stream().map(drop -> drop.create(player.getServerWorld())).map(EntityUtil::fromNative).collect(Collectors.toList());
if (!entities.isEmpty()) {
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.PLACEMENT);
Sponge.getCauseStackManager().pushCause(player);
DropItemEvent.Custom event = SpongeEventFactory.createDropItemEventCustom(Sponge.getCauseStackManager().getCurrentCause(), entities);
SpongeImpl.postEvent(event);
if (!event.isCancelled()) {
for (Entity droppedItem : event.getEntities()) {
droppedItem.setCreator(player.getUniqueID());
mixinWorld.forceSpawnEntity(droppedItem);
}
}
}
}
});
final IMixinContainer mixinContainer = ContainerUtil.toMixin(player.openContainer);
mixinContainer.setCaptureInventory(false);
mixinContainer.getCapturedTransactions().clear();
}
use of org.spongepowered.common.interfaces.IMixinContainer in project SpongeCommon by SpongePowered.
the class PlaceRecipePacketState method unwind.
@Override
public void unwind(InventoryPacketContext context) {
CPacketPlaceRecipe packet = context.getPacket();
boolean shift = packet.func_194319_c();
IRecipe recipe = packet.func_194317_b();
final EntityPlayerMP player = context.getPacketPlayer();
((IMixinContainer) player.openContainer).detectAndSendChanges(true);
((IMixinContainer) player.openContainer).setCaptureInventory(false);
((IMixinContainer) player.openContainer).setFirePreview(true);
Inventory craftInv = ((Inventory) player.openContainer).query(QueryOperationTypes.INVENTORY_TYPE.of(CraftingInventory.class));
if (!(craftInv instanceof CraftingInventory)) {
SpongeImpl.getLogger().warn("Detected crafting without a InventoryCrafting!? Crafting Event will not fire.");
return;
}
List<SlotTransaction> previewTransactions = ((IMixinContainer) player.openContainer).getPreviewTransactions();
if (previewTransactions.isEmpty()) {
CraftingOutput slot = ((CraftingInventory) craftInv).getResult();
SlotTransaction st = new SlotTransaction(slot, ItemStackSnapshot.NONE, ItemStackUtil.snapshotOf(slot.peek().orElse(ItemStack.empty())));
previewTransactions.add(st);
}
SpongeCommonEventFactory.callCraftEventPre(player, ((CraftingInventory) craftInv), previewTransactions.get(0), ((CraftingRecipe) recipe), player.openContainer, previewTransactions);
previewTransactions.clear();
final Entity spongePlayer = EntityUtil.fromNative(player);
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
frame.pushCause(spongePlayer);
frame.pushCause(player.openContainer);
List<SlotTransaction> transactions = ((IMixinContainer) player.openContainer).getCapturedTransactions();
ItemStackSnapshot cursor = ItemStackUtil.snapshotOf(player.inventory.getItemStack());
Transaction<ItemStackSnapshot> cursorTransaction = new Transaction<>(cursor, cursor);
ClickInventoryEvent event;
if (shift) {
event = SpongeEventFactory.createClickInventoryEventShiftPrimary(frame.getCurrentCause(), cursorTransaction, ((Container) player.openContainer), transactions);
} else {
event = SpongeEventFactory.createClickInventoryEventPrimary(frame.getCurrentCause(), cursorTransaction, ((Container) player.openContainer), transactions);
}
SpongeImpl.postEvent(event);
if (event.isCancelled() || !event.getCursorTransaction().isValid()) {
PacketPhaseUtil.handleCustomCursor(player, event.getCursorTransaction().getOriginal());
} else {
PacketPhaseUtil.handleCustomCursor(player, event.getCursorTransaction().getFinal());
}
PacketPhaseUtil.handleSlotRestore(player, player.openContainer, event.getTransactions(), event.isCancelled());
event.getTransactions().clear();
}
}
Aggregations