diff --git a/src/main/java/li/cil/oc2/api/bus/device/Device.java b/src/main/java/li/cil/oc2/api/bus/device/Device.java index b01d9356..1299e880 100644 --- a/src/main/java/li/cil/oc2/api/bus/device/Device.java +++ b/src/main/java/li/cil/oc2/api/bus/device/Device.java @@ -2,13 +2,9 @@ package li.cil.oc2.api.bus.device; import li.cil.oc2.api.bus.DeviceBus; import li.cil.oc2.api.bus.DeviceBusController; -import li.cil.oc2.api.bus.DeviceBusElement; import net.minecraft.nbt.CompoundNBT; import net.minecraftforge.common.util.INBTSerializable; -import java.util.Optional; -import java.util.UUID; - /** * Base interface for objects that can be registered as devices on a {@link DeviceBus}. *

@@ -20,22 +16,6 @@ import java.util.UUID; * detected. */ public interface Device extends INBTSerializable { - /** - * An identifier used to associate save data with this device. - *

- * This is required for a device to be serialized. When this returns - * {@link Optional#empty()}, {@link #serializeNBT()} and {@link #deserializeNBT(CompoundNBT)} - * will not be called. - *

- * Not to be confused with the identifiers used for devices on a {@link DeviceBus}, - * which are assigned by {@link DeviceBusElement}s to the devices they contain. - * - * @return a stable, unique identifier for this specific device type. - */ - default Optional getSerializationKey() { - return Optional.empty(); - } - @Override default CompoundNBT serializeNBT() { return new CompoundNBT(); 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 03b3ff9d..cdfab82c 100644 --- a/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java +++ b/src/main/java/li/cil/oc2/common/bus/AbstractGroupingDeviceBusElement.java @@ -1,12 +1,15 @@ 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.util.NBTTagIds; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.util.INBTSerializable; 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"; @@ -15,7 +18,7 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus /////////////////////////////////////////////////////////////////// protected final int groupCount; - protected final ArrayList> devicesByGroup; + protected final ArrayList> devicesByGroup; /////////////////////////////////////////////////////////////////// @@ -71,8 +74,11 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus @Override public Optional getDeviceIdentifier(final Device device) { for (int i = 0; i < groupCount; i++) { - if (devicesByGroup.get(i).contains(device)) { - return Optional.of(deviceIds[i]); + final HashSet group = devicesByGroup.get(i); + for (final DeviceInfo deviceInfo : group) { + if (Objects.equals(device, deviceInfo.device)) { + return Optional.of(deviceIds[i]); + } } } return super.getDeviceIdentifier(device); @@ -80,32 +86,31 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus /////////////////////////////////////////////////////////////////// - protected void setDevicesForGroup(final int index, final HashSet newDevices) { - final HashSet oldDevices = devicesByGroup.get(index); + protected void setDevicesForGroup(final int index, final HashSet newDevices) { + final HashSet oldDevices = devicesByGroup.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); + 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); + devices.addAll(addedDevices.stream().map(info -> info.device).collect(Collectors.toList())); oldDevices.removeAll(removedDevices); oldDevices.addAll(newDevices); final CompoundNBT devicesNbt = deviceData[index]; - for (final Device device : removedDevices) { - device.getSerializationKey().ifPresent(key -> - devicesNbt.remove(key.toString())); + for (final DeviceInfo deviceInfo : removedDevices) { + getSerializationKey(deviceInfo).ifPresent(devicesNbt::remove); } - for (final Device device : addedDevices) { - device.getSerializationKey().ifPresent(key -> { - if (devicesNbt.contains(key.toString(), NBTTagIds.TAG_COMPOUND)) { - device.deserializeNBT(devicesNbt.getCompound(key.toString())); + for (final DeviceInfo deviceInfo : addedDevices) { + getSerializationKey(deviceInfo).ifPresent(key -> { + if (devicesNbt.contains(key, NBTTagIds.TAG_COMPOUND)) { + deviceInfo.device.deserializeNBT(devicesNbt.getCompound(key)); } }); } @@ -118,11 +123,24 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus private void serializeDevices() { for (int i = 0; i < groupCount; i++) { final CompoundNBT devicesNbt = new CompoundNBT(); - for (final Device device : devicesByGroup.get(i)) { - device.getSerializationKey().ifPresent(key -> - devicesNbt.put(key.toString(), device.serializeNBT())); + 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(); + } + + return Optional.of(providerName.toString()); + } } 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 c263c20b..f52016af 100644 --- a/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java +++ b/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java @@ -1,6 +1,6 @@ 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.Devices; import net.minecraft.item.ItemStack; import net.minecraftforge.common.util.LazyOptional; @@ -19,12 +19,12 @@ public class ItemHandlerDeviceBusElement extends AbstractGroupingDeviceBusElemen } public void handleSlotChanged(final int slot) { - final HashSet newDevices = new HashSet<>(); + final HashSet newDevices = new HashSet<>(); final ItemStack stack = handler.getStackInSlot(slot); if (!stack.isEmpty()) { - for (final LazyOptional device : Devices.getDevices(stack)) { - device.ifPresent(newDevices::add); - device.addListener(unused -> handleSlotChanged(slot)); + for (final LazyOptional info : Devices.getDevices(stack)) { + info.ifPresent(newDevices::add); + info.addListener(unused -> handleSlotChanged(slot)); } } 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 c1e5ccd0..8c6b7211 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.api.bus.device.Device; +import li.cil.oc2.common.bus.device.DeviceInfo; import li.cil.oc2.common.bus.device.Devices; import li.cil.oc2.common.capabilities.Capabilities; import li.cil.oc2.common.util.ServerScheduler; @@ -80,11 +80,11 @@ 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 device : Devices.getDevices(world, pos, direction)) { - device.ifPresent(newDevices::add); - device.addListener(unused -> handleNeighborChanged(pos)); + 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/AbstractHardDiskDriveDevice.java b/src/main/java/li/cil/oc2/common/bus/device/AbstractHardDiskDriveDevice.java index 53f69961..90d19ed2 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 @@ -18,8 +18,6 @@ import java.util.OptionalLong; import java.util.UUID; public abstract class AbstractHardDiskDriveDevice extends AbstractObjectProxy implements VMDevice, VMDeviceLifecycleListener { - private static final UUID SERIALIZATION_KEY = UUID.fromString("8842cf60-a6e6-44d2-b442-380007625078"); - 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"; @@ -78,11 +76,6 @@ public abstract class AbstractHardDiskDriveDevice extends } } - @Override - public Optional getSerializationKey() { - return Optional.of(SERIALIZATION_KEY); - } - @Override public CompoundNBT serializeNBT() { final CompoundNBT nbt = new CompoundNBT(); 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 new file mode 100644 index 00000000..3450df01 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/bus/device/DeviceInfo.java @@ -0,0 +1,29 @@ +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 c196a607..893d6f09 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 @@ -19,7 +19,7 @@ import java.util.ArrayList; import java.util.List; 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 +28,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) { + public static List> getDevices(final DeviceQuery query) { final IForgeRegistry providers = Providers.PROVIDERS_REGISTRY.get(); - final ArrayList> devices = new ArrayList<>(); + final ArrayList> devices = new ArrayList<>(); for (final DeviceProvider provider : providers.getValues()) { final LazyOptional device = provider.getDevice(query); if (device.isPresent()) { - devices.add(device); + final LazyOptional info = device.lazyMap(d -> new DeviceInfo(d, provider)); + device.addListener(unused -> info.invalidate()); + devices.add(info); } } return devices; 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 70a00748..50b31e3a 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 @@ -12,13 +12,10 @@ import li.cil.sedna.memory.PhysicalMemoryOutputStream; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; -import java.util.Optional; import java.util.OptionalLong; import java.util.UUID; public final class MemoryDevice extends AbstractObjectProxy implements VMDevice, VMDeviceLifecycleListener { - private static final UUID SERIALIZATION_KEY = UUID.fromString("c82f8c1c-d7ff-43b0-ab44-989e1fe818bb"); - private static final String BLOB_HANDLE_NBT_TAG_NAME = "blob"; private static final String ADDRESS_NBT_TAG_NAME = "address"; @@ -67,11 +64,6 @@ public final class MemoryDevice extends AbstractObjectProxy implement } } - @Override - public Optional getSerializationKey() { - return Optional.of(SERIALIZATION_KEY); - } - @Override public CompoundNBT serializeNBT() { final CompoundNBT nbt = new CompoundNBT(); 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 17906a95..63d4ddec 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 @@ -18,7 +18,4 @@ public final class MemoryItemDeviceProvider extends AbstractItemDeviceProvider { protected LazyOptional getItemDevice(final ItemDeviceQuery query) { return LazyOptional.of(() -> new MemoryDevice(query.getItemStack())); } - - /////////////////////////////////////////////////////////////////// - }