Files
oc2r/src/main/java/li/cil/oc2/common/bus/AbstractItemDeviceBusElement.java

164 lines
5.6 KiB
Java

/* SPDX-License-Identifier: MIT */
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.device.Device;
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 li.cil.oc2.common.bus.device.provider.Providers;
import li.cil.oc2.common.bus.device.rpc.TypeNameRPCDevice;
import li.cil.oc2.common.bus.device.util.Devices;
import li.cil.oc2.common.bus.device.util.ItemDeviceInfo;
import li.cil.oc2.common.util.ItemDeviceUtils;
import li.cil.oc2.common.util.NBTTagIds;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.IForgeRegistry;
import javax.annotation.Nullable;
import java.util.*;
import static li.cil.oc2.common.util.RegistryUtils.optionalKey;
public abstract class AbstractItemDeviceBusElement extends AbstractGroupingDeviceBusElement<AbstractItemDeviceBusElement.ItemEntry, ItemDeviceQuery> {
public AbstractItemDeviceBusElement(final int groupCount) {
super(groupCount);
}
///////////////////////////////////////////////////////////////////
public boolean groupContains(final int groupIndex, final Device device) {
for (final ItemEntry entry : groups.get(groupIndex)) {
if (Objects.equals(entry.getDevice(), device)) {
return true;
}
}
return false;
}
public void handleSlotContentsChanged(final int slot, final ItemStack stack) {
final ItemQueryResult queryResult = collectDevices(stack);
setEntriesForGroup(slot, queryResult);
}
public void exportDeviceDataToItemStack(final int slot, final ItemStack stack) {
if (stack.isEmpty()) {
return;
}
final CompoundTag exportedTag = new CompoundTag();
for (final ItemEntry entry : groups.get(slot)) {
entry.getDeviceDataKey().ifPresent(key -> {
final CompoundTag deviceTag = new CompoundTag();
entry.getDevice().exportToItemStack(deviceTag);
if (!deviceTag.isEmpty()) {
exportedTag.put(key, deviceTag);
}
});
}
if (!exportedTag.isEmpty()) {
ItemDeviceUtils.setItemDeviceData(stack, exportedTag);
}
}
///////////////////////////////////////////////////////////////////
protected abstract ItemDeviceQuery makeQuery(final ItemStack stack);
protected ItemQueryResult collectDevices(final ItemStack stack) {
final ItemDeviceQuery query = makeQuery(stack);
final HashSet<ItemEntry> entries = new HashSet<>();
for (final ItemDeviceInfo deviceInfo : Devices.getDevices(query)) {
entries.add(new ItemEntry(deviceInfo));
}
collectSyntheticDevices(query, entries);
importDeviceDataFromItemStack(query, entries);
return new ItemQueryResult(query, entries);
}
@SuppressWarnings("ConstantValue")
protected void collectSyntheticDevices(final ItemDeviceQuery query, final HashSet<ItemEntry> entries) {
if (entries.isEmpty()) {
return;
}
if (query.getItemStack().getDisplayName() != null) {
entries.add(new ItemEntry(new ItemDeviceInfo(null, new TypeNameRPCDevice(query.getItemStack().getDisplayName().toString()), 0)));
}
}
@Override
protected void onEntryRemoved(final String dataKey, final CompoundTag tag, @Nullable final ItemDeviceQuery query) {
super.onEntryRemoved(dataKey, tag, query);
final IForgeRegistry<ItemDeviceProvider> registry = Providers.itemDeviceProviderRegistry();
final ItemDeviceProvider provider = registry.getValue(ResourceLocation.parse(dataKey));
if (provider != null) {
provider.unmount(query, tag);
}
}
///////////////////////////////////////////////////////////////////
private void importDeviceDataFromItemStack(final ItemDeviceQuery query, final HashSet<ItemEntry> entries) {
final CompoundTag exportedTag = ItemDeviceUtils.getItemDeviceData(query.getItemStack());
if (!exportedTag.isEmpty()) {
for (final ItemEntry entry : entries) {
entry.getDeviceDataKey().ifPresent(key -> {
if (exportedTag.contains(key, NBTTagIds.TAG_COMPOUND)) {
entry.deviceInfo.device.importFromItemStack(exportedTag.getCompound(key));
}
});
}
}
}
///////////////////////////////////////////////////////////////////
protected final class ItemQueryResult extends QueryResult {
@Nullable private final ItemDeviceQuery query;
private final Set<ItemEntry> entries;
public ItemQueryResult(@Nullable final ItemDeviceQuery query, final Set<ItemEntry> entries) {
this.query = query;
this.entries = entries;
}
@Nullable
@Override
public ItemDeviceQuery getQuery() {
return query;
}
@Override
public Set<ItemEntry> getEntries() {
return entries;
}
}
protected record ItemEntry(ItemDeviceInfo deviceInfo) implements Entry {
@Override
public Optional<String> getDeviceDataKey() {
return optionalKey(deviceInfo.provider);
}
@Override
public OptionalInt getDeviceEnergyConsumption() {
return OptionalInt.of(deviceInfo.getEnergyConsumption());
}
@Override
public ItemDevice getDevice() {
return deviceInfo.device;
}
}
}