use of org.lanternpowered.server.inventory.PeekedOfferTransactionResult in project LanternServer by LanternPowered.
the class ArmorQuickEquipInteractionBehavior method tryInteract.
@Override
public BehaviorResult tryInteract(BehaviorPipeline<Behavior> pipeline, BehaviorContext context) {
final LanternPlayer player = (LanternPlayer) context.requireContext(ContextKeys.PLAYER);
final ItemStack itemStack = context.requireContext(ContextKeys.USED_ITEM_STACK);
final PeekedOfferTransactionResult peekResult = player.getInventory().getEquipment().peekOffer(itemStack.copy());
if (peekResult.isSuccess()) {
final List<SlotTransaction> transactions = new ArrayList<>(peekResult.getTransactions());
final AbstractSlot slot = (AbstractSlot) context.getContext(ContextKeys.USED_SLOT).orElse(null);
if (slot != null) {
transactions.add(new SlotTransaction(slot, itemStack.createSnapshot(), LanternItemStack.toSnapshot(peekResult.getRejectedItem().orElse(null))));
}
final ChangeInventoryEvent.Equipment event = SpongeEventFactory.createChangeInventoryEventEquipment(context.getCurrentCause(), player.getInventory(), transactions);
if (event.isCancelled()) {
return BehaviorResult.CONTINUE;
}
event.getTransactions().stream().filter(Transaction::isValid).forEach(slotTransaction -> slotTransaction.getSlot().set(slotTransaction.getFinal().createStack()));
return BehaviorResult.SUCCESS;
}
return BehaviorResult.CONTINUE;
}
use of org.lanternpowered.server.inventory.PeekedOfferTransactionResult in project LanternServer by LanternPowered.
the class LanternFurnace method pulse.
@Override
public void pulse() {
super.pulse();
if (this.lastTick == -1) {
this.lastTick = LanternGame.currentTimeTicks();
return;
}
final long ticks = LanternGame.currentTimeTicks();
long elapsed = ticks - this.lastTick;
// This shouldn't happen
if (elapsed == 0) {
return;
}
this.lastTick = ticks;
while (elapsed > 0) {
int maxCookTime = 0;
Optional<SmeltingResult> smeltingResult = Optional.empty();
Optional<SmeltingRecipe> smeltingRecipe = Optional.empty();
ItemStack itemStack = this.inventory.getInputSlot().getRawItemStack();
final ItemStackSnapshot inputSlotItemSnapshot = itemStack == null ? null : itemStack.createSnapshot();
if (inputSlotItemSnapshot != null) {
// Check if the item can be smelted, this means finding a compatible
// recipe and the output has to be empty.
smeltingRecipe = Lantern.getRegistry().getSmeltingRecipeRegistry().findMatchingRecipe(inputSlotItemSnapshot);
if (smeltingRecipe.isPresent()) {
final int quantity = ((ISmeltingRecipe) smeltingRecipe.get()).getIngredient().getQuantity(inputSlotItemSnapshot);
if (inputSlotItemSnapshot.getQuantity() >= quantity) {
smeltingResult = smeltingRecipe.get().getResult(inputSlotItemSnapshot);
// Check if the item can be smelted
if (smeltingResult.isPresent()) {
// Check if the result could be added to the output
final PeekedOfferTransactionResult peekResult = this.inventory.getOutputSlot().peekOffer(smeltingResult.get().getResult().createStack());
if (peekResult.isSuccess()) {
maxCookTime = ((ISmeltingRecipe) smeltingRecipe.get()).getSmeltTime(inputSlotItemSnapshot).orElse(200);
}
}
}
}
}
// The ticks that are elapsed in this loop, limit
// this to one cooking cycle, this can only happen
// if actually a item is being cooked
long elapsed1 = elapsed;
int elapsedCookTime = get(Keys.PASSED_COOK_TIME).get();
int remainingCookTime = maxCookTime - elapsedCookTime;
if (maxCookTime > 0 && elapsed1 > remainingCookTime) {
elapsed1 = remainingCookTime;
}
elapsed -= elapsed1;
// Burn items until the furnace is burning properly
int maxBurnTime = get(Keys.MAX_BURN_TIME).get();
int elapsedBurnTime = get(Keys.PASSED_BURN_TIME).get();
int remainingBurnTime = maxBurnTime - elapsedBurnTime;
long elapsed2 = elapsed1;
while (elapsed2 >= remainingBurnTime) {
elapsed2 -= remainingBurnTime;
// Reset the max burn time
maxBurnTime = 0;
// Only burn a new item if the target item can be smelted
itemStack = this.inventory.getFuelSlot().getRawItemStack();
if (itemStack != null && maxCookTime > 0) {
// Check for the next fuel item
final ItemStackSnapshot itemStackSnapshot = itemStack.createSnapshot();
final Optional<IFuel> result = Lantern.getRegistry().getFuelRegistry().findMatching(itemStackSnapshot);
if (result.isPresent()) {
final OptionalInt optBurnTime = result.get().getBurnTime(itemStackSnapshot);
// We have a next matching burn item, check if we can poll one and then continue burning
if (optBurnTime.isPresent() && this.inventory.getFuelSlot().poll(1).isPresent()) {
maxBurnTime = optBurnTime.getAsInt();
remainingBurnTime = maxBurnTime;
elapsedBurnTime = 0;
// Put the rest item in the slot, if the slot is empty
if (this.inventory.getFuelSlot().size() == 0) {
final IIngredient ingredient = result.get().getIngredient();
final Optional<ItemStack> remainingItem = ingredient.getRemainingItem(itemStackSnapshot);
remainingItem.ifPresent(this.inventory.getFuelSlot()::setForced);
}
}
}
}
if (maxBurnTime == 0) {
break;
}
}
elapsedBurnTime = maxBurnTime == 0 ? 0 : (int) (elapsedBurnTime + elapsed2);
remainingBurnTime = maxBurnTime - elapsedBurnTime;
offer(Keys.MAX_BURN_TIME, maxBurnTime);
offer(Keys.PASSED_BURN_TIME, elapsedBurnTime);
if (maxCookTime > 0) {
// The furnace is still burning
if (remainingBurnTime > 0) {
// The item is smelted
if (elapsed1 >= remainingCookTime) {
offer(Keys.MAX_COOK_TIME, 0);
offer(Keys.PASSED_COOK_TIME, 0);
final int quantity = ((ISmeltingRecipe) smeltingRecipe.get()).getIngredient().getQuantity(inputSlotItemSnapshot);
this.inventory.getOutputSlot().offer(smeltingResult.get().getResult().createStack());
this.inventory.getInputSlot().poll(quantity);
// Put the rest item in the slot
if (this.inventory.getInputSlot().size() == 0) {
final IIngredient ingredient = ((ISmeltingRecipe) smeltingRecipe.get()).getIngredient();
final Optional<ItemStack> remainingItem = ingredient.getRemainingItem(inputSlotItemSnapshot);
remainingItem.ifPresent(this.inventory.getInputSlot()::set);
}
} else {
// Keep on smelting
offer(Keys.MAX_COOK_TIME, maxCookTime);
offer(Keys.PASSED_COOK_TIME, (int) (elapsedCookTime + elapsed1));
break;
}
} else if (elapsedCookTime > 0) {
// Undo smelting progress
final long time = elapsedCookTime - elapsed1 * 2;
offer(Keys.MAX_COOK_TIME, time <= 0 ? 0 : maxCookTime);
offer(Keys.PASSED_COOK_TIME, (int) (time <= 0 ? 0 : time));
break;
}
} else {
offer(Keys.MAX_COOK_TIME, 0);
offer(Keys.PASSED_COOK_TIME, 0);
}
}
BlockState blockState = getLocation().getBlock();
final boolean burning = get(Keys.PASSED_BURN_TIME).get() < get(Keys.MAX_BURN_TIME).get();
final boolean blockBurning = blockState.getType() == BlockTypes.LIT_FURNACE;
if (burning != blockBurning) {
blockState = (burning ? BlockTypes.LIT_FURNACE : BlockTypes.FURNACE).getDefaultState().withTrait(LanternEnumTraits.HORIZONTAL_FACING, blockState.getTraitValue(LanternEnumTraits.HORIZONTAL_FACING).get()).get();
getLocation().setBlock(blockState);
}
}
use of org.lanternpowered.server.inventory.PeekedOfferTransactionResult in project LanternServer by LanternPowered.
the class LanternFurnace method smelt.
@Override
public boolean smelt() {
final ItemStack itemStack = this.inventory.getInputSlot().getRawItemStack();
if (itemStack != null) {
// Check if the item can be smelted, this means finding a compatible
// recipe and the output has to be empty.
final ItemStackSnapshot itemStackSnapshot = itemStack.createSnapshot();
final Optional<SmeltingRecipe> smeltingRecipe = Lantern.getRegistry().getSmeltingRecipeRegistry().findMatchingRecipe(itemStackSnapshot);
final Optional<SmeltingResult> smeltingResult = smeltingRecipe.flatMap(recipe -> recipe.getResult(itemStackSnapshot));
// Check if the item can be smelted
if (smeltingResult.isPresent()) {
final int quantity = ((ISmeltingRecipe) smeltingRecipe.get()).getIngredient().getQuantity(itemStackSnapshot);
if (itemStack.getQuantity() >= quantity) {
final ItemStack result = smeltingResult.get().getResult().createStack();
// Check if the result could be added to the output
final PeekedOfferTransactionResult peekResult = this.inventory.getOutputSlot().peekOffer(result);
if (peekResult.isSuccess()) {
this.inventory.getInputSlot().poll(quantity);
this.inventory.getOutputSlot().offer(result);
return true;
}
}
}
}
return false;
}
use of org.lanternpowered.server.inventory.PeekedOfferTransactionResult 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.inventory.PeekedOfferTransactionResult 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);
}
Aggregations