diff --git a/src/main/java/li/cil/oc2/api/bus/device/ItemDevice.java b/src/main/java/li/cil/oc2/api/bus/device/ItemDevice.java new file mode 100644 index 00000000..a1f954e3 --- /dev/null +++ b/src/main/java/li/cil/oc2/api/bus/device/ItemDevice.java @@ -0,0 +1,9 @@ +package li.cil.oc2.api.bus.device; + +import net.minecraft.nbt.CompoundNBT; + +public interface ItemDevice extends Device { + void exportToItemStack(CompoundNBT nbt); + + void importFromItemStack(CompoundNBT nbt); +} diff --git a/src/main/java/li/cil/oc2/api/bus/device/provider/BlockDeviceProvider.java b/src/main/java/li/cil/oc2/api/bus/device/provider/BlockDeviceProvider.java new file mode 100644 index 00000000..6a80e7c3 --- /dev/null +++ b/src/main/java/li/cil/oc2/api/bus/device/provider/BlockDeviceProvider.java @@ -0,0 +1,51 @@ +package li.cil.oc2.api.bus.device.provider; + +import li.cil.oc2.api.bus.device.Device; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.registries.IForgeRegistryEntry; + +/** + * This is used to query for devices given a block face. + *

+ * Implementations may return various device types depending on the query. + *

+ * For identical queries and world state, implementations should return the same device. + * Failing that, implementations should return instances that are equal to each other + * when compared using {@link Object#equals(Object)} and have equal {@link Object#hashCode()}s. + *

+ * This allows avoiding unnecessary re-initialization of devices that have not changed since a + * previous scan. + *

+ * This is also required to avoid device duplication when a device is connected to a + * {@link li.cil.oc2.api.bus.DeviceBus} more than once. An example where this can occur are + * blocks that expose the same device on all sides having connected cabling adjacent to more + * than one face. + *

+ * Providers can be registered via the provider registries, much like blocks and items + * are registered. For example: + *

+ * class YourModInitialization {
+ *     static DeferredRegister<BlockDeviceProvider> BLOCK_DEVICE_PROVIDERS = DeferredRegister.create(BlockDeviceProvider.class, "your_mod_id");
+ *
+ *     static void initialize() {
+ *         BLOCK_DEVICE_PROVIDERS.register("your_block_device_name", YourBlockDeviceProvider::new);
+ *
+ *         BLOCK_DEVICE_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus());
+ *     }
+ * }
+ * 
+ * + * @see li.cil.oc2.api.bus.device.rpc.RPCDevice + * @see li.cil.oc2.api.bus.device.object.ObjectDevice + * @see li.cil.oc2.api.bus.device.vm.VMDevice + * @see BlockDeviceQuery + */ +public interface BlockDeviceProvider extends IForgeRegistryEntry { + /** + * Get a device for the specified query. + * + * @param query the query describing the object to get a {@link Device} for. + * @return a device for the specified query, if available. + */ + LazyOptional getDevice(BlockDeviceQuery query); +} diff --git a/src/main/java/li/cil/oc2/api/bus/device/provider/BlockDeviceQuery.java b/src/main/java/li/cil/oc2/api/bus/device/provider/BlockDeviceQuery.java index ac07c509..827f4acf 100644 --- a/src/main/java/li/cil/oc2/api/bus/device/provider/BlockDeviceQuery.java +++ b/src/main/java/li/cil/oc2/api/bus/device/provider/BlockDeviceQuery.java @@ -8,8 +8,10 @@ import javax.annotation.Nullable; /** * Device query for a block in the world. + * + * @see BlockDeviceProvider */ -public interface BlockDeviceQuery extends DeviceQuery { +public interface BlockDeviceQuery { /** * The world containing the block this query is performed for. * diff --git a/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceProvider.java b/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceProvider.java deleted file mode 100644 index 3e1fcd29..00000000 --- a/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceProvider.java +++ /dev/null @@ -1,55 +0,0 @@ -package li.cil.oc2.api.bus.device.provider; - -import li.cil.oc2.api.bus.device.Device; -import li.cil.oc2.api.bus.device.object.ObjectDevice; -import li.cil.oc2.api.bus.device.rpc.RPCDevice; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.registries.IForgeRegistryEntry; - -/** - * Allows querying for devices given some context. - *

- * See the specializations of {@link DeviceQuery} for possible queries. - *

- *

- * Providers can be registered via the device provider registry, much like blocks and items - * are registered. For example: - *

- * class YourModInitialization {
- *     static DeferredRegister<DeviceProvider> PROVIDERS = DeferredRegister.create(DeviceProvider.class, "your_mod_id");
- *
- *     static void initialize() {
- *         PROVIDERS.register("your_device_name", YourDeviceProvider::new);
- *
- *         PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus());
- *     }
- * }
- * 
- * - * @see RPCDevice - * @see ObjectDevice - * @see DeviceQuery - * @see BlockDeviceQuery - */ -public interface DeviceProvider extends IForgeRegistryEntry { - /** - * Get a device for the specified query. - * - * @param query the query describing the object to get a {@link Device} for. - * @return a device for the specified query, if available. - */ - LazyOptional getDevice(DeviceQuery query); -} diff --git a/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceQuery.java b/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceQuery.java deleted file mode 100644 index 4de1148e..00000000 --- a/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceQuery.java +++ /dev/null @@ -1,10 +0,0 @@ -package li.cil.oc2.api.bus.device.provider; - -/** - * Base interface for all queries to {@link DeviceProvider}s. - * - * @see DeviceProvider - * @see BlockDeviceQuery - */ -public interface DeviceQuery { -} diff --git a/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceProvider.java b/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceProvider.java new file mode 100644 index 00000000..9a30a4a1 --- /dev/null +++ b/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceProvider.java @@ -0,0 +1,48 @@ +package li.cil.oc2.api.bus.device.provider; + +import li.cil.oc2.api.bus.device.Device; +import li.cil.oc2.api.bus.device.ItemDevice; +import net.minecraftforge.registries.IForgeRegistryEntry; + +import java.util.Optional; + +/** + * This is used to query for devices given an item stack. + *

+ * Implementations may return various device types depending on the query. + *

+ * For identical queries, implementations should return the same device. Failing that, + * implementations should return instances that are equal to each other when compared + * using {@link Object#equals(Object)} and have equal {@link Object#hashCode()}s. + *

+ * This allows avoiding unnecessary re-initialization of devices that have not changed since a + * previous scan. + *

+ * Providers can be registered via the provider registries, much like blocks and items + * are registered. For example: + *

+ * class YourModInitialization {
+ *     static DeferredRegister<ItemDeviceProvider> ITEM_DEVICE_PROVIDERS = DeferredRegister.create(ItemDeviceProvider.class, "your_mod_id");
+ *
+ *     static void initialize() {
+ *         ITEM_DEVICE_PROVIDERS.register("your_item_device_name", YourItemDeviceProvider::new);
+ *
+ *         ITEM_DEVICE_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus());
+ *     }
+ * }
+ * 
+ * + * @see li.cil.oc2.api.bus.device.rpc.RPCDevice + * @see li.cil.oc2.api.bus.device.object.ObjectDevice + * @see li.cil.oc2.api.bus.device.vm.VMDevice + * @see ItemDeviceQuery + */ +public interface ItemDeviceProvider extends IForgeRegistryEntry { + /** + * Get a device for the specified query. + * + * @param query the query describing the object to get a {@link Device} for. + * @return a device for the specified query, if available. + */ + Optional getDevice(ItemDeviceQuery query); +} diff --git a/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceQuery.java b/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceQuery.java index 7d083e7c..c29f873d 100644 --- a/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceQuery.java +++ b/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceQuery.java @@ -2,6 +2,16 @@ package li.cil.oc2.api.bus.device.provider; import net.minecraft.item.ItemStack; -public interface ItemDeviceQuery extends DeviceQuery { +/** + * Device query for an item stack. + * + * @see ItemDeviceProvider + */ +public interface ItemDeviceQuery { + /** + * The item stack this query is performed for. + * + * @return the item stack to get a device for. + */ ItemStack getItemStack(); } diff --git a/src/main/java/li/cil/oc2/api/bus/device/rpc/RPCDevice.java b/src/main/java/li/cil/oc2/api/bus/device/rpc/RPCDevice.java index 81392d61..2cfbbfb3 100644 --- a/src/main/java/li/cil/oc2/api/bus/device/rpc/RPCDevice.java +++ b/src/main/java/li/cil/oc2/api/bus/device/rpc/RPCDevice.java @@ -2,7 +2,6 @@ package li.cil.oc2.api.bus.device.rpc; import li.cil.oc2.api.bus.device.Device; import li.cil.oc2.api.bus.device.object.ObjectDevice; -import li.cil.oc2.api.bus.device.provider.DeviceProvider; import java.util.List; @@ -20,7 +19,8 @@ import java.util.List; * the {@link ObjectDevice} class. * * @see ObjectDevice - * @see DeviceProvider + * @see li.cil.oc2.api.bus.device.provider.BlockDeviceProvider + * @see li.cil.oc2.api.bus.device.provider.ItemDeviceProvider */ public interface RPCDevice extends Device { /** diff --git a/src/main/java/li/cil/oc2/api/bus/device/vm/VMDevice.java b/src/main/java/li/cil/oc2/api/bus/device/vm/VMDevice.java index e054b516..41f5c1bf 100644 --- a/src/main/java/li/cil/oc2/api/bus/device/vm/VMDevice.java +++ b/src/main/java/li/cil/oc2/api/bus/device/vm/VMDevice.java @@ -17,6 +17,8 @@ import li.cil.sedna.api.device.MemoryMappedDevice; * for releasing unmanaged resources acquired in {@link #load(VMContext)}. * * @see VMDeviceLifecycleListener + * @see li.cil.oc2.api.bus.device.provider.BlockDeviceProvider + * @see li.cil.oc2.api.bus.device.provider.ItemDeviceProvider */ public interface VMDevice extends Device { /** diff --git a/src/main/java/li/cil/oc2/common/block/entity/AbstractTileEntity.java b/src/main/java/li/cil/oc2/common/block/entity/AbstractTileEntity.java index 84118705..8ff44bbf 100644 --- a/src/main/java/li/cil/oc2/common/block/entity/AbstractTileEntity.java +++ b/src/main/java/li/cil/oc2/common/block/entity/AbstractTileEntity.java @@ -20,6 +20,8 @@ public abstract class AbstractTileEntity extends TileEntity { super(tileEntityType); } + /////////////////////////////////////////////////////////////////// + @NotNull @Override public LazyOptional getCapability(@NotNull final Capability capability, @Nullable final Direction side) { diff --git a/src/main/java/li/cil/oc2/common/block/entity/BusCableTileEntity.java b/src/main/java/li/cil/oc2/common/block/entity/BusCableTileEntity.java index c771b306..64dc15bc 100644 --- a/src/main/java/li/cil/oc2/common/block/entity/BusCableTileEntity.java +++ b/src/main/java/li/cil/oc2/common/block/entity/BusCableTileEntity.java @@ -27,6 +27,8 @@ public class BusCableTileEntity extends AbstractTileEntity { setCapabilityIfAbsent(Capabilities.DEVICE_BUS_ELEMENT_CAPABILITY, busElement); } + /////////////////////////////////////////////////////////////////// + public void handleNeighborChanged(final BlockPos pos) { busElement.handleNeighborChanged(pos); } diff --git a/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java b/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java index 18e15680..e7d01e50 100644 --- a/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java +++ b/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java @@ -3,7 +3,6 @@ package li.cil.oc2.common.block.entity; import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue; import li.cil.ceres.api.Serialized; import li.cil.oc2.Constants; -import li.cil.oc2.api.API; import li.cil.oc2.api.bus.DeviceBusElement; import li.cil.oc2.api.bus.device.Device; import li.cil.oc2.api.bus.device.vm.VMContext; @@ -20,10 +19,7 @@ import li.cil.oc2.common.network.message.ComputerBusStateMessage; import li.cil.oc2.common.network.message.ComputerRunStateMessage; import li.cil.oc2.common.network.message.TerminalBlockOutputMessage; import li.cil.oc2.common.serialization.NBTSerialization; -import li.cil.oc2.common.util.HorizontalBlockUtils; -import li.cil.oc2.common.util.NBTTagIds; -import li.cil.oc2.common.util.NBTUtils; -import li.cil.oc2.common.util.ServerScheduler; +import li.cil.oc2.common.util.*; import li.cil.oc2.common.vm.Terminal; import li.cil.oc2.common.vm.VirtualMachine; import li.cil.oc2.common.vm.VirtualMachineRunner; @@ -128,9 +124,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic itemHandler.setStackInSlot(2, new ItemStack(Items.RAM_8M_ITEM.get())); final ItemStack hdd = new ItemStack(Items.HDD_ITEM.get()); - final CompoundNBT hddInfo = new CompoundNBT(); - hddInfo.putString(Constants.HDD_BASE_NBT_TAG_NAME, "linux"); - hdd.setTagInfo(API.MOD_ID, hddInfo); + ItemStackUtils.getOrCreateModDataTag(hdd).putString(Constants.HDD_BASE_NBT_TAG_NAME, "linux"); itemHandler.setStackInSlot(4, hdd); } diff --git a/src/main/java/li/cil/oc2/common/block/entity/RedstoneInterfaceTileEntity.java b/src/main/java/li/cil/oc2/common/block/entity/RedstoneInterfaceTileEntity.java index 5fdec17d..378cf641 100644 --- a/src/main/java/li/cil/oc2/common/block/entity/RedstoneInterfaceTileEntity.java +++ b/src/main/java/li/cil/oc2/common/block/entity/RedstoneInterfaceTileEntity.java @@ -39,6 +39,8 @@ public class RedstoneInterfaceTileEntity extends TileEntity implements NamedDevi super(TileEntities.REDSTONE_INTERFACE_TILE_ENTITY.get()); } + /////////////////////////////////////////////////////////////////// + @Override public CompoundNBT write(CompoundNBT compound) { compound = super.write(compound); diff --git a/src/main/java/li/cil/oc2/common/bus/AbstractDeviceBusController.java b/src/main/java/li/cil/oc2/common/bus/AbstractDeviceBusController.java index 04188fff..b5078c17 100644 --- a/src/main/java/li/cil/oc2/common/bus/AbstractDeviceBusController.java +++ b/src/main/java/li/cil/oc2/common/bus/AbstractDeviceBusController.java @@ -42,6 +42,8 @@ public abstract class AbstractDeviceBusController implements DeviceBusController this.root = root; } + /////////////////////////////////////////////////////////////////// + public void dispose() { for (final DeviceBusElement element : elements) { element.removeController(this); diff --git a/src/main/java/li/cil/oc2/common/bus/AbstractGroupingBlockDeviceBusElement.java b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingBlockDeviceBusElement.java new file mode 100644 index 00000000..8a573ace --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingBlockDeviceBusElement.java @@ -0,0 +1,10 @@ +package li.cil.oc2.common.bus; + +import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider; +import li.cil.oc2.common.bus.device.BlockDeviceInfo; + +public abstract class AbstractGroupingBlockDeviceBusElement extends AbstractGroupingDeviceBusElement { + public AbstractGroupingBlockDeviceBusElement(final int groupCount) { + super(groupCount); + } +} diff --git a/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java index cdfab82c..85c684f4 100644 --- a/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java +++ b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java @@ -1,55 +1,58 @@ package li.cil.oc2.common.bus; import li.cil.oc2.api.bus.device.Device; -import li.cil.oc2.common.bus.device.DeviceInfo; +import li.cil.oc2.common.bus.device.AbstractDeviceInfo; +import li.cil.oc2.common.util.ItemDeviceUtils; import li.cil.oc2.common.util.NBTTagIds; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; -import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.registries.IForgeRegistryEntry; import java.util.*; import java.util.stream.Collectors; -public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBusElement implements INBTSerializable { - private static final String DEVICE_ID_NBT_TAG_NAME = "deviceId"; - private static final String DEVICE_DATA_NBT_TAG_NAME = "deviceData"; +public abstract class AbstractGroupingDeviceBusElement, TDeviceInfo extends AbstractDeviceInfo> extends AbstractDeviceBusElement implements INBTSerializable { + private static final String GROUP_ID_NBT_TAG_NAME = "groupId"; + private static final String GROUP_DATA_NBT_TAG_NAME = "groupData"; /////////////////////////////////////////////////////////////////// protected final int groupCount; - protected final ArrayList> devicesByGroup; + protected final ArrayList> groups; /////////////////////////////////////////////////////////////////// - protected final UUID[] deviceIds; - protected final CompoundNBT[] deviceData; + protected final UUID[] groupIds; + protected final CompoundNBT[] groupData; /////////////////////////////////////////////////////////////////// protected AbstractGroupingDeviceBusElement(final int groupCount) { this.groupCount = groupCount; - this.devicesByGroup = new ArrayList<>(groupCount); - this.deviceIds = new UUID[groupCount]; - this.deviceData = new CompoundNBT[groupCount]; + this.groups = new ArrayList<>(groupCount); + this.groupIds = new UUID[groupCount]; + this.groupData = new CompoundNBT[groupCount]; for (int i = 0; i < groupCount; i++) { - devicesByGroup.add(new HashSet<>()); - deviceIds[i] = UUID.randomUUID(); - deviceData[i] = new CompoundNBT(); + groups.add(new HashSet<>()); + groupIds[i] = UUID.randomUUID(); + groupData[i] = new CompoundNBT(); } } + /////////////////////////////////////////////////////////////////// + @Override public ListNBT serializeNBT() { - serializeDevices(); - final ListNBT nbt = new ListNBT(); for (int i = 0; i < groupCount; i++) { + serializeDevices(i); + final CompoundNBT sideNbt = new CompoundNBT(); - sideNbt.putUniqueId(DEVICE_ID_NBT_TAG_NAME, deviceIds[i]); - sideNbt.put(DEVICE_DATA_NBT_TAG_NAME, deviceData[i]); + sideNbt.putUniqueId(GROUP_ID_NBT_TAG_NAME, groupIds[i]); + sideNbt.put(GROUP_DATA_NBT_TAG_NAME, groupData[i]); nbt.add(sideNbt); } @@ -62,11 +65,11 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus for (int i = 0; i < count; i++) { final CompoundNBT sideNbt = nbt.getCompound(i); - if (sideNbt.hasUniqueId(DEVICE_ID_NBT_TAG_NAME)) { - deviceIds[i] = sideNbt.getUniqueId(DEVICE_ID_NBT_TAG_NAME); + if (sideNbt.hasUniqueId(GROUP_ID_NBT_TAG_NAME)) { + groupIds[i] = sideNbt.getUniqueId(GROUP_ID_NBT_TAG_NAME); } - if (sideNbt.contains(DEVICE_DATA_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { - deviceData[i] = sideNbt.getCompound(DEVICE_DATA_NBT_TAG_NAME); + if (sideNbt.contains(GROUP_DATA_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { + groupData[i] = sideNbt.getCompound(GROUP_DATA_NBT_TAG_NAME); } } } @@ -74,10 +77,10 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus @Override public Optional getDeviceIdentifier(final Device device) { for (int i = 0; i < groupCount; i++) { - final HashSet group = devicesByGroup.get(i); - for (final DeviceInfo deviceInfo : group) { + final HashSet group = groups.get(i); + for (final TDeviceInfo deviceInfo : group) { if (Objects.equals(device, deviceInfo.device)) { - return Optional.of(deviceIds[i]); + return Optional.of(groupIds[i]); } } } @@ -86,29 +89,29 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus /////////////////////////////////////////////////////////////////// - protected void setDevicesForGroup(final int index, final HashSet newDevices) { - final HashSet oldDevices = devicesByGroup.get(index); + protected final void setDevicesForGroup(final int index, final Set newDevices) { + final HashSet oldDevices = groups.get(index); if (Objects.equals(newDevices, oldDevices)) { return; } - final HashSet removedDevices = new HashSet<>(oldDevices); + final HashSet removedDevices = new HashSet<>(oldDevices); removedDevices.removeAll(newDevices); devices.removeAll(removedDevices.stream().map(info -> info.device).collect(Collectors.toList())); - final HashSet addedDevices = new HashSet<>(newDevices); + final HashSet addedDevices = new HashSet<>(newDevices); addedDevices.removeAll(oldDevices); devices.addAll(addedDevices.stream().map(info -> info.device).collect(Collectors.toList())); oldDevices.removeAll(removedDevices); oldDevices.addAll(newDevices); - final CompoundNBT devicesNbt = deviceData[index]; - for (final DeviceInfo deviceInfo : removedDevices) { - getSerializationKey(deviceInfo).ifPresent(devicesNbt::remove); + final CompoundNBT devicesNbt = groupData[index]; + for (final TDeviceInfo deviceInfo : removedDevices) { + ItemDeviceUtils.getItemDeviceDataKey(deviceInfo.provider).ifPresent(devicesNbt::remove); } - for (final DeviceInfo deviceInfo : addedDevices) { - getSerializationKey(deviceInfo).ifPresent(key -> { + for (final TDeviceInfo deviceInfo : addedDevices) { + ItemDeviceUtils.getItemDeviceDataKey(deviceInfo.provider).ifPresent(key -> { if (devicesNbt.contains(key, NBTTagIds.TAG_COMPOUND)) { deviceInfo.device.deserializeNBT(devicesNbt.getCompound(key)); } @@ -120,27 +123,17 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus /////////////////////////////////////////////////////////////////// - private void serializeDevices() { - for (int i = 0; i < groupCount; i++) { - final CompoundNBT devicesNbt = new CompoundNBT(); - for (final DeviceInfo deviceInfo : devicesByGroup.get(i)) { - getSerializationKey(deviceInfo).ifPresent(key -> { - final CompoundNBT deviceNbt = deviceInfo.device.serializeNBT(); - if (!deviceNbt.isEmpty()) { - devicesNbt.put(key, deviceNbt); - } - }); - } - deviceData[i] = devicesNbt; - } - } - - private static Optional getSerializationKey(final DeviceInfo info) { - final ResourceLocation providerName = info.provider.getRegistryName(); - if (providerName == null) { - return Optional.empty(); + private void serializeDevices(final int index) { + final CompoundNBT devicesNbt = new CompoundNBT(); + for (final TDeviceInfo deviceInfo : groups.get(index)) { + ItemDeviceUtils.getItemDeviceDataKey(deviceInfo.provider).ifPresent(key -> { + final CompoundNBT deviceNbt = deviceInfo.device.serializeNBT(); + if (!deviceNbt.isEmpty()) { + devicesNbt.put(key, deviceNbt); + } + }); } - return Optional.of(providerName.toString()); + groupData[index] = devicesNbt; } } diff --git a/src/main/java/li/cil/oc2/common/bus/AbstractGroupingItemDeviceBusElement.java b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingItemDeviceBusElement.java new file mode 100644 index 00000000..b11ee9c3 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingItemDeviceBusElement.java @@ -0,0 +1,10 @@ +package li.cil.oc2.common.bus; + +import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider; +import li.cil.oc2.common.bus.device.ItemDeviceInfo; + +public abstract class AbstractGroupingItemDeviceBusElement extends AbstractGroupingDeviceBusElement { + public AbstractGroupingItemDeviceBusElement(final int groupCount) { + super(groupCount); + } +} diff --git a/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java b/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java index f52016af..4b8b4570 100644 --- a/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java +++ b/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java @@ -1,33 +1,64 @@ package li.cil.oc2.common.bus; -import li.cil.oc2.common.bus.device.DeviceInfo; import li.cil.oc2.common.bus.device.Devices; +import li.cil.oc2.common.bus.device.ItemDeviceInfo; +import li.cil.oc2.common.util.ItemDeviceUtils; +import li.cil.oc2.common.util.NBTTagIds; import net.minecraft.item.ItemStack; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.ItemStackHandler; +import net.minecraft.nbt.CompoundNBT; +import java.util.Collections; import java.util.HashSet; -public class ItemHandlerDeviceBusElement extends AbstractGroupingDeviceBusElement { - private final ItemStackHandler handler; +public class ItemHandlerDeviceBusElement extends AbstractGroupingItemDeviceBusElement { + public ItemHandlerDeviceBusElement(final int slotCount) { + super(slotCount); + } /////////////////////////////////////////////////////////////////// - public ItemHandlerDeviceBusElement(final ItemStackHandler handler) { - super(handler.getSlots()); - this.handler = handler; + public void updateDevices(final int slot, final ItemStack stack) { + if (!stack.isEmpty()) { + final HashSet newDevices = new HashSet<>(Devices.getDevices(stack)); + importDeviceDataFromItemStack(stack, newDevices); + setDevicesForGroup(slot, newDevices); + } else { + setDevicesForGroup(slot, Collections.emptySet()); + } } - public void handleSlotChanged(final int slot) { - final HashSet newDevices = new HashSet<>(); - final ItemStack stack = handler.getStackInSlot(slot); + public void handleBeforeItemRemoved(final int slot, final ItemStack stack) { if (!stack.isEmpty()) { - for (final LazyOptional info : Devices.getDevices(stack)) { - info.ifPresent(newDevices::add); - info.addListener(unused -> handleSlotChanged(slot)); - } + exportDeviceDataToItemStack(slot, stack); + } + } + + /////////////////////////////////////////////////////////////////// + + private void exportDeviceDataToItemStack(final int slot, final ItemStack stack) { + final CompoundNBT exportedNbt = new CompoundNBT(); + for (final ItemDeviceInfo info : groups.get(slot)) { + ItemDeviceUtils.getItemDeviceDataKey(info.provider).ifPresent(key -> { + final CompoundNBT deviceNbt = new CompoundNBT(); + info.device.exportToItemStack(deviceNbt); + if (!deviceNbt.isEmpty()) { + exportedNbt.put(key, deviceNbt); + } + }); } - setDevicesForGroup(slot, newDevices); + ItemDeviceUtils.setItemDeviceData(stack, exportedNbt); + } + + private void importDeviceDataFromItemStack(final ItemStack stack, final HashSet devices) { + ItemDeviceUtils.getItemDeviceData(stack).ifPresent(exportedNbt -> { + for (final ItemDeviceInfo info : devices) { + ItemDeviceUtils.getItemDeviceDataKey(info.provider).ifPresent(key -> { + if (exportedNbt.contains(key, NBTTagIds.TAG_COMPOUND)) { + info.device.importFromItemStack(exportedNbt.getCompound(key)); + } + }); + } + }); } } diff --git a/src/main/java/li/cil/oc2/common/bus/RPCAdapter.java b/src/main/java/li/cil/oc2/common/bus/RPCAdapter.java index e1360c5a..557cd0ee 100644 --- a/src/main/java/li/cil/oc2/common/bus/RPCAdapter.java +++ b/src/main/java/li/cil/oc2/common/bus/RPCAdapter.java @@ -71,6 +71,8 @@ public final class RPCAdapter implements Steppable { .create(); } + /////////////////////////////////////////////////////////////////// + public void reset() { transmitBuffer.clear(); receiveBuffer = null; diff --git a/src/main/java/li/cil/oc2/common/bus/TileEntityDeviceBusElement.java b/src/main/java/li/cil/oc2/common/bus/TileEntityDeviceBusElement.java index 8c6b7211..15fc78bd 100644 --- a/src/main/java/li/cil/oc2/common/bus/TileEntityDeviceBusElement.java +++ b/src/main/java/li/cil/oc2/common/bus/TileEntityDeviceBusElement.java @@ -2,7 +2,7 @@ package li.cil.oc2.common.bus; import li.cil.oc2.api.bus.DeviceBus; import li.cil.oc2.api.bus.DeviceBusElement; -import li.cil.oc2.common.bus.device.DeviceInfo; +import li.cil.oc2.common.bus.device.BlockDeviceInfo; import li.cil.oc2.common.bus.device.Devices; import li.cil.oc2.common.capabilities.Capabilities; import li.cil.oc2.common.util.ServerScheduler; @@ -21,7 +21,7 @@ import java.util.Optional; import static java.util.Objects.requireNonNull; -public class TileEntityDeviceBusElement extends AbstractGroupingDeviceBusElement { +public class TileEntityDeviceBusElement extends AbstractGroupingBlockDeviceBusElement { private static final int NEIGHBOR_COUNT = 6; final Direction[] NEIGHBOR_DIRECTIONS = Direction.values(); @@ -36,6 +36,8 @@ public class TileEntityDeviceBusElement extends AbstractGroupingDeviceBusElement this.tileEntity = tileEntity; } + /////////////////////////////////////////////////////////////////// + @Override public Optional>> getNeighbors() { final World world = tileEntity.getWorld(); @@ -80,9 +82,9 @@ public class TileEntityDeviceBusElement extends AbstractGroupingDeviceBusElement final int index = direction.getIndex(); - final HashSet newDevices = new HashSet<>(); + final HashSet newDevices = new HashSet<>(); if (canConnectToSide(direction)) { - for (final LazyOptional deviceInfo : Devices.getDevices(world, pos, direction)) { + for (final LazyOptional deviceInfo : Devices.getDevices(world, pos, direction)) { deviceInfo.ifPresent(newDevices::add); deviceInfo.addListener(unused -> handleNeighborChanged(pos)); } diff --git a/src/main/java/li/cil/oc2/common/bus/device/AbstractDeviceInfo.java b/src/main/java/li/cil/oc2/common/bus/device/AbstractDeviceInfo.java new file mode 100644 index 00000000..4a42fd40 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/AbstractDeviceInfo.java @@ -0,0 +1,33 @@ +package li.cil.oc2.common.bus.device; + +import li.cil.oc2.api.bus.device.Device; +import net.minecraftforge.registries.IForgeRegistryEntry; + +import java.util.Objects; + +public abstract class AbstractDeviceInfo, TDevice extends Device> { + public final TProvider provider; + public final TDevice device; + + /////////////////////////////////////////////////////////////////// + + protected AbstractDeviceInfo(final TProvider provider, final TDevice device) { + this.provider = provider; + this.device = device; + } + + /////////////////////////////////////////////////////////////////// + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final AbstractDeviceInfo that = (AbstractDeviceInfo) o; + return provider.equals(that.provider) && device.equals(that.device); + } + + @Override + public int hashCode() { + return Objects.hash(provider, device); + } +} diff --git a/src/main/java/li/cil/oc2/common/bus/device/AbstractHardDiskDriveDevice.java b/src/main/java/li/cil/oc2/common/bus/device/AbstractHardDiskDriveDevice.java index 90d19ed2..dba26715 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/AbstractHardDiskDriveDevice.java +++ b/src/main/java/li/cil/oc2/common/bus/device/AbstractHardDiskDriveDevice.java @@ -1,7 +1,6 @@ package li.cil.oc2.common.bus.device; import li.cil.oc2.api.bus.device.vm.*; -import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy; import li.cil.oc2.common.serialization.BlobStorage; import li.cil.oc2.common.serialization.NBTSerialization; import li.cil.oc2.common.util.NBTTagIds; @@ -17,7 +16,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.UUID; -public abstract class AbstractHardDiskDriveDevice extends AbstractObjectProxy implements VMDevice, VMDeviceLifecycleListener { +public abstract class AbstractHardDiskDriveDevice extends AbstractItemDevice implements VMDevice, VMDeviceLifecycleListener { private static final String DEVICE_NBT_TAG_NAME = "device"; private static final String ADDRESS_NBT_TAG_NAME = "address"; private static final String INTERRUPT_NBT_TAG_NAME = "interrupt"; @@ -45,6 +44,8 @@ public abstract class AbstractHardDiskDriveDevice extends super(stack); } + /////////////////////////////////////////////////////////////////// + @Override public VMDeviceLoadResult load(final VMContext context) { if (!allocateDevice(context)) { @@ -76,6 +77,20 @@ public abstract class AbstractHardDiskDriveDevice extends } } + @Override + public void exportToItemStack(final CompoundNBT nbt) { + if (blobHandle != null) { + nbt.putUniqueId(BLOB_HANDLE_NBT_TAG_NAME, blobHandle); + } + } + + @Override + public void importFromItemStack(final CompoundNBT nbt) { + if (nbt.hasUniqueId(BLOB_HANDLE_NBT_TAG_NAME)) { + blobHandle = nbt.getUniqueId(BLOB_HANDLE_NBT_TAG_NAME); + } + } + @Override public CompoundNBT serializeNBT() { final CompoundNBT nbt = new CompoundNBT(); diff --git a/src/main/java/li/cil/oc2/common/bus/device/AbstractItemDevice.java b/src/main/java/li/cil/oc2/common/bus/device/AbstractItemDevice.java new file mode 100644 index 00000000..92a0a8d3 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/AbstractItemDevice.java @@ -0,0 +1,21 @@ +package li.cil.oc2.common.bus.device; + +import li.cil.oc2.api.bus.device.ItemDevice; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; + +public abstract class AbstractItemDevice extends AbstractObjectDevice implements ItemDevice { + public AbstractItemDevice(final ItemStack value) { + super(value); + } + + /////////////////////////////////////////////////////////////////// + + @Override + public void exportToItemStack(final CompoundNBT nbt) { + } + + @Override + public void importFromItemStack(final CompoundNBT nbt) { + } +} diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractObjectProxy.java b/src/main/java/li/cil/oc2/common/bus/device/AbstractObjectDevice.java similarity index 64% rename from src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractObjectProxy.java rename to src/main/java/li/cil/oc2/common/bus/device/AbstractObjectDevice.java index 38c3a704..8a72ca68 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractObjectProxy.java +++ b/src/main/java/li/cil/oc2/common/bus/device/AbstractObjectDevice.java @@ -1,22 +1,24 @@ -package li.cil.oc2.common.bus.device.provider.util; +package li.cil.oc2.common.bus.device; import javax.annotation.Nullable; import java.util.Objects; -public abstract class AbstractObjectProxy { +public abstract class AbstractObjectDevice { protected final T value; /////////////////////////////////////////////////////////////////// - public AbstractObjectProxy(final T value) { + public AbstractObjectDevice(final T value) { this.value = value; } + /////////////////////////////////////////////////////////////////// + @Override public boolean equals(@Nullable final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final AbstractObjectProxy that = (AbstractObjectProxy) o; + final AbstractObjectDevice that = (AbstractObjectDevice) o; return value.equals(that.value); } diff --git a/src/main/java/li/cil/oc2/common/bus/device/BlockDeviceInfo.java b/src/main/java/li/cil/oc2/common/bus/device/BlockDeviceInfo.java new file mode 100644 index 00000000..269a4364 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/BlockDeviceInfo.java @@ -0,0 +1,10 @@ +package li.cil.oc2.common.bus.device; + +import li.cil.oc2.api.bus.device.Device; +import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider; + +public final class BlockDeviceInfo extends AbstractDeviceInfo { + public BlockDeviceInfo(final BlockDeviceProvider blockDeviceProvider, final Device device) { + super(blockDeviceProvider, device); + } +} diff --git a/src/main/java/li/cil/oc2/common/bus/device/DeviceInfo.java b/src/main/java/li/cil/oc2/common/bus/device/DeviceInfo.java deleted file mode 100644 index 3450df01..00000000 --- a/src/main/java/li/cil/oc2/common/bus/device/DeviceInfo.java +++ /dev/null @@ -1,29 +0,0 @@ -package li.cil.oc2.common.bus.device; - -import li.cil.oc2.api.bus.device.Device; -import li.cil.oc2.api.bus.device.provider.DeviceProvider; - -import java.util.Objects; - -public final class DeviceInfo { - public final Device device; - public final DeviceProvider provider; - - public DeviceInfo(final Device device, final DeviceProvider provider) { - this.device = device; - this.provider = provider; - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final DeviceInfo that = (DeviceInfo) o; - return device.equals(that.device) && provider.equals(that.provider); - } - - @Override - public int hashCode() { - return Objects.hash(device, provider); - } -} diff --git a/src/main/java/li/cil/oc2/common/bus/device/Devices.java b/src/main/java/li/cil/oc2/common/bus/device/Devices.java index 893d6f09..4f077763 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/Devices.java +++ b/src/main/java/li/cil/oc2/common/bus/device/Devices.java @@ -1,9 +1,10 @@ package li.cil.oc2.common.bus.device; import li.cil.oc2.api.bus.device.Device; +import li.cil.oc2.api.bus.device.ItemDevice; +import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider; import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery; -import li.cil.oc2.api.bus.device.provider.DeviceProvider; -import li.cil.oc2.api.bus.device.provider.DeviceQuery; +import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider; import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery; import li.cil.oc2.common.init.Providers; import net.minecraft.item.ItemStack; @@ -17,9 +18,10 @@ import net.minecraftforge.registries.IForgeRegistry; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Optional; public final class Devices { - public static List> getDevices(final TileEntity tileEntity, final Direction side) { + public static List> getDevices(final TileEntity tileEntity, final Direction side) { final World world = tileEntity.getWorld(); final BlockPos pos = tileEntity.getPos(); @@ -28,21 +30,23 @@ public final class Devices { return getDevices(world, pos, side); } - public static List> getDevices(final World world, final BlockPos pos, final Direction side) { + public static List> getDevices(final World world, final BlockPos pos, final Direction side) { return getDevices(new BlockQuery(world, pos, side)); } - public static List> getDevices(final ItemStack stack) { + public static List getDevices(final ItemStack stack) { return getDevices(new ItemQuery(stack)); } - public static List> getDevices(final DeviceQuery query) { - final IForgeRegistry providers = Providers.PROVIDERS_REGISTRY.get(); - final ArrayList> devices = new ArrayList<>(); - for (final DeviceProvider provider : providers.getValues()) { + /////////////////////////////////////////////////////////////////// + + private static List> getDevices(final BlockQuery query) { + final IForgeRegistry registry = Providers.BLOCK_DEVICE_PROVIDER_REGISTRY.get(); + final ArrayList> devices = new ArrayList<>(); + for (final BlockDeviceProvider provider : registry.getValues()) { final LazyOptional device = provider.getDevice(query); if (device.isPresent()) { - final LazyOptional info = device.lazyMap(d -> new DeviceInfo(d, provider)); + final LazyOptional info = device.lazyMap(d -> new BlockDeviceInfo(provider, d)); device.addListener(unused -> info.invalidate()); devices.add(info); } @@ -50,6 +54,16 @@ public final class Devices { return devices; } + private static List getDevices(final ItemQuery query) { + final IForgeRegistry registry = Providers.ITEM_DEVICE_PROVIDER_REGISTRY.get(); + final ArrayList devices = new ArrayList<>(); + for (final ItemDeviceProvider provider : registry.getValues()) { + final Optional device = provider.getDevice(query); + device.ifPresent(d -> devices.add(new ItemDeviceInfo(provider, d))); + } + return devices; + } + /////////////////////////////////////////////////////////////////// private static class BlockQuery implements BlockDeviceQuery { diff --git a/src/main/java/li/cil/oc2/common/bus/device/HardDiskDriveDevice.java b/src/main/java/li/cil/oc2/common/bus/device/HardDiskDriveDevice.java index 4426acaa..9013f784 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/HardDiskDriveDevice.java +++ b/src/main/java/li/cil/oc2/common/bus/device/HardDiskDriveDevice.java @@ -11,12 +11,16 @@ public final class HardDiskDriveDevice extends AbstractHardDiskDriveDevice { + public ItemDeviceInfo(final ItemDeviceProvider itemDeviceProvider, final ItemDevice device) { + super(itemDeviceProvider, device); + } +} diff --git a/src/main/java/li/cil/oc2/common/bus/device/MemoryDevice.java b/src/main/java/li/cil/oc2/common/bus/device/MemoryDevice.java index 50b31e3a..62e7c187 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/MemoryDevice.java +++ b/src/main/java/li/cil/oc2/common/bus/device/MemoryDevice.java @@ -2,7 +2,6 @@ package li.cil.oc2.common.bus.device; import li.cil.oc2.Constants; import li.cil.oc2.api.bus.device.vm.*; -import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy; import li.cil.oc2.common.serialization.BlobStorage; import li.cil.oc2.common.util.NBTTagIds; import li.cil.sedna.api.device.PhysicalMemory; @@ -15,7 +14,7 @@ import net.minecraft.nbt.CompoundNBT; import java.util.OptionalLong; import java.util.UUID; -public final class MemoryDevice extends AbstractObjectProxy implements VMDevice, VMDeviceLifecycleListener { +public final class MemoryDevice extends AbstractItemDevice implements VMDevice, VMDeviceLifecycleListener { private static final String BLOB_HANDLE_NBT_TAG_NAME = "blob"; private static final String ADDRESS_NBT_TAG_NAME = "address"; @@ -37,6 +36,8 @@ public final class MemoryDevice extends AbstractObjectProxy implement super(value); } + /////////////////////////////////////////////////////////////////// + @Override public VMDeviceLoadResult load(final VMContext context) { if (!allocateDevice(context)) { diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/BlockDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/BlockDeviceProvider.java deleted file mode 100644 index 6a516963..00000000 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/BlockDeviceProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -package li.cil.oc2.common.bus.device.provider; - -import li.cil.oc2.api.bus.device.Device; -import li.cil.oc2.api.bus.device.object.Callbacks; -import li.cil.oc2.api.bus.device.object.ObjectDevice; -import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery; -import li.cil.oc2.api.bus.device.provider.DeviceQuery; -import li.cil.oc2.common.bus.device.provider.util.AbstractDeviceProvider; -import li.cil.oc2.common.util.WorldUtils; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraftforge.common.util.LazyOptional; - -public final class BlockDeviceProvider extends AbstractDeviceProvider { - @Override - public LazyOptional getDevice(final DeviceQuery query) { - if (!(query instanceof BlockDeviceQuery)) { - return LazyOptional.empty(); - } - - final BlockDeviceQuery blockQuery = (BlockDeviceQuery) query; - final BlockState blockState = blockQuery.getWorld().getBlockState(blockQuery.getQueryPosition()); - if (blockState.getBlock().isAir(blockState, blockQuery.getWorld(), blockQuery.getQueryPosition())) { - return LazyOptional.empty(); - } - - final Block block = blockState.getBlock(); - if (!Callbacks.hasMethods(block)) { - return LazyOptional.empty(); - } - - final String typeName = WorldUtils.getBlockName(blockQuery.getWorld(), blockQuery.getQueryPosition()); - return LazyOptional.of(() -> new ObjectDevice(block, typeName)); - } -} diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/BlockStateDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/BlockStateDeviceProvider.java new file mode 100644 index 00000000..924444fa --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/BlockStateDeviceProvider.java @@ -0,0 +1,35 @@ +package li.cil.oc2.common.bus.device.provider; + +import li.cil.oc2.api.bus.device.Device; +import li.cil.oc2.api.bus.device.object.Callbacks; +import li.cil.oc2.api.bus.device.object.ObjectDevice; +import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery; +import li.cil.oc2.common.bus.device.provider.util.AbstractBlockDeviceProvider; +import li.cil.oc2.common.util.WorldUtils; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.util.LazyOptional; + +public final class BlockStateDeviceProvider extends AbstractBlockDeviceProvider { + @Override + public LazyOptional getDevice(final BlockDeviceQuery query) { + final World world = query.getWorld(); + final BlockPos position = query.getQueryPosition(); + + final BlockState blockState = world.getBlockState(position); + final Block block = blockState.getBlock(); + + if (block.isAir(blockState, world, position)) { + return LazyOptional.empty(); + } + + if (!Callbacks.hasMethods(block)) { + return LazyOptional.empty(); + } + + final String typeName = WorldUtils.getBlockName(world, position); + return LazyOptional.of(() -> new ObjectDevice(block, typeName)); + } +} diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/EnergyStorageDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/EnergyStorageBlockDeviceProvider.java similarity index 74% rename from src/main/java/li/cil/oc2/common/bus/device/provider/EnergyStorageDeviceProvider.java rename to src/main/java/li/cil/oc2/common/bus/device/provider/EnergyStorageBlockDeviceProvider.java index bbb1d710..2d55ed55 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/EnergyStorageDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/EnergyStorageBlockDeviceProvider.java @@ -4,31 +4,32 @@ import li.cil.oc2.api.bus.device.Device; 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.provider.BlockDeviceQuery; -import li.cil.oc2.common.bus.device.provider.util.AbstractCapabilityAnyTileEntityDeviceProvider; -import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy; +import li.cil.oc2.common.bus.device.provider.util.AbstractTileEntityCapabilityDeviceProvider; +import li.cil.oc2.common.bus.device.AbstractObjectDevice; import li.cil.oc2.common.capabilities.Capabilities; +import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.IEnergyStorage; -public final class EnergyStorageDeviceProvider extends AbstractCapabilityAnyTileEntityDeviceProvider { +public final class EnergyStorageBlockDeviceProvider extends AbstractTileEntityCapabilityDeviceProvider { private static final String ENERGY_STORAGE_TYPE_NAME = "energyStorage"; /////////////////////////////////////////////////////////////////// - public EnergyStorageDeviceProvider() { + public EnergyStorageBlockDeviceProvider() { super(() -> Capabilities.ENERGY_STORAGE_CAPABILITY); } /////////////////////////////////////////////////////////////////// @Override - protected LazyOptional getDevice(final BlockDeviceQuery query, final IEnergyStorage value) { + protected LazyOptional getBlockDevice(final BlockDeviceQuery query, final IEnergyStorage value) { return LazyOptional.of(() -> new ObjectDevice(new EnergyStorageDevice(value), ENERGY_STORAGE_TYPE_NAME)); } /////////////////////////////////////////////////////////////////// - public static final class EnergyStorageDevice extends AbstractObjectProxy { + public static final class EnergyStorageDevice extends AbstractObjectDevice { public EnergyStorageDevice(final IEnergyStorage energyStorage) { super(energyStorage); } diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/FluidHandlerDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/FluidHandlerBlockDeviceProvider.java similarity index 74% rename from src/main/java/li/cil/oc2/common/bus/device/provider/FluidHandlerDeviceProvider.java rename to src/main/java/li/cil/oc2/common/bus/device/provider/FluidHandlerBlockDeviceProvider.java index 7a3d7cc7..99128e4f 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/FluidHandlerDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/FluidHandlerBlockDeviceProvider.java @@ -4,32 +4,33 @@ import li.cil.oc2.api.bus.device.Device; 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.provider.BlockDeviceQuery; -import li.cil.oc2.common.bus.device.provider.util.AbstractCapabilityAnyTileEntityDeviceProvider; -import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy; +import li.cil.oc2.common.bus.device.provider.util.AbstractTileEntityCapabilityDeviceProvider; +import li.cil.oc2.common.bus.device.AbstractObjectDevice; import li.cil.oc2.common.capabilities.Capabilities; +import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; -public final class FluidHandlerDeviceProvider extends AbstractCapabilityAnyTileEntityDeviceProvider { +public final class FluidHandlerBlockDeviceProvider extends AbstractTileEntityCapabilityDeviceProvider { private static final String FLUID_HANDLER_TYPE_NAME = "fluidHandler"; /////////////////////////////////////////////////////////////////// - public FluidHandlerDeviceProvider() { + public FluidHandlerBlockDeviceProvider() { super(() -> Capabilities.FLUID_HANDLER_CAPABILITY); } /////////////////////////////////////////////////////////////////// @Override - protected LazyOptional getDevice(final BlockDeviceQuery query, final IFluidHandler value) { + protected LazyOptional getBlockDevice(final BlockDeviceQuery query, final IFluidHandler value) { return LazyOptional.of(() -> new ObjectDevice(new FluidHandlerDevice(value), FLUID_HANDLER_TYPE_NAME)); } /////////////////////////////////////////////////////////////////// - public static final class FluidHandlerDevice extends AbstractObjectProxy { + public static final class FluidHandlerDevice extends AbstractObjectDevice { public FluidHandlerDevice(final IFluidHandler fluidHandler) { super(fluidHandler); } diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/HardDriveItemDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/HardDriveItemDeviceProvider.java index fd559f34..aff7228a 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/HardDriveItemDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/HardDriveItemDeviceProvider.java @@ -2,70 +2,88 @@ package li.cil.oc2.common.bus.device.provider; import li.cil.oc2.Config; import li.cil.oc2.Constants; -import li.cil.oc2.api.API; -import li.cil.oc2.api.bus.device.Device; +import li.cil.oc2.api.bus.device.ItemDevice; import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery; import li.cil.oc2.common.bus.device.HardDiskDriveDevice; import li.cil.oc2.common.bus.device.SparseHardDiskDriveDevice; import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider; import li.cil.oc2.common.init.Items; +import li.cil.oc2.common.util.ItemStackUtils; import li.cil.oc2.common.util.NBTTagIds; import li.cil.sedna.api.device.BlockDevice; import li.cil.sedna.buildroot.Buildroot; import li.cil.sedna.device.block.ByteBufferBlockDevice; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; -import net.minecraftforge.common.util.LazyOptional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import javax.annotation.Nullable; import java.io.IOException; import java.util.Objects; +import java.util.Optional; public final class HardDriveItemDeviceProvider extends AbstractItemDeviceProvider { private static final Logger LOGGER = LogManager.getLogger(); /////////////////////////////////////////////////////////////////// + private static final ByteBufferBlockDevice ROOT_FS; + + static { + ByteBufferBlockDevice rootfs; + try { + rootfs = ByteBufferBlockDevice.createFromStream(Buildroot.getRootFilesystem(), true); + } catch (final IOException e) { + LOGGER.error(e); + rootfs = ByteBufferBlockDevice.create(0, true); + } + ROOT_FS = rootfs; + } + + /////////////////////////////////////////////////////////////////// + public HardDriveItemDeviceProvider() { - super(Items.HDD_ITEM.get()); + super(Items.HDD_ITEM); } /////////////////////////////////////////////////////////////////// @Override - protected LazyOptional getItemDevice(final ItemDeviceQuery query) { + protected Optional getItemDevice(final ItemDeviceQuery query) { final ItemStack stack = query.getItemStack(); - final CompoundNBT info = stack.getChildTag(API.MOD_ID); + final CompoundNBT info = ItemStackUtils.getModDataTag(stack); if (info == null) { - return LazyOptional.empty(); + return Optional.empty(); } final boolean readonly = info.getBoolean(Constants.HDD_READONLY_NBT_TAG_NAME); if (info.contains(Constants.HDD_BASE_NBT_TAG_NAME, NBTTagIds.TAG_STRING)) { final String baseName = info.getString(Constants.HDD_BASE_NBT_TAG_NAME); - BlockDevice base = null; - - // TODO Allow registering additional base file systems? - if (Objects.equals(baseName, "linux")) { - try { - base = ByteBufferBlockDevice.createFromStream(Buildroot.getRootFilesystem(), true); - } catch (final IOException e) { - LOGGER.error(e); - } - } + final BlockDevice base = getBaseBlockDevice(baseName); if (base != null) { - final BlockDevice baseForClosure = base; - return LazyOptional.of(() -> new SparseHardDiskDriveDevice(stack, baseForClosure, readonly)); + return Optional.of(new SparseHardDiskDriveDevice(stack, base, readonly)); } } else if (info.contains(Constants.HDD_SIZE_NBT_TAG_NAME, NBTTagIds.TAG_INT)) { final int size = Math.max(0, Math.min(Config.maxHddSize, info.getInt(Constants.HDD_SIZE_NBT_TAG_NAME))); - return LazyOptional.of(() -> new HardDiskDriveDevice(stack, size, readonly)); + return Optional.of(new HardDiskDriveDevice(stack, size, readonly)); } - return LazyOptional.empty(); + return Optional.empty(); + } + + /////////////////////////////////////////////////////////////////// + + @Nullable + private static BlockDevice getBaseBlockDevice(final String name) { + // TODO Allow registering additional base file systems. + if (Objects.equals(name, "linux")) { + return ROOT_FS; + } + + return null; } } diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/ItemHandlerDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/ItemHandlerBlockDeviceProvider.java similarity index 74% rename from src/main/java/li/cil/oc2/common/bus/device/provider/ItemHandlerDeviceProvider.java rename to src/main/java/li/cil/oc2/common/bus/device/provider/ItemHandlerBlockDeviceProvider.java index ac9fabde..3bd53f6a 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/ItemHandlerDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/ItemHandlerBlockDeviceProvider.java @@ -4,32 +4,33 @@ import li.cil.oc2.api.bus.device.Device; 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.provider.BlockDeviceQuery; -import li.cil.oc2.common.bus.device.provider.util.AbstractCapabilityAnyTileEntityDeviceProvider; -import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy; +import li.cil.oc2.common.bus.device.AbstractObjectDevice; +import li.cil.oc2.common.bus.device.provider.util.AbstractTileEntityCapabilityDeviceProvider; import li.cil.oc2.common.capabilities.Capabilities; import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; -public final class ItemHandlerDeviceProvider extends AbstractCapabilityAnyTileEntityDeviceProvider { +public final class ItemHandlerBlockDeviceProvider extends AbstractTileEntityCapabilityDeviceProvider { private static final String ITEM_HANDLER_TYPE_NAME = "itemHandler"; /////////////////////////////////////////////////////////////////// - public ItemHandlerDeviceProvider() { + public ItemHandlerBlockDeviceProvider() { super(() -> Capabilities.ITEM_HANDLER_CAPABILITY); } /////////////////////////////////////////////////////////////////// @Override - protected LazyOptional getDevice(final BlockDeviceQuery query, final IItemHandler value) { + protected LazyOptional getBlockDevice(final BlockDeviceQuery query, final IItemHandler value) { return LazyOptional.of(() -> new ObjectDevice(new ItemHandlerDevice(value), ITEM_HANDLER_TYPE_NAME)); } /////////////////////////////////////////////////////////////////// - public static final class ItemHandlerDevice extends AbstractObjectProxy { + public static final class ItemHandlerDevice extends AbstractObjectDevice { public ItemHandlerDevice(final IItemHandler itemHandler) { super(itemHandler); } diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/MemoryItemDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/MemoryItemDeviceProvider.java index 63d4ddec..72caa368 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/MemoryItemDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/MemoryItemDeviceProvider.java @@ -1,21 +1,22 @@ package li.cil.oc2.common.bus.device.provider; -import li.cil.oc2.api.bus.device.Device; +import li.cil.oc2.api.bus.device.ItemDevice; import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery; import li.cil.oc2.common.bus.device.MemoryDevice; import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider; import li.cil.oc2.common.init.Items; -import net.minecraftforge.common.util.LazyOptional; + +import java.util.Optional; public final class MemoryItemDeviceProvider extends AbstractItemDeviceProvider { public MemoryItemDeviceProvider() { - super(Items.RAM_8M_ITEM.get()); + super(Items.RAM_8M_ITEM); } /////////////////////////////////////////////////////////////////// @Override - protected LazyOptional getItemDevice(final ItemDeviceQuery query) { - return LazyOptional.of(() -> new MemoryDevice(query.getItemStack())); + protected Optional getItemDevice(final ItemDeviceQuery query) { + return Optional.of(new MemoryDevice(query.getItemStack())); } } diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/TileEntityDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/TileEntityDeviceProvider.java index cea5d476..825f962c 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/TileEntityDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/TileEntityDeviceProvider.java @@ -7,15 +7,12 @@ import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery; import li.cil.oc2.common.bus.device.provider.util.AbstractTileEntityDeviceProvider; import li.cil.oc2.common.util.WorldUtils; import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; import net.minecraftforge.common.util.LazyOptional; public final class TileEntityDeviceProvider extends AbstractTileEntityDeviceProvider { - public TileEntityDeviceProvider() { - super(TileEntity.class); - } - @Override - public LazyOptional getDevice(final BlockDeviceQuery query, final TileEntity tileEntity) { + public LazyOptional getBlockDevice(final BlockDeviceQuery query, final TileEntity tileEntity) { if (Callbacks.hasMethods(tileEntity)) { return LazyOptional.of(() -> { final String typeName = WorldUtils.getBlockName(query.getWorld(), query.getQueryPosition()); diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractBlockDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractBlockDeviceProvider.java new file mode 100644 index 00000000..22fc742a --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractBlockDeviceProvider.java @@ -0,0 +1,7 @@ +package li.cil.oc2.common.bus.device.provider.util; + +import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider; +import net.minecraftforge.registries.ForgeRegistryEntry; + +public abstract class AbstractBlockDeviceProvider extends ForgeRegistryEntry implements BlockDeviceProvider { +} diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractCapabilityAnyTileEntityDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractCapabilityAnyTileEntityDeviceProvider.java deleted file mode 100644 index bde4254b..00000000 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractCapabilityAnyTileEntityDeviceProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package li.cil.oc2.common.bus.device.provider.util; - -import net.minecraft.tileentity.TileEntity; -import net.minecraftforge.common.capabilities.Capability; - -import java.util.function.Supplier; - -public abstract class AbstractCapabilityAnyTileEntityDeviceProvider extends AbstractCapabilityTileEntityDeviceProvider { - public AbstractCapabilityAnyTileEntityDeviceProvider(final Supplier> capabilitySupplier) { - super(TileEntity.class, capabilitySupplier); - } -} diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractDeviceProvider.java deleted file mode 100644 index a9f3c7ac..00000000 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractDeviceProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package li.cil.oc2.common.bus.device.provider.util; - -import li.cil.oc2.api.bus.device.provider.DeviceProvider; -import net.minecraftforge.registries.ForgeRegistryEntry; - -public abstract class AbstractDeviceProvider extends ForgeRegistryEntry implements DeviceProvider { -} diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractItemDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractItemDeviceProvider.java index f30f7aab..b357a7c8 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractItemDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractItemDeviceProvider.java @@ -1,37 +1,45 @@ package li.cil.oc2.common.bus.device.provider.util; -import li.cil.oc2.api.bus.device.Device; -import li.cil.oc2.api.bus.device.provider.DeviceQuery; +import li.cil.oc2.api.bus.device.ItemDevice; +import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider; import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fml.RegistryObject; +import net.minecraftforge.registries.ForgeRegistryEntry; -public abstract class AbstractItemDeviceProvider extends AbstractDeviceProvider { - private final Item item; +import java.util.Optional; - protected AbstractItemDeviceProvider(final Item item) { +public abstract class AbstractItemDeviceProvider extends ForgeRegistryEntry implements ItemDeviceProvider { + private final RegistryObject item; + + /////////////////////////////////////////////////////////////////// + + protected AbstractItemDeviceProvider(final RegistryObject item) { this.item = item; } - @Override - public LazyOptional getDevice(final DeviceQuery query) { - if (!(query instanceof ItemDeviceQuery)) { - return LazyOptional.empty(); - } - - final ItemDeviceQuery itemDeviceQuery = (ItemDeviceQuery) query; - final ItemStack stack = itemDeviceQuery.getItemStack(); - if (stack.isEmpty()) { - return LazyOptional.empty(); - } - - if (stack.getItem() != item) { - return LazyOptional.empty(); - } - - return getItemDevice(itemDeviceQuery); + protected AbstractItemDeviceProvider() { + this.item = null; } - protected abstract LazyOptional getItemDevice(final ItemDeviceQuery query); + /////////////////////////////////////////////////////////////////// + + @Override + public final Optional getDevice(final ItemDeviceQuery query) { + final ItemStack stack = query.getItemStack(); + if (stack.isEmpty()) { + return Optional.empty(); + } + + if (item != null && stack.getItem() != item.get()) { + return Optional.empty(); + } + + return getItemDevice(query); + } + + /////////////////////////////////////////////////////////////////// + + protected abstract Optional getItemDevice(final ItemDeviceQuery query); } diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractCapabilityTileEntityDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractTileEntityCapabilityDeviceProvider.java similarity index 58% rename from src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractCapabilityTileEntityDeviceProvider.java rename to src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractTileEntityCapabilityDeviceProvider.java index 77cb185c..275d7892 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractCapabilityTileEntityDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractTileEntityCapabilityDeviceProvider.java @@ -3,23 +3,30 @@ package li.cil.oc2.common.bus.device.provider.util; import li.cil.oc2.api.bus.device.Device; import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery; import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import java.util.function.Supplier; -public abstract class AbstractCapabilityTileEntityDeviceProvider extends AbstractTileEntityDeviceProvider { +public abstract class AbstractTileEntityCapabilityDeviceProvider extends AbstractTileEntityDeviceProvider { private final Supplier> capabilitySupplier; /////////////////////////////////////////////////////////////////// - protected AbstractCapabilityTileEntityDeviceProvider(final Class tileEntityType, final Supplier> capabilitySupplier) { + protected AbstractTileEntityCapabilityDeviceProvider(final TileEntityType tileEntityType, final Supplier> capabilitySupplier) { super(tileEntityType); this.capabilitySupplier = capabilitySupplier; } + protected AbstractTileEntityCapabilityDeviceProvider(final Supplier> capabilitySupplier) { + this.capabilitySupplier = capabilitySupplier; + } + + /////////////////////////////////////////////////////////////////// + @Override - protected final LazyOptional getDevice(final BlockDeviceQuery blockQuery, final TileEntity tileEntity) { + protected final LazyOptional getBlockDevice(final BlockDeviceQuery blockQuery, final TileEntity tileEntity) { final Capability capability = capabilitySupplier.get(); if (capability == null) throw new IllegalStateException(); final LazyOptional optional = tileEntity.getCapability(capability, blockQuery.getQuerySide()); @@ -28,10 +35,10 @@ public abstract class AbstractCapabilityTileEntityDeviceProvider device = getDevice(blockQuery, value); + final LazyOptional device = getBlockDevice(blockQuery, value); optional.addListener(ignored -> device.invalidate()); return device; } - protected abstract LazyOptional getDevice(final BlockDeviceQuery query, final TCapability value); + protected abstract LazyOptional getBlockDevice(final BlockDeviceQuery query, final TCapability value); } diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractTileEntityDeviceProvider.java b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractTileEntityDeviceProvider.java index 262d7401..39d14807 100644 --- a/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractTileEntityDeviceProvider.java +++ b/src/main/java/li/cil/oc2/common/bus/device/provider/util/AbstractTileEntityDeviceProvider.java @@ -2,37 +2,42 @@ package li.cil.oc2.common.bus.device.provider.util; import li.cil.oc2.api.bus.device.Device; import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery; -import li.cil.oc2.api.bus.device.provider.DeviceQuery; import li.cil.oc2.common.util.WorldUtils; import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; import net.minecraftforge.common.util.LazyOptional; -public abstract class AbstractTileEntityDeviceProvider extends AbstractDeviceProvider { - private final Class tileEntityType; +public abstract class AbstractTileEntityDeviceProvider extends AbstractBlockDeviceProvider { + private final TileEntityType tileEntityType; /////////////////////////////////////////////////////////////////// - protected AbstractTileEntityDeviceProvider(final Class tileEntityType) { + protected AbstractTileEntityDeviceProvider(final TileEntityType tileEntityType) { this.tileEntityType = tileEntityType; } - @SuppressWarnings("unchecked") - @Override - public LazyOptional getDevice(final DeviceQuery query) { - if (!(query instanceof BlockDeviceQuery)) { - return LazyOptional.empty(); - } - - final BlockDeviceQuery blockQuery = (BlockDeviceQuery) query; - final TileEntity tileEntity = WorldUtils.getTileEntityIfChunkExists(blockQuery.getWorld(), blockQuery.getQueryPosition()); - if (!tileEntityType.isInstance(tileEntity)) { - return LazyOptional.empty(); - } - - return getDevice(blockQuery, (T) tileEntity); + protected AbstractTileEntityDeviceProvider() { + this.tileEntityType = null; } /////////////////////////////////////////////////////////////////// - protected abstract LazyOptional getDevice(final BlockDeviceQuery query, final T tileEntity); + @SuppressWarnings("unchecked") + @Override + public final LazyOptional getDevice(final BlockDeviceQuery query) { + final TileEntity tileEntity = WorldUtils.getTileEntityIfChunkExists(query.getWorld(), query.getQueryPosition()); + if (tileEntity == null) { + return LazyOptional.empty(); + } + + if (tileEntityType != null && tileEntity.getType() != tileEntityType) { + return LazyOptional.empty(); + } + + return getBlockDevice(query, (T) tileEntity); + } + + /////////////////////////////////////////////////////////////////// + + protected abstract LazyOptional getBlockDevice(final BlockDeviceQuery query, final T tileEntity); } diff --git a/src/main/java/li/cil/oc2/common/container/DeviceItemStackHandler.java b/src/main/java/li/cil/oc2/common/container/DeviceItemStackHandler.java index 4b46b39b..78d22323 100644 --- a/src/main/java/li/cil/oc2/common/container/DeviceItemStackHandler.java +++ b/src/main/java/li/cil/oc2/common/container/DeviceItemStackHandler.java @@ -24,9 +24,11 @@ public class DeviceItemStackHandler extends ItemStackHandler { public DeviceItemStackHandler(final NonNullList stacks) { super(stacks); - this.busElement = new ItemHandlerDeviceBusElement(this); + this.busElement = new ItemHandlerDeviceBusElement(getSlots()); } + /////////////////////////////////////////////////////////////////// + public DeviceBusElement getBusElement() { return busElement; } @@ -42,14 +44,19 @@ public class DeviceItemStackHandler extends ItemStackHandler { public void deserializeNBT(final CompoundNBT nbt) { super.deserializeNBT(nbt); busElement.deserializeNBT(nbt.getList(BUS_ELEMENT_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)); - for (int i = 0; i < getSlots(); i++) { - busElement.handleSlotChanged(i); + for (int slot = 0; slot < getSlots(); slot++) { + busElement.updateDevices(slot, getStackInSlot(slot)); } } + @NotNull @Override - public boolean isItemValid(final int slot, @NotNull final ItemStack stack) { - return super.isItemValid(slot, stack); + public ItemStack extractItem(final int slot, final int amount, final boolean simulate) { + if (!simulate && amount > 0) { + busElement.handleBeforeItemRemoved(slot, getStackInSlot(slot)); + } + + return super.extractItem(slot, amount, simulate); } @Override @@ -57,11 +64,16 @@ public class DeviceItemStackHandler extends ItemStackHandler { return 1; } + @Override + public boolean isItemValid(final int slot, @NotNull final ItemStack stack) { + return super.isItemValid(slot, stack); + } + /////////////////////////////////////////////////////////////////// @Override protected void onContentsChanged(final int slot) { super.onContentsChanged(slot); - busElement.handleSlotChanged(slot); + busElement.updateDevices(slot, getStackInSlot(slot)); } } diff --git a/src/main/java/li/cil/oc2/common/init/Providers.java b/src/main/java/li/cil/oc2/common/init/Providers.java index 79c049f8..ff8ce42c 100644 --- a/src/main/java/li/cil/oc2/common/init/Providers.java +++ b/src/main/java/li/cil/oc2/common/init/Providers.java @@ -1,7 +1,8 @@ package li.cil.oc2.common.init; import li.cil.oc2.api.API; -import li.cil.oc2.api.bus.device.provider.DeviceProvider; +import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider; +import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider; import li.cil.oc2.common.bus.device.provider.*; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.DeferredRegister; @@ -11,25 +12,28 @@ import net.minecraftforge.registries.RegistryBuilder; import java.util.function.Supplier; public final class Providers { - private static final DeferredRegister PROVIDERS = DeferredRegister.create(DeviceProvider.class, API.MOD_ID); + private static final DeferredRegister BLOCK_DEVICE_PROVIDERS = DeferredRegister.create(BlockDeviceProvider.class, API.MOD_ID); + private static final DeferredRegister ITEM_DEVICE_PROVIDERS = DeferredRegister.create(ItemDeviceProvider.class, API.MOD_ID); /////////////////////////////////////////////////////////////////// - public static final Supplier> PROVIDERS_REGISTRY = PROVIDERS.makeRegistry("device_providers", RegistryBuilder::new); + public static final Supplier> BLOCK_DEVICE_PROVIDER_REGISTRY = BLOCK_DEVICE_PROVIDERS.makeRegistry("block_device_providers", RegistryBuilder::new); + public static final Supplier> ITEM_DEVICE_PROVIDER_REGISTRY = ITEM_DEVICE_PROVIDERS.makeRegistry("item_device_providers", RegistryBuilder::new); /////////////////////////////////////////////////////////////////// public static void initialize() { - PROVIDERS.register("block", BlockDeviceProvider::new); - PROVIDERS.register("tile_entity", TileEntityDeviceProvider::new); + BLOCK_DEVICE_PROVIDERS.register("block", BlockStateDeviceProvider::new); + BLOCK_DEVICE_PROVIDERS.register("tile_entity", TileEntityDeviceProvider::new); - PROVIDERS.register("energy_storage", EnergyStorageDeviceProvider::new); - PROVIDERS.register("fluid_handler", FluidHandlerDeviceProvider::new); - PROVIDERS.register("item_handler", ItemHandlerDeviceProvider::new); + BLOCK_DEVICE_PROVIDERS.register("energy_storage", EnergyStorageBlockDeviceProvider::new); + BLOCK_DEVICE_PROVIDERS.register("fluid_handler", FluidHandlerBlockDeviceProvider::new); + BLOCK_DEVICE_PROVIDERS.register("item_handler", ItemHandlerBlockDeviceProvider::new); - PROVIDERS.register("item_memory", MemoryItemDeviceProvider::new); - PROVIDERS.register("item_hard_drive", HardDriveItemDeviceProvider::new); + ITEM_DEVICE_PROVIDERS.register("item_memory", MemoryItemDeviceProvider::new); + ITEM_DEVICE_PROVIDERS.register("item_hard_drive", HardDriveItemDeviceProvider::new); - PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus()); + BLOCK_DEVICE_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus()); + ITEM_DEVICE_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus()); } } diff --git a/src/main/java/li/cil/oc2/common/network/Network.java b/src/main/java/li/cil/oc2/common/network/Network.java index 43e5ebf3..119a1d54 100644 --- a/src/main/java/li/cil/oc2/common/network/Network.java +++ b/src/main/java/li/cil/oc2/common/network/Network.java @@ -22,6 +22,8 @@ public final class Network { PROTOCOL_VERSION::equals ); + /////////////////////////////////////////////////////////////////// + private static int nextPacketId = 1; /////////////////////////////////////////////////////////////////// diff --git a/src/main/java/li/cil/oc2/common/network/message/AbstractTerminalBlockMessage.java b/src/main/java/li/cil/oc2/common/network/message/AbstractTerminalBlockMessage.java index 429b273b..5f7cd72d 100644 --- a/src/main/java/li/cil/oc2/common/network/message/AbstractTerminalBlockMessage.java +++ b/src/main/java/li/cil/oc2/common/network/message/AbstractTerminalBlockMessage.java @@ -21,6 +21,8 @@ public abstract class AbstractTerminalBlockMessage { fromBytes(buffer); } + /////////////////////////////////////////////////////////////////// + public void fromBytes(final PacketBuffer buffer) { pos = buffer.readBlockPos(); data = buffer.readByteArray(); diff --git a/src/main/java/li/cil/oc2/common/network/message/ComputerBusStateMessage.java b/src/main/java/li/cil/oc2/common/network/message/ComputerBusStateMessage.java index 52ea2282..54e0aa14 100644 --- a/src/main/java/li/cil/oc2/common/network/message/ComputerBusStateMessage.java +++ b/src/main/java/li/cil/oc2/common/network/message/ComputerBusStateMessage.java @@ -24,6 +24,8 @@ public class ComputerBusStateMessage { fromBytes(buffer); } + /////////////////////////////////////////////////////////////////// + public static boolean handleMessage(final ComputerBusStateMessage message, final Supplier context) { context.get().enqueueWork(() -> MessageUtils.withClientTileEntityAt(message.pos, ComputerTileEntity.class, (tileEntity) -> tileEntity.setBusStateClient(message.busState))); diff --git a/src/main/java/li/cil/oc2/common/network/message/ComputerRunStateMessage.java b/src/main/java/li/cil/oc2/common/network/message/ComputerRunStateMessage.java index fbd77f74..47fe6129 100644 --- a/src/main/java/li/cil/oc2/common/network/message/ComputerRunStateMessage.java +++ b/src/main/java/li/cil/oc2/common/network/message/ComputerRunStateMessage.java @@ -23,6 +23,8 @@ public class ComputerRunStateMessage { fromBytes(buffer); } + /////////////////////////////////////////////////////////////////// + public static boolean handleMessage(final ComputerRunStateMessage message, final Supplier context) { context.get().enqueueWork(() -> MessageUtils.withClientTileEntityAt(message.pos, ComputerTileEntity.class, (tileEntity) -> tileEntity.setRunStateClient(message.runState))); diff --git a/src/main/java/li/cil/oc2/common/network/message/TerminalBlockInputMessage.java b/src/main/java/li/cil/oc2/common/network/message/TerminalBlockInputMessage.java index 3f155a1f..7ffa8948 100644 --- a/src/main/java/li/cil/oc2/common/network/message/TerminalBlockInputMessage.java +++ b/src/main/java/li/cil/oc2/common/network/message/TerminalBlockInputMessage.java @@ -17,6 +17,8 @@ public final class TerminalBlockInputMessage extends AbstractTerminalBlockMessag super(buffer); } + /////////////////////////////////////////////////////////////////// + public static boolean handleMessage(final AbstractTerminalBlockMessage message, final Supplier context) { context.get().enqueueWork(() -> MessageUtils.withServerTileEntityAt(context, message.pos, ComputerTileEntity.class, (tileEntity) -> tileEntity.getTerminal().putInput(ByteBuffer.wrap(message.data)))); diff --git a/src/main/java/li/cil/oc2/common/network/message/TerminalBlockOutputMessage.java b/src/main/java/li/cil/oc2/common/network/message/TerminalBlockOutputMessage.java index 6612e163..73477cdd 100644 --- a/src/main/java/li/cil/oc2/common/network/message/TerminalBlockOutputMessage.java +++ b/src/main/java/li/cil/oc2/common/network/message/TerminalBlockOutputMessage.java @@ -17,6 +17,8 @@ public final class TerminalBlockOutputMessage extends AbstractTerminalBlockMessa super(buffer); } + /////////////////////////////////////////////////////////////////// + public static boolean handleMessage(final AbstractTerminalBlockMessage message, final Supplier context) { context.get().enqueueWork(() -> MessageUtils.withClientTileEntityAt(message.pos, ComputerTileEntity.class, tileEntity -> tileEntity.getTerminal().putOutput(ByteBuffer.wrap(message.data)))); diff --git a/src/main/java/li/cil/oc2/common/util/HorizontalBlockUtils.java b/src/main/java/li/cil/oc2/common/util/HorizontalBlockUtils.java index 496d625b..64676f72 100644 --- a/src/main/java/li/cil/oc2/common/util/HorizontalBlockUtils.java +++ b/src/main/java/li/cil/oc2/common/util/HorizontalBlockUtils.java @@ -9,6 +9,8 @@ import javax.annotation.Nullable; public final class HorizontalBlockUtils { public static final int HORIZONTAL_DIRECTION_COUNT = 4; + /////////////////////////////////////////////////////////////////// + @Nullable public static Direction toLocal(final BlockState blockState, @Nullable final Direction direction) { if (direction == null) { diff --git a/src/main/java/li/cil/oc2/common/util/ItemDeviceUtils.java b/src/main/java/li/cil/oc2/common/util/ItemDeviceUtils.java new file mode 100644 index 00000000..7dcf0a55 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/util/ItemDeviceUtils.java @@ -0,0 +1,49 @@ +package li.cil.oc2.common.util; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.IForgeRegistryEntry; + +import javax.annotation.Nullable; +import java.util.Optional; + +public final class ItemDeviceUtils { + private static final String ITEM_DEVICE_DATA_NBT_TAG_NAME = "item_device"; + + /////////////////////////////////////////////////////////////////// + + public static Optional getItemDeviceData(final ItemStack stack) { + if (stack.isEmpty()) { + return Optional.empty(); + } + + final CompoundNBT nbt = ItemStackUtils.getModDataTag(stack); + if (nbt == null) { + return Optional.empty(); + } + + return Optional.of(nbt.getCompound(ITEM_DEVICE_DATA_NBT_TAG_NAME)); + } + + public static void setItemDeviceData(final ItemStack stack, final CompoundNBT data) { + if (data.isEmpty()) { + return; + } + + ItemStackUtils.getOrCreateModDataTag(stack).put(ITEM_DEVICE_DATA_NBT_TAG_NAME, data); + } + + public static Optional getItemDeviceDataKey(@Nullable final IForgeRegistryEntry provider) { + if (provider == null) { + return Optional.empty(); + } + + final ResourceLocation providerName = provider.getRegistryName(); + if (providerName == null) { + return Optional.empty(); + } + + return Optional.of(providerName.toString()); + } +} diff --git a/src/main/java/li/cil/oc2/common/util/ItemStackUtils.java b/src/main/java/li/cil/oc2/common/util/ItemStackUtils.java new file mode 100644 index 00000000..b4aa5c70 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/util/ItemStackUtils.java @@ -0,0 +1,26 @@ +package li.cil.oc2.common.util; + +import li.cil.oc2.api.API; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; + +import javax.annotation.Nullable; + +public final class ItemStackUtils { + @Nullable + public static CompoundNBT getModDataTag(final ItemStack stack) { + if (stack.isEmpty()) { + return null; + } + + return stack.getChildTag(API.MOD_ID); + } + + public static CompoundNBT getOrCreateModDataTag(final ItemStack stack) { + if (stack.isEmpty()) { + throw new IllegalArgumentException(); + } + + return stack.getOrCreateChildTag(API.MOD_ID); + } +} diff --git a/src/main/java/li/cil/oc2/common/vm/ManagedInterruptAllocator.java b/src/main/java/li/cil/oc2/common/vm/ManagedInterruptAllocator.java index 970441f7..473c522c 100644 --- a/src/main/java/li/cil/oc2/common/vm/ManagedInterruptAllocator.java +++ b/src/main/java/li/cil/oc2/common/vm/ManagedInterruptAllocator.java @@ -23,6 +23,8 @@ public final class ManagedInterruptAllocator implements InterruptAllocator { this.interruptCount = interruptCount; } + /////////////////////////////////////////////////////////////////// + public void freeze() { isFrozen = true; } diff --git a/src/main/java/li/cil/oc2/common/vm/ManagedInterruptController.java b/src/main/java/li/cil/oc2/common/vm/ManagedInterruptController.java index 1c9e3972..2845a3fa 100644 --- a/src/main/java/li/cil/oc2/common/vm/ManagedInterruptController.java +++ b/src/main/java/li/cil/oc2/common/vm/ManagedInterruptController.java @@ -15,6 +15,8 @@ public final class ManagedInterruptController implements InterruptController { this.allocator = allocator; } + /////////////////////////////////////////////////////////////////// + public void invalidate() { isValid = false; interruptController.lowerInterrupts(raisedInterrupts); diff --git a/src/main/java/li/cil/oc2/common/vm/ManagedMemoryAllocator.java b/src/main/java/li/cil/oc2/common/vm/ManagedMemoryAllocator.java index d7c7ae06..bbb1c221 100644 --- a/src/main/java/li/cil/oc2/common/vm/ManagedMemoryAllocator.java +++ b/src/main/java/li/cil/oc2/common/vm/ManagedMemoryAllocator.java @@ -9,6 +9,8 @@ public final class ManagedMemoryAllocator implements MemoryAllocator { private final ArrayList claimedMemory = new ArrayList<>(); private boolean isFrozen; + /////////////////////////////////////////////////////////////////// + public void freeze() { isFrozen = true; } diff --git a/src/main/java/li/cil/oc2/common/vm/ManagedMemoryMap.java b/src/main/java/li/cil/oc2/common/vm/ManagedMemoryMap.java index b9a5e453..baad095f 100644 --- a/src/main/java/li/cil/oc2/common/vm/ManagedMemoryMap.java +++ b/src/main/java/li/cil/oc2/common/vm/ManagedMemoryMap.java @@ -18,6 +18,8 @@ final class ManagedMemoryMap implements MemoryMap { this.memoryMap = memoryMap; } + /////////////////////////////////////////////////////////////////// + @Override public OptionalLong findFreeRange(final long start, final long end, final int size) { return memoryMap.findFreeRange(start, end, size); diff --git a/src/main/java/li/cil/oc2/common/vm/ManagedMemoryRangeAllocator.java b/src/main/java/li/cil/oc2/common/vm/ManagedMemoryRangeAllocator.java index 65df3d00..b285d022 100644 --- a/src/main/java/li/cil/oc2/common/vm/ManagedMemoryRangeAllocator.java +++ b/src/main/java/li/cil/oc2/common/vm/ManagedMemoryRangeAllocator.java @@ -14,10 +14,14 @@ public final class ManagedMemoryRangeAllocator implements MemoryRangeAllocator { private final ArrayList managedDevices = new ArrayList<>(); private boolean isFrozen; + /////////////////////////////////////////////////////////////////// + public ManagedMemoryRangeAllocator(final Board board) { this.board = board; } + /////////////////////////////////////////////////////////////////// + public void freeze() { isFrozen = true; } diff --git a/src/main/java/li/cil/oc2/common/vm/ManagedVMContext.java b/src/main/java/li/cil/oc2/common/vm/ManagedVMContext.java index a23dc072..6646e854 100644 --- a/src/main/java/li/cil/oc2/common/vm/ManagedVMContext.java +++ b/src/main/java/li/cil/oc2/common/vm/ManagedVMContext.java @@ -27,6 +27,8 @@ public final class ManagedVMContext implements VMContext { this.memoryAllocator = new ManagedMemoryAllocator(); } + /////////////////////////////////////////////////////////////////// + public void freeze() { memoryRangeAllocator.freeze(); interruptAllocator.freeze(); diff --git a/src/main/java/li/cil/oc2/common/vm/Terminal.java b/src/main/java/li/cil/oc2/common/vm/Terminal.java index 1e138569..9ce6d1c2 100644 --- a/src/main/java/li/cil/oc2/common/vm/Terminal.java +++ b/src/main/java/li/cil/oc2/common/vm/Terminal.java @@ -57,12 +57,16 @@ public final class Terminal { private static final byte DEFAULT_COLORS = COLOR_WHITE << COLOR_FOREGROUND_SHIFT; private static final byte DEFAULT_STYLE = 0; + /////////////////////////////////////////////////////////////////// + public enum State { // Must be public for serialization. NORMAL, // Currently reading characters normally. ESCAPE, // Last character was ESC, figure out what kind next. SEQUENCE, // Know what sequence we have, now parsing it. } + /////////////////////////////////////////////////////////////////// + private final ByteArrayFIFOQueue input = new ByteArrayFIFOQueue(32); private final byte[] buffer = new byte[WIDTH * HEIGHT]; private final byte[] colors = new byte[WIDTH * HEIGHT]; @@ -85,10 +89,14 @@ public final class Terminal { private transient Object renderer; private transient boolean displayOnly; // Set on client to not send responses to status requests. + /////////////////////////////////////////////////////////////////// + public Terminal() { clear(); } + /////////////////////////////////////////////////////////////////// + public void setDisplayOnly(final boolean value) { displayOnly = value; } @@ -331,6 +339,8 @@ public final class Terminal { } } + /////////////////////////////////////////////////////////////////// + private void selectStyle(final int sgr) { switch (sgr) { case 0: { // Reset / Normal @@ -476,6 +486,8 @@ public final class Terminal { dirty.set(-1); } + /////////////////////////////////////////////////////////////////// + @OnlyIn(Dist.CLIENT) private static final class Renderer { private static final ResourceLocation LOCATION_FONT_TEXTURE = new ResourceLocation(API.MOD_ID, "textures/font/terminus.png"); @@ -506,15 +518,21 @@ public final class Terminal { 0x777777, // White }; + /////////////////////////////////////////////////////////////// + private final Terminal terminal; private final Object[] lines = new Object[HEIGHT]; // Cached vertex buffers for rendering, untyped for server. private Object lastMatrix; // Untyped for server. + /////////////////////////////////////////////////////////////// + public Renderer(final Terminal terminal) { this.terminal = terminal; } + /////////////////////////////////////////////////////////////// + public void render(final AtomicInteger dirty, final MatrixStack stack) { validateLineCache(dirty, stack); renderBuffer(); @@ -524,6 +542,8 @@ public final class Terminal { } } + /////////////////////////////////////////////////////////////// + private void renderBuffer() { GlStateManager.depthMask(false); Minecraft.getInstance().getTextureManager().bindTexture(LOCATION_FONT_TEXTURE); diff --git a/src/main/java/li/cil/oc2/common/vm/VirtualMachine.java b/src/main/java/li/cil/oc2/common/vm/VirtualMachine.java index 944c90aa..3c06a234 100644 --- a/src/main/java/li/cil/oc2/common/vm/VirtualMachine.java +++ b/src/main/java/li/cil/oc2/common/vm/VirtualMachine.java @@ -7,22 +7,12 @@ import li.cil.oc2.api.bus.device.vm.MemoryRangeAllocator; import li.cil.oc2.api.bus.device.vm.VMContext; import li.cil.oc2.common.bus.RPCAdapter; import li.cil.sedna.api.device.InterruptController; -import li.cil.sedna.buildroot.Buildroot; -import li.cil.sedna.device.block.ByteBufferBlockDevice; import li.cil.sedna.device.rtc.GoldfishRTC; import li.cil.sedna.device.serial.UART16550A; import li.cil.sedna.device.virtio.VirtIOConsoleDevice; import li.cil.sedna.riscv.R5Board; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; public final class VirtualMachine { - private static final Logger LOGGER = LogManager.getLogger(); - - /////////////////////////////////////////////////////////////////// - // We report a clock rate to the VM such that for the VM it looks as though // passes as much faster as MC time passes faster than real time. public static final int REPORTED_CPU_FREQUENCY = 700_000; @@ -32,19 +22,6 @@ public final class VirtualMachine { private static final int RTC_INTERRUPT = 0x2; private static final int RPC_INTERRUPT = 0x3; - private static final ByteBufferBlockDevice ROOT_FS; - - static { - ByteBufferBlockDevice rootfs; - try { - rootfs = ByteBufferBlockDevice.createFromStream(Buildroot.getRootFilesystem(), true); - } catch (final IOException e) { - LOGGER.error(e); - rootfs = ByteBufferBlockDevice.create(0, true); - } - ROOT_FS = rootfs; - } - /////////////////////////////////////////////////////////////////// public final MinecraftRealTimeCounter rtc = new MinecraftRealTimeCounter(); @@ -92,6 +69,8 @@ public final class VirtualMachine { board.setStandardOutputDevice(uart); } + /////////////////////////////////////////////////////////////////// + public void reset() { board.reset(); rpcAdapter.reset(); diff --git a/src/main/java/li/cil/oc2/common/vm/VirtualMachineDeviceBusAdapter.java b/src/main/java/li/cil/oc2/common/vm/VirtualMachineDeviceBusAdapter.java index bf865370..107ac587 100644 --- a/src/main/java/li/cil/oc2/common/vm/VirtualMachineDeviceBusAdapter.java +++ b/src/main/java/li/cil/oc2/common/vm/VirtualMachineDeviceBusAdapter.java @@ -33,6 +33,8 @@ public final class VirtualMachineDeviceBusAdapter { this.claimedInterrupts.set(0); } + /////////////////////////////////////////////////////////////////// + public VMContext getGlobalContext() { return globalContext; } diff --git a/src/main/java/li/cil/oc2/common/vm/VirtualMachineRunner.java b/src/main/java/li/cil/oc2/common/vm/VirtualMachineRunner.java index d468ca49..929801e5 100644 --- a/src/main/java/li/cil/oc2/common/vm/VirtualMachineRunner.java +++ b/src/main/java/li/cil/oc2/common/vm/VirtualMachineRunner.java @@ -36,6 +36,8 @@ public class VirtualMachineRunner implements Runnable { this.board = board; } + /////////////////////////////////////////////////////////////////// + public void tick() { cycleLimit += getCyclesPerTick(); if (timeQuotaInMillis.addAndGet(TIMESLICE_IN_MS) > 0 && lastSchedule == null || lastSchedule.isDone() || lastSchedule.isCancelled()) {