use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.
the class MixinEntityPlayer method onSetItemStackToSlot.
@Inject(method = "setItemStackToSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;"))
private void onSetItemStackToSlot(EntityEquipmentSlot slotIn, ItemStack stack, CallbackInfo ci) {
if (((IMixinInventoryPlayer) this.inventory).capturesTransactions()) {
if (slotIn == EntityEquipmentSlot.MAINHAND) {
ItemStack orig = this.inventory.mainInventory.get(this.inventory.currentItem);
Slot slot = ((PlayerInventory) this.inventory).getMain().getHotbar().getSlot(SlotIndex.of(this.inventory.currentItem)).get();
((IMixinInventoryPlayer) this.inventory).getCapturedTransactions().add(new SlotTransaction(slot, ItemStackUtil.snapshotOf(orig), ItemStackUtil.snapshotOf(stack)));
} else if (slotIn == EntityEquipmentSlot.OFFHAND) {
ItemStack orig = this.inventory.offHandInventory.get(0);
Slot slot = ((PlayerInventory) this.inventory).getOffhand();
((IMixinInventoryPlayer) this.inventory).getCapturedTransactions().add(new SlotTransaction(slot, ItemStackUtil.snapshotOf(orig), ItemStackUtil.snapshotOf(stack)));
} else if (slotIn.getSlotType() == EntityEquipmentSlot.Type.ARMOR) {
ItemStack orig = this.inventory.armorInventory.get(slotIn.getIndex());
Slot slot = ((PlayerInventory) this.inventory).getEquipment().getSlot(SlotIndex.of(slotIn.getIndex())).get();
((IMixinInventoryPlayer) this.inventory).getCapturedTransactions().add(new SlotTransaction(slot, ItemStackUtil.snapshotOf(orig), ItemStackUtil.snapshotOf(stack)));
}
}
}
use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.
the class MixinInventoryPlayer method onAdd.
@Redirect(method = "storePartialItemStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/InventoryPlayer;addResource(ILnet/minecraft/item/ItemStack;)I"))
public int onAdd(InventoryPlayer inv, int index, ItemStack stack) {
if (this.doCapture) {
// Capture items getting picked up
Slot slot = index == 40 ? this.getOffhand() : getSpongeSlot(index);
ItemStackSnapshot original = ItemStackUtil.snapshotOf(this.getStackInSlot(index));
int result = this.addResource(index, stack);
ItemStackSnapshot replacement = ItemStackUtil.snapshotOf(this.getStackInSlot(index));
this.capturedTransactions.add(new SlotTransaction(slot, original, replacement));
return result;
}
return this.addResource(index, stack);
}
use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.
the class MixinContainer method detectAndSendChanges.
@Override
public void detectAndSendChanges(boolean captureOnly) {
this.spongeInit();
for (int i = 0; i < this.inventorySlots.size(); ++i) {
final Slot slot = this.inventorySlots.get(i);
final ItemStack itemstack = slot.getStack();
ItemStack itemstack1 = this.inventoryItemStacks.get(i);
if (!ItemStack.areItemStacksEqual(itemstack1, itemstack)) {
// Sponge start
if (this.captureInventory) {
final ItemStackSnapshot originalItem = itemstack1.isEmpty() ? ItemStackSnapshot.NONE : ((org.spongepowered.api.item.inventory.ItemStack) itemstack1).createSnapshot();
final ItemStackSnapshot newItem = itemstack.isEmpty() ? ItemStackSnapshot.NONE : ((org.spongepowered.api.item.inventory.ItemStack) itemstack).createSnapshot();
org.spongepowered.api.item.inventory.Slot adapter = null;
try {
adapter = this.getContainerSlot(i);
if (this.shiftCraft) {
this.capturedCraftShiftTransactions.add(new SlotTransaction(adapter, originalItem, newItem));
} else {
this.capturedSlotTransactions.add(new SlotTransaction(adapter, originalItem, newItem));
}
} catch (IndexOutOfBoundsException e) {
SpongeImpl.getLogger().error("SlotIndex out of LensBounds! Did the Container change after creation?", e);
}
// We simply capture in order to send the proper changes back to client.
if (captureOnly) {
continue;
}
}
// Sponge end
itemstack1 = itemstack.copy();
this.inventoryItemStacks.set(i, itemstack1);
for (IContainerListener listener : this.listeners) {
listener.sendSlotContents((Container) (Object) this, i, itemstack1);
}
}
}
}
use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.
the class CommandState method unwind.
@Override
public void unwind(CommandPhaseContext phaseContext) {
Optional<EntityPlayer> playerSource = phaseContext.getSource(EntityPlayer.class);
if (playerSource.isPresent()) {
// Post event for inventory changes
((IMixinInventoryPlayer) playerSource.get().inventory).setCapture(false);
List<SlotTransaction> list = ((IMixinInventoryPlayer) playerSource.get().inventory).getCapturedTransactions();
if (!list.isEmpty()) {
ChangeInventoryEvent event = SpongeEventFactory.createChangeInventoryEvent(Sponge.getCauseStackManager().getCurrentCause(), ((Inventory) playerSource.get().inventory), list);
SpongeImpl.postEvent(event);
PacketPhaseUtil.handleSlotRestore(playerSource.get(), null, list, event.isCancelled());
list.clear();
}
}
final CommandSource sender = phaseContext.getSource(CommandSource.class).orElseThrow(TrackingUtil.throwWithContext("Expected to be capturing a Command Sender, but none found!", phaseContext));
phaseContext.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(list -> TrackingUtil.processBlockCaptures(list, this, phaseContext));
try (StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(sender);
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.PLACEMENT);
phaseContext.getCapturedEntitySupplier().acceptAndClearIfNotEmpty(entities -> {
// TODO the entity spawn causes are not likely valid,
// need to investigate further.
final SpawnEntityEvent spawnEntityEvent = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), entities);
SpongeImpl.postEvent(spawnEntityEvent);
if (!spawnEntityEvent.isCancelled()) {
final boolean isPlayer = sender instanceof Player;
final Player player = isPlayer ? (Player) sender : null;
for (Entity entity : spawnEntityEvent.getEntities()) {
if (isPlayer) {
EntityUtil.toMixin(entity).setCreator(player.getUniqueId());
}
EntityUtil.getMixinWorld(entity).forceSpawnEntity(entity);
}
}
});
}
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(sender);
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.DROPPED_ITEM);
phaseContext.getCapturedEntityDropSupplier().acceptIfNotEmpty(uuidItemStackMultimap -> {
for (Map.Entry<UUID, Collection<ItemDropData>> entry : uuidItemStackMultimap.asMap().entrySet()) {
final UUID key = entry.getKey();
@Nullable net.minecraft.entity.Entity foundEntity = null;
for (WorldServer worldServer : WorldManager.getWorlds()) {
final net.minecraft.entity.Entity entityFromUuid = worldServer.getEntityFromUuid(key);
if (entityFromUuid != null) {
foundEntity = entityFromUuid;
break;
}
}
final Optional<Entity> affectedEntity = Optional.ofNullable((Entity) foundEntity);
if (!affectedEntity.isPresent()) {
continue;
}
final Collection<ItemDropData> itemStacks = entry.getValue();
if (itemStacks.isEmpty()) {
return;
}
final List<ItemDropData> items = new ArrayList<>();
items.addAll(itemStacks);
itemStacks.clear();
final WorldServer minecraftWorld = EntityUtil.getMinecraftWorld(affectedEntity.get());
if (!items.isEmpty()) {
final List<Entity> itemEntities = items.stream().map(data -> data.create(minecraftWorld)).map(EntityUtil::fromNative).collect(Collectors.toList());
Sponge.getCauseStackManager().pushCause(affectedEntity.get());
final DropItemEvent.Destruct destruct = SpongeEventFactory.createDropItemEventDestruct(Sponge.getCauseStackManager().getCurrentCause(), itemEntities);
SpongeImpl.postEvent(destruct);
Sponge.getCauseStackManager().popCause();
if (!destruct.isCancelled()) {
final boolean isPlayer = sender instanceof Player;
final Player player = isPlayer ? (Player) sender : null;
for (Entity entity : destruct.getEntities()) {
if (isPlayer) {
EntityUtil.toMixin(entity).setCreator(player.getUniqueId());
}
EntityUtil.getMixinWorld(entity).forceSpawnEntity(entity);
}
}
}
}
});
}
}
use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.
the class BasicInventoryPacketState method unwind.
@Override
public void unwind(InventoryPacketContext context) {
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 CPacketClickWindow 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.getUsedButton();
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(openContainer);
Sponge.getCauseStackManager().pushCause(player);
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() && transaction.getOriginal().equals(transaction.getFinal())) {
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.getSlotId(), openContainer, inventoryEvent.getTransactions());
}
SpongeImpl.postEvent(inventoryEvent);
if (inventoryEvent.isCancelled() || PacketPhaseUtil.allTransactionsInvalid(inventoryEvent.getTransactions())) {
if (inventoryEvent instanceof ClickInventoryEvent.Drop) {
capturedItems.clear();
}
// Restore cursor
if (inventoryEvent.isCancelled() || !inventoryEvent.getCursorTransaction().isValid()) {
PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getOriginal());
} else if (inventoryEvent.getCursorTransaction().getCustom().isPresent()) {
PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getFinal());
}
// 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);
}
Aggregations