use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class LanternItem method tryToPickupItems.
private void tryToPickupItems() {
final Set<Entity> entities = getWorld().getIntersectingEntities(getBoundingBox().get().expand(2.0, 0.5, 2.0), entity -> entity != this && entity instanceof Carrier);
if (entities.isEmpty()) {
return;
}
ItemStack itemStack = get(Keys.REPRESENTED_ITEM).map(ItemStackSnapshot::createStack).orElse(null);
if (itemStack == null) {
remove();
return;
}
// TODO: Call pre pickup event
for (Entity entity : entities) {
// Ignore dead entities
if (entity instanceof LanternLiving && ((LanternLiving) entity).isDead()) {
continue;
}
Inventory inventory = ((Carrier) entity).getInventory();
if (inventory instanceof PlayerInventory) {
inventory = ((PlayerInventory) inventory).getMain();
}
final PeekedOfferTransactionResult peekResult = ((IInventory) inventory).peekOffer(itemStack);
final ItemStack rejected = peekResult.getRejectedItem().orElse(null);
final CauseStack causeStack = CauseStack.current();
final ChangeInventoryEvent.Pickup event;
try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
frame.addContext(LanternEventContextKeys.ORIGINAL_ITEM_STACK, itemStack);
if (rejected != null) {
frame.addContext(LanternEventContextKeys.REST_ITEM_STACK, rejected);
}
event = SpongeEventFactory.createChangeInventoryEventPickup(causeStack.getCurrentCause(), inventory, peekResult.getTransactions());
event.setCancelled(!peekResult.isSuccess());
Sponge.getEventManager().post(event);
}
if (event.isCancelled() && !isRemoved()) {
// Don't continue if the entity was removed during the event
continue;
}
event.getTransactions().stream().filter(Transaction::isValid).forEach(transaction -> transaction.getSlot().set(transaction.getFinal().createStack()));
final int added;
if (rejected != null) {
added = itemStack.getQuantity() - rejected.getQuantity();
itemStack = rejected;
} else {
added = itemStack.getQuantity();
}
if (added != 0 && entity instanceof Living) {
triggerEvent(new CollectEntityEvent((Living) entity, added));
}
if (rejected == null || isRemoved()) {
itemStack = null;
}
if (itemStack == null) {
break;
}
}
if (itemStack != null) {
offer(Keys.REPRESENTED_ITEM, itemStack.createSnapshot());
} else {
remove();
}
}
use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class LanternLiving method handleDeath.
private void handleDeath() {
// have already been thrown.
if (getWorld() == null) {
setDead(true);
}
if (isDead()) {
return;
}
setDead(true);
final CauseStack causeStack = CauseStack.current();
// Only players can keep their inventory
final boolean keepsInventory = this instanceof LanternPlayer && getWorld().getOrCreateRule(RuleTypes.KEEP_INVENTORY).getValue();
// Post the entity destruction event
final DestructEntityEvent.Death event = SpongeEventFactory.createDestructEntityEventDeath(causeStack.getCurrentCause(), MessageChannel.TO_NONE, Optional.empty(), new MessageEvent.MessageFormatter(), this, keepsInventory, false);
postDestructEvent(event);
try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
// Add the destruct event to the cause, this can be used
// to track the cause of the entity death.
frame.pushCause(event);
// Post the harvest event
handleDeath(causeStack);
}
// Clear the inventory, if keepsInventory is false in the thrown Death event
if (!event.getKeepInventory() && this instanceof Carrier) {
((Carrier) this).getInventory().clear();
}
}
use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class VanillaContainerInteractionBehavior method handleShiftClick.
@Override
public void handleShiftClick(ClientContainer clientContainer, ClientSlot clientSlot, MouseButton mouseButton) {
final LanternPlayer player = clientContainer.getPlayer();
if (player != this.container.getPlayerInventory().getCarrier().orElse(null) || !(clientSlot instanceof ClientSlot.Slot) || mouseButton == MouseButton.MIDDLE) {
return;
}
final AbstractInventorySlot slot = ((ClientSlot.Slot) clientSlot).getSlot();
final ItemStack itemStack = slot.peek().orElse(null);
final Transaction<ItemStackSnapshot> cursorTransaction;
final List<SlotTransaction> transactions = new ArrayList<>();
if (slot instanceof CraftingOutput) {
final ItemStackSnapshot cursorItem = LanternItemStack.toSnapshot(getCursorItem());
cursorTransaction = new Transaction<>(cursorItem, cursorItem);
final AbstractInventory parent = slot.parent();
if (parent instanceof CraftingInventory) {
final CraftingInventory inventory = (CraftingInventory) parent;
final Optional<ExtendedCraftingResult> optResult = Lantern.getRegistry().getCraftingRecipeRegistry().getExtendedResult(inventory.getCraftingGrid(), player.getWorld());
if (optResult.isPresent()) {
final ExtendedCraftingResult result = optResult.get();
final ItemStackSnapshot resultItem = result.getResult().getResult();
int times = result.getMaxTimes();
final ItemStack itemStack1 = resultItem.createStack();
itemStack1.setQuantity(times * itemStack1.getQuantity());
final AbstractInventory targetInventory = this.container.getPlayerInventory().getView(LanternPlayerInventory.View.REVERSE_MAIN_AND_HOTBAR);
PeekedOfferTransactionResult peekResult = targetInventory.peekOffer(itemStack1);
if (peekResult.isSuccess()) {
transactions.add(new SlotTransaction(slot, resultItem, ItemStackSnapshot.NONE));
final ItemStack rejectedItem = peekResult.getRejectedItem().orElse(null);
if (rejectedItem != null) {
final int added = itemStack1.getQuantity() - rejectedItem.getQuantity();
times = added / resultItem.getQuantity();
final int diff = added % resultItem.getQuantity();
if (diff != 0) {
itemStack1.setQuantity(resultItem.getQuantity() * times);
peekResult = targetInventory.peekOffer(itemStack1);
checkState(peekResult.isSuccess());
}
}
transactions.addAll(peekResult.getTransactions());
updateCraftingGrid(player, inventory, result.getMatrixResult(times), transactions);
}
} else {
// No actual transaction, there shouldn't have been a item in the crafting result slot
transactions.add(new SlotTransaction(slot, ItemStackSnapshot.NONE, ItemStackSnapshot.NONE));
}
} else {
Lantern.getLogger().warn("Found a CraftingOutput slot without a CraftingInventory as parent.");
return;
}
} else {
final ItemStackSnapshot cursorItem = LanternItemStack.toSnapshot(getCursorItem());
cursorTransaction = new Transaction<>(cursorItem, cursorItem);
if (itemStack != null) {
final IInventory target = this.container.getOpenInventory().getShiftClickBehavior().getTarget(this.container, slot);
final PeekedOfferTransactionResult result = target.peekOffer(itemStack.copy());
if (result.isSuccess()) {
transactions.addAll(result.getTransactions());
final ItemStack rejectedItem = result.getRejectedItem().orElse(null);
if (rejectedItem != null) {
slot.peekPoll(itemStack.getQuantity() - rejectedItem.getQuantity(), stack -> true).ifPresent(peekResult -> transactions.addAll(peekResult.getTransactions()));
} else {
slot.peekPoll(stack -> true).ifPresent(peekResult -> transactions.addAll(peekResult.getTransactions()));
}
}
}
}
final List<SlotTransaction> transactions1 = this.container.transformSlots(transactions);
final CauseStack causeStack = CauseStack.current();
final ClickInventoryEvent.Shift event;
if (mouseButton == MouseButton.LEFT) {
event = SpongeEventFactory.createClickInventoryEventShiftPrimary(causeStack.getCurrentCause(), cursorTransaction, this.container, transactions1);
} else {
event = SpongeEventFactory.createClickInventoryEventShiftSecondary(causeStack.getCurrentCause(), cursorTransaction, this.container, transactions1);
}
finishInventoryEvent(event);
}
use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class VanillaContainerInteractionBehavior method handleClick.
@Override
public void handleClick(ClientContainer clientContainer, @Nullable ClientSlot clientSlot, MouseButton mouseButton) {
final LanternPlayer player = clientContainer.getPlayer();
if (player != this.container.getPlayerInventory().getCarrier().orElse(null) || (clientSlot != null && !(clientSlot instanceof ClientSlot.Slot))) {
return;
}
final CauseStack causeStack = CauseStack.current();
if (clientSlot == null) {
causeStack.addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
final List<Entity> entities = new ArrayList<>();
final Transaction<ItemStackSnapshot> cursorTransaction;
// Clicking outside the container
ItemStackSnapshot oldItem = ItemStackSnapshot.NONE;
ItemStackSnapshot newItem = ItemStackSnapshot.NONE;
if (getCursorItem() != null) {
oldItem = getCursorItem().createSnapshot();
final ItemStackSnapshot droppedItem;
if (mouseButton != MouseButton.LEFT) {
final ItemStack stack = getCursorItem().copy();
stack.setQuantity(stack.getQuantity() - 1);
newItem = LanternItemStack.toSnapshot(stack);
stack.setQuantity(1);
droppedItem = LanternItemStack.toSnapshot(stack);
} else {
droppedItem = oldItem;
}
LanternEventHelper.handlePreDroppedItemSpawning(player.getTransform(), droppedItem).ifPresent(entities::add);
}
cursorTransaction = new Transaction<>(oldItem, newItem);
final ClickInventoryEvent.Drop event;
if (mouseButton == MouseButton.LEFT) {
event = SpongeEventFactory.createClickInventoryEventDropOutsidePrimary(causeStack.getCurrentCause(), cursorTransaction, entities, this.container, new ArrayList<>());
} else {
event = SpongeEventFactory.createClickInventoryEventDropOutsideSecondary(causeStack.getCurrentCause(), cursorTransaction, entities, this.container, new ArrayList<>());
}
finishInventoryEvent(event);
return;
}
// Clicking inside the container
final AbstractSlot slot = ((ClientSlot.Slot) clientSlot).getSlot();
if (mouseButton == MouseButton.MIDDLE) {
final ItemStackSnapshot oldItem = LanternItemStack.toSnapshot(getCursorItem());
Transaction<ItemStackSnapshot> cursorTransaction = null;
final Optional<GameMode> gameMode = player.get(Keys.GAME_MODE);
if (gameMode.isPresent() && gameMode.get().equals(GameModes.CREATIVE) && getCursorItem() == null) {
final ItemStack stack = slot.peek().orElse(null);
if (stack != null) {
stack.setQuantity(stack.getMaxStackQuantity());
cursorTransaction = new Transaction<>(oldItem, stack.createSnapshot());
}
}
if (cursorTransaction == null) {
cursorTransaction = new Transaction<>(oldItem, oldItem);
}
final ClickInventoryEvent.Middle event = SpongeEventFactory.createClickInventoryEventMiddle(causeStack.getCurrentCause(), cursorTransaction, this.container, new ArrayList<>());
finishInventoryEvent(event);
} else {
// Crafting slots have special click behavior
if (slot instanceof CraftingOutput) {
List<SlotTransaction> transactions = new ArrayList<>();
Transaction<ItemStackSnapshot> cursorTransaction;
final AbstractInventory parent = slot.parent();
if (parent instanceof CraftingInventory) {
ClickInventoryEvent event;
final CraftingInventory inventory = (CraftingInventory) parent;
final Optional<ExtendedCraftingResult> optResult = Lantern.getRegistry().getCraftingRecipeRegistry().getExtendedResult(inventory.getCraftingGrid(), player.getWorld());
final ItemStackSnapshot originalCursorItem = LanternItemStack.toSnapshot(getCursorItem());
if (optResult.isPresent()) {
final CraftingResult result = optResult.get().getResult();
final ItemStackSnapshot resultItem = result.getResult();
int quantity = -1;
if (getCursorItem() == null) {
quantity = resultItem.getQuantity();
} else if (LanternItemStack.areSimilar(resultItem.createStack(), getCursorItem())) {
final int quantity1 = resultItem.getQuantity() + getCursorItem().getQuantity();
if (quantity1 < getCursorItem().getMaxStackQuantity()) {
quantity = quantity1;
}
}
if (quantity == -1) {
cursorTransaction = new Transaction<>(originalCursorItem, originalCursorItem);
transactions.add(new SlotTransaction(slot, resultItem, resultItem));
} else {
final LanternItemStack itemStack = (LanternItemStack) resultItem.createStack();
itemStack.setQuantity(quantity);
cursorTransaction = new Transaction<>(originalCursorItem, itemStack.createSnapshot());
transactions.add(new SlotTransaction(slot, resultItem, ItemStackSnapshot.NONE));
updateCraftingGrid(player, inventory, optResult.get().getMatrixResult(1), transactions);
}
} else {
cursorTransaction = new Transaction<>(originalCursorItem, originalCursorItem);
// No actual transaction, there shouldn't have been a item in the crafting result slot
transactions.add(new SlotTransaction(slot, ItemStackSnapshot.NONE, ItemStackSnapshot.NONE));
}
transactions = this.container.transformSlots(transactions);
if (mouseButton == MouseButton.LEFT) {
event = SpongeEventFactory.createClickInventoryEventPrimary(causeStack.getCurrentCause(), cursorTransaction, this.container, transactions);
} else {
event = SpongeEventFactory.createClickInventoryEventSecondary(causeStack.getCurrentCause(), cursorTransaction, this.container, transactions);
}
finishInventoryEvent(event);
return;
} else {
Lantern.getLogger().warn("Found a CraftingOutput slot without a CraftingInventory as parent.");
}
}
ClickInventoryEvent event;
if (mouseButton == MouseButton.LEFT) {
final List<SlotTransaction> transactions = new ArrayList<>();
Transaction<ItemStackSnapshot> cursorTransaction = null;
if (getCursorItem() != null && !(slot instanceof OutputSlot)) {
final PeekedOfferTransactionResult result = slot.peekOffer(getCursorItem());
if (result.isSuccess()) {
transactions.addAll(result.getTransactions());
cursorTransaction = new Transaction<>(getCursorItem().createSnapshot(), LanternItemStack.toSnapshot(result.getRejectedItem().orElse(null)));
} else {
final PeekedSetTransactionResult result1 = slot.peekSet(getCursorItem());
if (result1.isSuccess()) {
cursorTransaction = new Transaction<>(getCursorItem().createSnapshot(), LanternItemStack.toSnapshot(result1.getReplacedItem().orElse(null)));
transactions.addAll(result1.getTransactions());
}
}
} else if (getCursorItem() == null) {
final PeekedPollTransactionResult result = slot.peekPoll(stack -> true).orElse(null);
if (result != null) {
cursorTransaction = new Transaction<>(ItemStackSnapshot.NONE, LanternItemStack.toSnapshot(result.getPolledItem()));
transactions.addAll(result.getTransactions());
} else {
cursorTransaction = new Transaction<>(ItemStackSnapshot.NONE, ItemStackSnapshot.NONE);
}
}
if (cursorTransaction == null) {
final ItemStackSnapshot cursorItem = LanternItemStack.toSnapshot(getCursorItem());
cursorTransaction = new Transaction<>(cursorItem, cursorItem);
}
event = SpongeEventFactory.createClickInventoryEventPrimary(causeStack.getCurrentCause(), cursorTransaction, this.container, this.container.transformSlots(transactions));
} else {
final List<SlotTransaction> transactions = new ArrayList<>();
Transaction<ItemStackSnapshot> cursorTransaction = null;
if (getCursorItem() == null) {
int stackSize = slot.getStackSize();
if (stackSize != 0) {
stackSize = stackSize - (stackSize / 2);
final PeekedPollTransactionResult result = slot.peekPoll(stackSize, stack -> true).get();
transactions.addAll(result.getTransactions());
cursorTransaction = new Transaction<>(ItemStackSnapshot.NONE, result.getPolledItem().createSnapshot());
}
} else {
final ItemStack itemStack = getCursorItem().copy();
itemStack.setQuantity(1);
final PeekedOfferTransactionResult result = slot.peekOffer(itemStack);
if (result.isSuccess()) {
final ItemStackSnapshot oldCursor = getCursorItem().createSnapshot();
int quantity = getCursorItem().getQuantity() - 1;
if (quantity <= 0) {
cursorTransaction = new Transaction<>(oldCursor, ItemStackSnapshot.NONE);
} else {
final ItemStack newCursorItem = getCursorItem().copy();
newCursorItem.setQuantity(quantity);
cursorTransaction = new Transaction<>(oldCursor, newCursorItem.createSnapshot());
}
transactions.addAll(result.getTransactions());
} else {
final PeekedSetTransactionResult result1 = slot.peekSet(getCursorItem());
if (result1.isSuccess()) {
final ItemStack replacedItem = result1.getReplacedItem().orElse(null);
if (replacedItem != null) {
setCursorItem(replacedItem);
cursorTransaction = new Transaction<>(getCursorItem().createSnapshot(), LanternItemStack.toSnapshot(replacedItem));
} else {
cursorTransaction = new Transaction<>(getCursorItem().createSnapshot(), ItemStackSnapshot.NONE);
}
transactions.addAll(result1.getTransactions());
}
}
}
if (cursorTransaction == null) {
final ItemStackSnapshot cursorItem = LanternItemStack.toSnapshot(getCursorItem());
cursorTransaction = new Transaction<>(cursorItem, cursorItem);
}
event = SpongeEventFactory.createClickInventoryEventSecondary(causeStack.getCurrentCause(), cursorTransaction, this.container, this.container.transformSlots(transactions));
}
finishInventoryEvent(event);
}
}
use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class VanillaContainerInteractionBehavior method handleDropKey.
@Override
public void handleDropKey(ClientContainer clientContainer, ClientSlot clientSlot, boolean ctrl) {
final LanternPlayer player = clientContainer.getPlayer();
if (player != this.container.getPlayerInventory().getCarrier().orElse(null) || !(clientSlot instanceof ClientSlot.Slot)) {
return;
}
final AbstractSlot slot = ((ClientSlot.Slot) clientSlot).getSlot();
final CauseStack causeStack = CauseStack.current();
causeStack.addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
final List<Entity> entities = new ArrayList<>();
final Transaction<ItemStackSnapshot> cursorTransaction;
List<SlotTransaction> slotTransactions = new ArrayList<>();
final ItemStackSnapshot item = LanternItemStack.toSnapshot(getCursorItem());
cursorTransaction = new Transaction<>(item, item);
final Optional<PeekedPollTransactionResult> result = ctrl ? slot.peekPoll(itemStack -> true) : slot.peekPoll(1, itemStack -> true);
if (result.isPresent()) {
final List<SlotTransaction> transactions = result.get().getTransactions();
slotTransactions.addAll(transactions);
final ItemStack itemStack = transactions.get(0).getOriginal().createStack();
itemStack.setQuantity(itemStack.getQuantity() - transactions.get(0).getFinal().getQuantity());
LanternEventHelper.handlePreDroppedItemSpawning(player.getTransform(), LanternItemStackSnapshot.wrap(itemStack)).ifPresent(entities::add);
}
slotTransactions = this.container.transformSlots(slotTransactions);
final ClickInventoryEvent.Drop event;
if (ctrl) {
event = SpongeEventFactory.createClickInventoryEventDropFull(causeStack.getCurrentCause(), cursorTransaction, entities, this.container, slotTransactions);
} else {
event = SpongeEventFactory.createClickInventoryEventDropSingle(causeStack.getCurrentCause(), cursorTransaction, entities, this.container, slotTransactions);
}
finishInventoryEvent(event);
}
Aggregations