use of cn.nukkit.inventory.transaction.action.SlotChangeAction in project Nukkit by Nukkit.
the class InventoryTransaction method callExecuteEvent.
protected boolean callExecuteEvent() {
InventoryTransactionEvent ev = new InventoryTransactionEvent(this);
this.source.getServer().getPluginManager().callEvent(ev);
SlotChangeAction from = null;
SlotChangeAction to = null;
Player who = null;
for (InventoryAction action : this.actions) {
if (!(action instanceof SlotChangeAction)) {
continue;
}
SlotChangeAction slotChange = (SlotChangeAction) action;
if (slotChange.getInventory() instanceof PlayerInventory) {
who = (Player) slotChange.getInventory().getHolder();
}
if (from == null) {
from = slotChange;
} else {
to = slotChange;
}
}
if (who != null && to != null) {
if (from.getTargetItem().getCount() > from.getSourceItem().getCount()) {
from = to;
}
InventoryClickEvent ev2 = new InventoryClickEvent(who, from.getInventory(), from.getSlot(), from.getSourceItem(), from.getTargetItem());
this.source.getServer().getPluginManager().callEvent(ev2);
if (ev2.isCancelled()) {
return false;
}
}
return !ev.isCancelled();
}
use of cn.nukkit.inventory.transaction.action.SlotChangeAction in project Nukkit by Nukkit.
the class InventoryTransaction method squashDuplicateSlotChanges.
/**
* Iterates over SlotChangeActions in this transaction and compacts any which refer to the same inventorySlot in the same
* inventory so they can be correctly handled.
* <p>
* Under normal circumstances, the same inventorySlot would never be changed more than once in a single transaction. However,
* due to the way things like the crafting grid are "implemented" in MCPE 1.2 (a.k.a. hacked-in), we may get
* multiple inventorySlot changes referring to the same inventorySlot in a single transaction. These multiples are not even guaranteed
* to be in the correct order (inventorySlot splitting in the crafting grid for example, causes the actions to be sent in the
* wrong order), so this method also tries to chain them into order.
*
* @return bool
*/
protected boolean squashDuplicateSlotChanges() {
Map<Integer, List<SlotChangeAction>> slotChanges = new HashMap<>();
for (InventoryAction action : this.actions) {
if (action instanceof SlotChangeAction) {
int hash = Objects.hash(((SlotChangeAction) action).getInventory(), ((SlotChangeAction) action).getSlot());
List<SlotChangeAction> list = slotChanges.get(hash);
if (list == null) {
list = new ArrayList<>();
}
list.add((SlotChangeAction) action);
slotChanges.put(hash, list);
}
}
for (Entry<Integer, List<SlotChangeAction>> entry : new ArrayList<>(slotChanges.entrySet())) {
int hash = entry.getKey();
List<SlotChangeAction> list = entry.getValue();
if (list.size() == 1) {
// No need to compact inventorySlot changes if there is only one on this inventorySlot
slotChanges.remove(hash);
continue;
}
List<SlotChangeAction> originalList = new ArrayList<>(list);
SlotChangeAction originalAction = null;
Item lastTargetItem = null;
for (int i = 0; i < list.size(); i++) {
SlotChangeAction action = list.get(i);
if (action.isValid(this.source)) {
originalAction = action;
lastTargetItem = action.getTargetItem();
list.remove(i);
break;
}
}
if (originalAction == null) {
// Couldn't find any actions that had a source-item matching the current inventory inventorySlot
return false;
}
int sortedThisLoop;
do {
sortedThisLoop = 0;
for (int i = 0; i < list.size(); i++) {
SlotChangeAction action = list.get(i);
Item actionSource = action.getSourceItem();
if (actionSource.equalsExact(lastTargetItem)) {
lastTargetItem = action.getTargetItem();
list.remove(i);
sortedThisLoop++;
} else if (actionSource.equals(lastTargetItem)) {
lastTargetItem.count -= actionSource.count;
list.remove(i);
if (lastTargetItem.count == 0)
sortedThisLoop++;
}
}
} while (sortedThisLoop > 0);
if (list.size() > 0) {
// couldn't chain all the actions together
MainLogger.getLogger().debug("Failed to compact " + originalList.size() + " actions for " + this.source.getName());
return false;
}
for (SlotChangeAction action : originalList) {
this.actions.remove(action);
}
this.addAction(new SlotChangeAction(originalAction.getInventory(), originalAction.getSlot(), originalAction.getSourceItem(), lastTargetItem));
MainLogger.getLogger().debug("Successfully compacted " + originalList.size() + " actions for " + this.source.getName());
}
return true;
}
Aggregations