use of it.unimi.dsi.fastutil.objects.Object2BooleanArrayMap in project Mekanism by mekanism.
the class QIOCraftingTransferHandler method hasRoomToShuffle.
/**
* Loosely based on how {@link mekanism.common.content.qio.QIOServerCraftingTransferHandler}'s hasRoomToShuffle method works.
*/
private static boolean hasRoomToShuffle(QIOCraftingTransferHelper qioTransferHelper, @Nullable QIOFrequency frequency, QIOCraftingWindow craftingWindow, List<HotBarSlot> hotBarSlots, List<MainInventorySlot> mainInventorySlots, Map<HashedItemSource, List<List<SingularHashedItemSource>>> shuffleLookup) {
// Map used to keep track of inputs while also merging identical inputs, so we can cut down
// on how many times we have to check if things can stack
Object2IntMap<HashedItem> leftOverInput = new Object2IntArrayMap<>(9);
for (byte slotIndex = 0; slotIndex < 9; slotIndex++) {
IInventorySlot slot = craftingWindow.getInputSlot(slotIndex);
if (!slot.isEmpty()) {
// Note: We can use raw as we are not modifying the stack or persisting the reference
HashedItem type = HashedItem.raw(slot.getStack());
HashedItemSource source = qioTransferHelper.getSource(type);
if (source == null) {
// Something went wrong, this should never be null for the things in the crafting slots
return false;
}
int remaining = source.getSlotRemaining(slotIndex);
if (remaining > 0) {
// Don't bother adding any that we fully used
leftOverInput.mergeInt(type, remaining, Integer::sum);
}
}
}
if (!leftOverInput.isEmpty()) {
// If we have any leftover inputs in the crafting inventory, then get a simulated view of what the player's inventory
// will look like after things are changed
BaseSimulatedInventory simulatedInventory = new BaseSimulatedInventory(hotBarSlots, mainInventorySlots) {
@Override
protected int getRemaining(int slot, ItemStack currentStored) {
HashedItemSource source = qioTransferHelper.getSource(HashedItem.raw(currentStored));
if (source == null) {
return currentStored.getCount();
}
return source.getSlotRemaining((byte) (slot + 9));
}
};
Object2IntMap<HashedItem> stillLeftOver = simulatedInventory.shuffleInputs(leftOverInput, frequency != null);
if (stillLeftOver == null) {
// If we have remaining items and no frequency then we don't have room to shuffle
return false;
}
if (!stillLeftOver.isEmpty() && frequency != null) {
// If we still have left over things try adding them to the frequency. We only are able to do a rough check and estimate
// on if the frequency has room or not as depending on how things are stored in the drives there is a chance that we
// do not actually have as much item space or types available, but this is the best we can do on the client side
// Note: We validate the frequency is not null, even though it shouldn't be null if we have anything still left over
// Note: We calculate these numbers as a difference so that it is easier to make sure none of the numbers accidentally overflow
int availableItemTypes = frequency.getTotalItemTypeCapacity() - frequency.getTotalItemTypes(true);
long availableItemSpace = frequency.getTotalItemCountCapacity() - frequency.getTotalItemCount();
Object2BooleanMap<HashedItemSource> usedQIOSource = new Object2BooleanArrayMap<>(shuffleLookup.size());
for (Map.Entry<HashedItemSource, List<List<SingularHashedItemSource>>> entry : shuffleLookup.entrySet()) {
HashedItemSource source = entry.getKey();
boolean usedQIO = false;
for (List<SingularHashedItemSource> usedSources : entry.getValue()) {
for (SingularHashedItemSource usedSource : usedSources) {
UUID qioSource = usedSource.getQioSource();
if (qioSource != null) {
// Free up however much space as we used of the item
availableItemSpace += usedSource.getUsed();
if (source.getQIORemaining(qioSource) == 0) {
// If we used all that is available, we need to also free up an item type
availableItemTypes++;
usedQIO = true;
}
}
}
}
usedQIOSource.put(source, usedQIO);
}
for (Object2IntMap.Entry<HashedItem> entry : stillLeftOver.object2IntEntrySet()) {
availableItemSpace -= entry.getIntValue();
if (availableItemSpace <= 0) {
// No room for all our items, fail
return false;
}
HashedItemSource source = qioTransferHelper.getSource(entry.getKey());
if (source == null) {
// Something went wrong, this should never be null for the things in the crafting slots
return false;
} else if (source.hasQIOSources()) {
// It is stored, check to make sure it isn't a type we are removing at least one of fully
if (usedQIOSource.containsKey(source) && usedQIOSource.getBoolean(source)) {
// if it is, then we need to reclaim the item type as being available
availableItemTypes--;
if (availableItemTypes <= 0) {
// Not enough room for types
return false;
}
}
} else {
// The item is not stored in the QIO frequency, we need to use an item type up
// Note: This is not super accurate due to the fact that we don't know for
// certain if our used source actually matched or differed in server side only
// NBT, but it is the best we can do on the client side
availableItemTypes--;
if (availableItemTypes <= 0) {
// Not enough room for types
return false;
}
}
}
}
}
return true;
}
Aggregations