Use provider registry name as serialization key.

This commit is contained in:
Florian Nücke
2020-12-19 12:54:46 +01:00
parent 41d06e84e1
commit 556ae0cf6e
9 changed files with 84 additions and 73 deletions

View File

@@ -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}.
* <p>
@@ -20,22 +16,6 @@ import java.util.UUID;
* detected.
*/
public interface Device extends INBTSerializable<CompoundNBT> {
/**
* An identifier used to associate save data with this device.
* <p>
* This is <em>required</em> for a device to be serialized. When this returns
* {@link Optional#empty()}, {@link #serializeNBT()} and {@link #deserializeNBT(CompoundNBT)}
* will not be called.
* <p>
* 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<UUID> getSerializationKey() {
return Optional.empty();
}
@Override
default CompoundNBT serializeNBT() {
return new CompoundNBT();

View File

@@ -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<ListNBT> {
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<HashSet<Device>> devicesByGroup;
protected final ArrayList<HashSet<DeviceInfo>> devicesByGroup;
///////////////////////////////////////////////////////////////////
@@ -71,8 +74,11 @@ public abstract class AbstractGroupingDeviceBusElement extends AbstractDeviceBus
@Override
public Optional<UUID> getDeviceIdentifier(final Device device) {
for (int i = 0; i < groupCount; i++) {
if (devicesByGroup.get(i).contains(device)) {
return Optional.of(deviceIds[i]);
final HashSet<DeviceInfo> 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<Device> newDevices) {
final HashSet<Device> oldDevices = devicesByGroup.get(index);
protected void setDevicesForGroup(final int index, final HashSet<DeviceInfo> newDevices) {
final HashSet<DeviceInfo> oldDevices = devicesByGroup.get(index);
if (Objects.equals(newDevices, oldDevices)) {
return;
}
final HashSet<Device> removedDevices = new HashSet<>(oldDevices);
final HashSet<DeviceInfo> removedDevices = new HashSet<>(oldDevices);
removedDevices.removeAll(newDevices);
devices.removeAll(removedDevices);
devices.removeAll(removedDevices.stream().map(info -> info.device).collect(Collectors.toList()));
final HashSet<Device> addedDevices = new HashSet<>(newDevices);
final HashSet<DeviceInfo> 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<String> getSerializationKey(final DeviceInfo info) {
final ResourceLocation providerName = info.provider.getRegistryName();
if (providerName == null) {
return Optional.empty();
}
return Optional.of(providerName.toString());
}
}

View File

@@ -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<Device> newDevices = new HashSet<>();
final HashSet<DeviceInfo> newDevices = new HashSet<>();
final ItemStack stack = handler.getStackInSlot(slot);
if (!stack.isEmpty()) {
for (final LazyOptional<Device> device : Devices.getDevices(stack)) {
device.ifPresent(newDevices::add);
device.addListener(unused -> handleSlotChanged(slot));
for (final LazyOptional<DeviceInfo> info : Devices.getDevices(stack)) {
info.ifPresent(newDevices::add);
info.addListener(unused -> handleSlotChanged(slot));
}
}

View File

@@ -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<Device> newDevices = new HashSet<>();
final HashSet<DeviceInfo> newDevices = new HashSet<>();
if (canConnectToSide(direction)) {
for (final LazyOptional<Device> device : Devices.getDevices(world, pos, direction)) {
device.ifPresent(newDevices::add);
device.addListener(unused -> handleNeighborChanged(pos));
for (final LazyOptional<DeviceInfo> deviceInfo : Devices.getDevices(world, pos, direction)) {
deviceInfo.ifPresent(newDevices::add);
deviceInfo.addListener(unused -> handleNeighborChanged(pos));
}
}

View File

@@ -18,8 +18,6 @@ import java.util.OptionalLong;
import java.util.UUID;
public abstract class AbstractHardDiskDriveDevice<T extends BlockDevice> extends AbstractObjectProxy<ItemStack> 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<T extends BlockDevice> extends
}
}
@Override
public Optional<UUID> getSerializationKey() {
return Optional.of(SERIALIZATION_KEY);
}
@Override
public CompoundNBT serializeNBT() {
final CompoundNBT nbt = new CompoundNBT();

View File

@@ -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);
}
}

View File

@@ -19,7 +19,7 @@ import java.util.ArrayList;
import java.util.List;
public final class Devices {
public static List<LazyOptional<Device>> getDevices(final TileEntity tileEntity, final Direction side) {
public static List<LazyOptional<DeviceInfo>> 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<LazyOptional<Device>> getDevices(final World world, final BlockPos pos, final Direction side) {
public static List<LazyOptional<DeviceInfo>> getDevices(final World world, final BlockPos pos, final Direction side) {
return getDevices(new BlockQuery(world, pos, side));
}
public static List<LazyOptional<Device>> getDevices(final ItemStack stack) {
public static List<LazyOptional<DeviceInfo>> getDevices(final ItemStack stack) {
return getDevices(new ItemQuery(stack));
}
public static List<LazyOptional<Device>> getDevices(final DeviceQuery query) {
public static List<LazyOptional<DeviceInfo>> getDevices(final DeviceQuery query) {
final IForgeRegistry<DeviceProvider> providers = Providers.PROVIDERS_REGISTRY.get();
final ArrayList<LazyOptional<Device>> devices = new ArrayList<>();
final ArrayList<LazyOptional<DeviceInfo>> devices = new ArrayList<>();
for (final DeviceProvider provider : providers.getValues()) {
final LazyOptional<Device> device = provider.getDevice(query);
if (device.isPresent()) {
devices.add(device);
final LazyOptional<DeviceInfo> info = device.lazyMap(d -> new DeviceInfo(d, provider));
device.addListener(unused -> info.invalidate());
devices.add(info);
}
}
return devices;

View File

@@ -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<ItemStack> 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<ItemStack> implement
}
}
@Override
public Optional<UUID> getSerializationKey() {
return Optional.of(SERIALIZATION_KEY);
}
@Override
public CompoundNBT serializeNBT() {
final CompoundNBT nbt = new CompoundNBT();

View File

@@ -18,7 +18,4 @@ public final class MemoryItemDeviceProvider extends AbstractItemDeviceProvider {
protected LazyOptional<Device> getItemDevice(final ItemDeviceQuery query) {
return LazyOptional.of(() -> new MemoryDevice(query.getItemStack()));
}
///////////////////////////////////////////////////////////////////
}