Make AbstractVirtualMachineItemStackHandlers more flexible.

This commit is contained in:
Florian Nücke
2021-01-14 16:55:31 +01:00
parent 3b2dc8cefa
commit bf3a0da468
6 changed files with 90 additions and 81 deletions

View File

@@ -12,4 +12,5 @@ public final class DeviceTypes {
@ObjectHolder("hard_drive") public static DeviceType HARD_DRIVE = null;
@ObjectHolder("flash_memory") public static DeviceType FLASH_MEMORY = null;
@ObjectHolder("card") public static DeviceType CARD = null;
@ObjectHolder("robot_module") public static DeviceType ROBOT_MODULE = null;
}

View File

@@ -26,6 +26,7 @@ public final class DeviceTypes {
register("hard_drive");
register("flash_memory");
register("card");
register("robot_module");
DEVICE_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus());
}

View File

@@ -2,6 +2,7 @@ package li.cil.oc2.common.entity;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.bus.device.object.Callback;
import li.cil.oc2.api.bus.device.object.ObjectDevice;
import li.cil.oc2.api.bus.device.object.Parameter;
@@ -71,7 +72,7 @@ public final class RobotEntity extends Entity {
private static final int MEMORY_SLOTS = 4;
private static final int HARD_DRIVE_SLOTS = 2;
private static final int FLASH_MEMORY_SLOTS = 1;
private static final int CARD_SLOTS = 2;
private static final int MODULE_SLOTS = 4;
///////////////////////////////////////////////////////////////////
@@ -483,7 +484,12 @@ public final class RobotEntity extends Entity {
private final class RobotItemStackHandlers extends AbstractVirtualMachineItemStackHandlers {
public RobotItemStackHandlers() {
super(MEMORY_SLOTS, HARD_DRIVE_SLOTS, FLASH_MEMORY_SLOTS, CARD_SLOTS);
super(
GroupDefinition.of(DeviceTypes.MEMORY, MEMORY_SLOTS),
GroupDefinition.of(DeviceTypes.HARD_DRIVE, HARD_DRIVE_SLOTS),
GroupDefinition.of(DeviceTypes.FLASH_MEMORY, FLASH_MEMORY_SLOTS),
GroupDefinition.of(DeviceTypes.ROBOT_MODULE, MODULE_SLOTS)
);
}
@Override

View File

@@ -1,6 +1,7 @@
package li.cil.oc2.common.item;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.data.BaseBlockDevices;
import li.cil.oc2.common.bus.device.data.Firmwares;
@@ -46,18 +47,18 @@ public final class ItemGroup {
final ItemStack computer = new ItemStack(Items.COMPUTER_ITEM.get());
final CompoundNBT computerItems = ItemStackUtils.getOrCreateTileEntityInventoryTag(computer);
computerItems.put(AbstractVirtualMachineItemStackHandlers.MEMORY_TAG_NAME, makeInventoryTag(
computerItems.put(DeviceTypes.MEMORY.getRegistryName().toString(), makeInventoryTag(
MemoryItem.withCapacity(8 * Constants.MEGABYTE),
MemoryItem.withCapacity(8 * Constants.MEGABYTE),
MemoryItem.withCapacity(8 * Constants.MEGABYTE)
));
computerItems.put(AbstractVirtualMachineItemStackHandlers.HARD_DRIVE_TAG_NAME, makeInventoryTag(
computerItems.put(DeviceTypes.HARD_DRIVE.getRegistryName().toString(), makeInventoryTag(
HardDriveItem.withBase(BaseBlockDevices.BUILDROOT.get())
));
computerItems.put(AbstractVirtualMachineItemStackHandlers.FLASH_MEMORY_TAG_NAME, makeInventoryTag(
computerItems.put(DeviceTypes.FLASH_MEMORY.getRegistryName().toString(), makeInventoryTag(
FlashMemoryItem.withFirmware(Firmwares.BUILDROOT.get())
));
computerItems.put(AbstractVirtualMachineItemStackHandlers.CARD_TAG_NAME, makeInventoryTag(
computerItems.put(DeviceTypes.CARD.getRegistryName().toString(), makeInventoryTag(
new ItemStack(Items.NETWORK_INTERFACE_CARD_ITEM.get())
));

View File

@@ -2,6 +2,7 @@ package li.cil.oc2.common.tileentity;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.block.ComputerBlock;
import li.cil.oc2.common.bus.AbstractDeviceBusController;
@@ -225,7 +226,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
@Override
protected void collectCapabilities(final CapabilityCollector collector, @Nullable final Direction direction) {
collector.offer(Capabilities.ITEM_HANDLER, items.itemHandlers);
collector.offer(Capabilities.ITEM_HANDLER, items.combinedItemHandlers);
collector.offer(Capabilities.DEVICE_BUS_ELEMENT, busElement);
}
@@ -262,7 +263,12 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
private final class ComputerItemStackHandlers extends AbstractVirtualMachineItemStackHandlers {
public ComputerItemStackHandlers() {
super(MEMORY_SLOTS, HARD_DRIVE_SLOTS, FLASH_MEMORY_SLOTS, CARD_SLOTS);
super(
GroupDefinition.of(DeviceTypes.MEMORY, MEMORY_SLOTS),
GroupDefinition.of(DeviceTypes.HARD_DRIVE, HARD_DRIVE_SLOTS),
GroupDefinition.of(DeviceTypes.FLASH_MEMORY, FLASH_MEMORY_SLOTS),
GroupDefinition.of(DeviceTypes.CARD, CARD_SLOTS)
);
}
@Override

View File

@@ -15,75 +15,77 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public abstract class AbstractVirtualMachineItemStackHandlers implements VirtualMachineItemStackHandlers {
public static final class GroupDefinition {
public final DeviceType deviceType;
public final int count;
public static GroupDefinition of(final DeviceType deviceType, final int count) {
return new GroupDefinition(deviceType, count);
}
private GroupDefinition(final DeviceType deviceType, final int count) {
this.deviceType = deviceType;
this.count = count;
}
}
///////////////////////////////////////////////////////////////////
private static final long ITEM_DEVICE_BASE_ADDRESS = 0x40000000L;
private static final int ITEM_DEVICE_STRIDE = 0x1000;
public static final String MEMORY_TAG_NAME = "memory";
public static final String HARD_DRIVE_TAG_NAME = "hard_drive";
public static final String FLASH_MEMORY_TAG_NAME = "flash_memory";
public static final String CARD_TAG_NAME = "card";
///////////////////////////////////////////////////////////////////
public static void addInformation(final ItemStack stack, final List<ITextComponent> tooltip) {
TooltipUtils.addInventoryInformation(stack, tooltip,
MEMORY_TAG_NAME,
HARD_DRIVE_TAG_NAME,
FLASH_MEMORY_TAG_NAME,
CARD_TAG_NAME);
final ForgeRegistry<DeviceType> registry = RegistryManager.ACTIVE.getRegistry(DeviceType.REGISTRY);
if (registry != null) {
TooltipUtils.addInventoryInformation(stack, tooltip,
registry.getValues().stream().map(deviceType ->
deviceType.getRegistryName().toString()).toArray(String[]::new));
}
}
///////////////////////////////////////////////////////////////////
public final DeviceBusElement busElement = new BusElement();
public final DeviceItemStackHandler memoryItemHandler;
public final DeviceItemStackHandler hardDriveItemHandler;
public final DeviceItemStackHandler flashMemoryItemHandler;
public final DeviceItemStackHandler cardItemHandler;
// NB: linked hash map such that order of parameters in constructor is retained.
// This is relevant when assigning default addresses for devices.
private final LinkedHashMap<DeviceType, DeviceItemStackHandler> itemHandlers = new LinkedHashMap<>();
public final IItemHandler itemHandlers;
public final IItemHandler combinedItemHandlers;
///////////////////////////////////////////////////////////////////
public AbstractVirtualMachineItemStackHandlers(final int memorySlots,
final int hardDriveSlots,
final int flashMemorySlots,
final int cardSlots) {
memoryItemHandler = new ItemHandler(memorySlots, this::getDevices, DeviceTypes.MEMORY);
hardDriveItemHandler = new ItemHandler(hardDriveSlots, this::getDevices, DeviceTypes.HARD_DRIVE);
flashMemoryItemHandler = new ItemHandler(flashMemorySlots, this::getDevices, DeviceTypes.FLASH_MEMORY);
cardItemHandler = new ItemHandler(cardSlots, this::getDevices, DeviceTypes.CARD);
public AbstractVirtualMachineItemStackHandlers(final GroupDefinition... groups) {
for (final GroupDefinition group : groups) {
itemHandlers.put(group.deviceType, new ItemHandler(group.count, this::getDevices, group.deviceType));
}
itemHandlers = new CombinedInvWrapper(memoryItemHandler, hardDriveItemHandler, flashMemoryItemHandler, cardItemHandler);
combinedItemHandlers = new CombinedInvWrapper(itemHandlers.values().toArray(new IItemHandlerModifiable[0]));
}
///////////////////////////////////////////////////////////////////
@Override
public Optional<IItemHandler> getItemHandler(final DeviceType deviceType) {
if (deviceType == DeviceTypes.MEMORY) {
return Optional.of(memoryItemHandler);
} else if (deviceType == DeviceTypes.HARD_DRIVE) {
return Optional.of(hardDriveItemHandler);
} else if (deviceType == DeviceTypes.FLASH_MEMORY) {
return Optional.of(flashMemoryItemHandler);
} else if (deviceType == DeviceTypes.CARD) {
return Optional.of(cardItemHandler);
}
return Optional.empty();
return Optional.ofNullable(itemHandlers.get(deviceType));
}
@Override
public boolean isEmpty() {
for (int slot = 0; slot < itemHandlers.getSlots(); slot++) {
if (!itemHandlers.getStackInSlot(slot).isEmpty()) {
for (int slot = 0; slot < combinedItemHandlers.getSlots(); slot++) {
if (!combinedItemHandlers.getStackInSlot(slot).isEmpty()) {
return false;
}
}
@@ -93,22 +95,23 @@ public abstract class AbstractVirtualMachineItemStackHandlers implements Virtual
public OptionalLong getDefaultDeviceAddress(final VMDevice wrapper) {
long address = ITEM_DEVICE_BASE_ADDRESS;
for (int slot = 0; slot < hardDriveItemHandler.getSlots(); slot++) {
final Collection<ItemDeviceInfo> devices = hardDriveItemHandler.getBusElement().getDeviceGroup(slot);
for (final ItemDeviceInfo info : devices) {
if (Objects.equals(info.device, wrapper)) {
return OptionalLong.of(address);
}
for (final Map.Entry<DeviceType, DeviceItemStackHandler> entry : itemHandlers.entrySet()) {
final DeviceType deviceType = entry.getKey();
final DeviceItemStackHandler handler = entry.getValue();
// Ahhh, such special casing, much wow. Honestly I don't expect this
// special case to ever be needed for anything other than physical
// memory, so it's fine. Prove me wrong.
if (deviceType == DeviceTypes.MEMORY) {
continue;
}
address += ITEM_DEVICE_STRIDE;
}
for (int slot = 0; slot < cardItemHandler.getSlots(); slot++) {
final Collection<ItemDeviceInfo> devices = cardItemHandler.getBusElement().getDeviceGroup(slot);
for (final ItemDeviceInfo info : devices) {
if (Objects.equals(info.device, wrapper)) {
return OptionalLong.of(address);
for (int i = 0; i < handler.getSlots(); i++) {
final Collection<ItemDeviceInfo> devices = handler.getBusElement().getDeviceGroup(i);
for (final ItemDeviceInfo info : devices) {
if (Objects.equals(info.device, wrapper)) {
return OptionalLong.of(address);
}
}
}
@@ -120,36 +123,30 @@ public abstract class AbstractVirtualMachineItemStackHandlers implements Virtual
@Override
public void exportDeviceDataToItemStacks() {
memoryItemHandler.exportDeviceDataToItemStacks();
hardDriveItemHandler.exportDeviceDataToItemStacks();
flashMemoryItemHandler.exportDeviceDataToItemStacks();
cardItemHandler.exportDeviceDataToItemStacks();
for (final DeviceItemStackHandler handler : itemHandlers.values()) {
handler.exportDeviceDataToItemStacks();
}
}
public void exportToItemStack(final ItemStack stack) {
final CompoundNBT items = ItemStackUtils.getOrCreateTileEntityInventoryTag(stack);
items.put(MEMORY_TAG_NAME, memoryItemHandler.serializeNBT());
items.put(HARD_DRIVE_TAG_NAME, hardDriveItemHandler.serializeNBT());
items.put(FLASH_MEMORY_TAG_NAME, flashMemoryItemHandler.serializeNBT());
items.put(CARD_TAG_NAME, cardItemHandler.serializeNBT());
final CompoundNBT tag = ItemStackUtils.getOrCreateTileEntityInventoryTag(stack);
itemHandlers.forEach((deviceType, handler) ->
tag.put(deviceType.getRegistryName().toString(), handler.serializeNBT()));
}
public CompoundNBT serialize() {
final CompoundNBT tag = new CompoundNBT();
tag.put(MEMORY_TAG_NAME, memoryItemHandler.serializeNBT());
tag.put(HARD_DRIVE_TAG_NAME, hardDriveItemHandler.serializeNBT());
tag.put(FLASH_MEMORY_TAG_NAME, flashMemoryItemHandler.serializeNBT());
tag.put(CARD_TAG_NAME, cardItemHandler.serializeNBT());
itemHandlers.forEach((deviceType, handler) ->
tag.put(deviceType.getRegistryName().toString(), handler.serializeNBT()));
return tag;
}
public void deserialize(final CompoundNBT tag) {
memoryItemHandler.deserializeNBT(tag.getCompound(MEMORY_TAG_NAME));
hardDriveItemHandler.deserializeNBT(tag.getCompound(HARD_DRIVE_TAG_NAME));
flashMemoryItemHandler.deserializeNBT(tag.getCompound(FLASH_MEMORY_TAG_NAME));
cardItemHandler.deserializeNBT(tag.getCompound(CARD_TAG_NAME));
itemHandlers.forEach((deviceType, handler) ->
handler.deserializeNBT(tag.getCompound(deviceType.getRegistryName().toString())));
}
///////////////////////////////////////////////////////////////////
@@ -176,12 +173,9 @@ public abstract class AbstractVirtualMachineItemStackHandlers implements Virtual
private final class BusElement extends AbstractDeviceBusElement {
@Override
public Optional<Collection<LazyOptional<DeviceBusElement>>> getNeighbors() {
return Optional.of(Arrays.asList(
LazyOptional.of(memoryItemHandler::getBusElement),
LazyOptional.of(hardDriveItemHandler::getBusElement),
LazyOptional.of(flashMemoryItemHandler::getBusElement),
LazyOptional.of(cardItemHandler::getBusElement)
));
return Optional.of(itemHandlers.values().stream()
.map(h -> LazyOptional.of(() -> (DeviceBusElement) h.getBusElement()))
.collect(Collectors.toList()));
}
}
}