mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-15 04:30:29 +00:00
Small refactoring to generic peripherals
- Remove SidedGenericPeripheral (we never used this!), adding the functionality to GenericPeripheral directly. This is just used on the Fabric side for now, but might make sense with Forge too. - Move GenericPeripheralBuilder into the common project - this is identical between the two projects! - GenericPeripheralBuilder now generates a list of methods internally, rather than being passed the methods. - Add a tiny bit of documentation.
This commit is contained in:
parent
4a5e03c11a
commit
a29a516a3f
@ -12,19 +12,23 @@ import dan200.computercraft.api.peripheral.IComputerAccess;
|
|||||||
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
|
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
import dan200.computercraft.shared.platform.RegistryWrappers;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
class GenericPeripheral implements IDynamicPeripheral {
|
public final class GenericPeripheral implements IDynamicPeripheral {
|
||||||
|
private final BlockEntity tile;
|
||||||
|
private final Direction side;
|
||||||
|
|
||||||
private final String type;
|
private final String type;
|
||||||
private final Set<String> additionalTypes;
|
private final Set<String> additionalTypes;
|
||||||
private final BlockEntity tile;
|
|
||||||
private final List<SaturatedMethod> methods;
|
private final List<SaturatedMethod> methods;
|
||||||
|
|
||||||
GenericPeripheral(BlockEntity tile, @Nullable String name, Set<String> additionalTypes, List<SaturatedMethod> methods) {
|
GenericPeripheral(BlockEntity tile, Direction side, @Nullable String name, Set<String> additionalTypes, List<SaturatedMethod> methods) {
|
||||||
|
this.side = side;
|
||||||
var type = RegistryWrappers.BLOCK_ENTITY_TYPES.getKey(tile.getType());
|
var type = RegistryWrappers.BLOCK_ENTITY_TYPES.getKey(tile.getType());
|
||||||
this.tile = tile;
|
this.tile = tile;
|
||||||
this.type = name != null ? name : type.toString();
|
this.type = name != null ? name : type.toString();
|
||||||
@ -32,6 +36,10 @@ class GenericPeripheral implements IDynamicPeripheral {
|
|||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Direction side() {
|
||||||
|
return side;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getMethodNames() {
|
public String[] getMethodNames() {
|
||||||
var names = new String[methods.size()];
|
var names = new String[methods.size()];
|
||||||
@ -54,7 +62,6 @@ class GenericPeripheral implements IDynamicPeripheral {
|
|||||||
return additionalTypes;
|
return additionalTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public Object getTarget() {
|
public Object getTarget() {
|
||||||
return tile;
|
return tile;
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.shared.peripheral.generic;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import dan200.computercraft.api.peripheral.PeripheralType;
|
||||||
|
import dan200.computercraft.core.asm.NamedMethod;
|
||||||
|
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for a {@link GenericPeripheral}.
|
||||||
|
* <p>
|
||||||
|
* This handles building a list of {@linkplain SaturatedMethod methods} and computing the appropriate
|
||||||
|
* {@link PeripheralType} from the {@linkplain NamedMethod#genericType() methods' peripheral types}.
|
||||||
|
* <p>
|
||||||
|
* See the platform-specific peripheral providers for the usage of this.
|
||||||
|
*/
|
||||||
|
final class GenericPeripheralBuilder {
|
||||||
|
private @Nullable String name;
|
||||||
|
private final Set<String> additionalTypes = new HashSet<>(0);
|
||||||
|
private final ArrayList<SaturatedMethod> methods = new ArrayList<>(0);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
IPeripheral toPeripheral(BlockEntity tile, Direction side) {
|
||||||
|
if (methods.isEmpty()) return null;
|
||||||
|
|
||||||
|
methods.trimToSize();
|
||||||
|
return new GenericPeripheral(tile, side, name, additionalTypes, methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean addMethods(Object target) {
|
||||||
|
var methods = PeripheralMethod.GENERATOR.getMethods(target.getClass());
|
||||||
|
if (methods.isEmpty()) return false;
|
||||||
|
|
||||||
|
var saturatedMethods = this.methods;
|
||||||
|
saturatedMethods.ensureCapacity(saturatedMethods.size() + methods.size());
|
||||||
|
for (var method : methods) {
|
||||||
|
saturatedMethods.add(new SaturatedMethod(target, method.name(), method.method()));
|
||||||
|
|
||||||
|
// If we have a peripheral type, use it. Always pick the smallest one, so it's consistent (assuming mods
|
||||||
|
// don't change).
|
||||||
|
var type = method.genericType();
|
||||||
|
if (type != null && type.getPrimaryType() != null) {
|
||||||
|
var name = type.getPrimaryType();
|
||||||
|
if (this.name == null || this.name.compareTo(name) > 0) this.name = name;
|
||||||
|
}
|
||||||
|
if (type != null) additionalTypes.addAll(type.getAdditionalTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -9,18 +9,20 @@ import dan200.computercraft.api.lua.ILuaContext;
|
|||||||
import dan200.computercraft.api.lua.LuaException;
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
import dan200.computercraft.api.lua.MethodResult;
|
import dan200.computercraft.api.lua.MethodResult;
|
||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
import dan200.computercraft.core.asm.NamedMethod;
|
|
||||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link PeripheralMethod} along with the method's target.
|
||||||
|
*/
|
||||||
final class SaturatedMethod {
|
final class SaturatedMethod {
|
||||||
private final Object target;
|
private final Object target;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final PeripheralMethod method;
|
private final PeripheralMethod method;
|
||||||
|
|
||||||
SaturatedMethod(Object target, NamedMethod<PeripheralMethod> method) {
|
SaturatedMethod(Object target, String name, PeripheralMethod method) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
name = method.name();
|
this.name = name;
|
||||||
this.method = method.method();
|
this.method = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodResult apply(ILuaContext context, IComputerAccess computer, IArguments args) throws LuaException {
|
MethodResult apply(ILuaContext context, IComputerAccess computer, IArguments args) throws LuaException {
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
package dan200.computercraft.shared.peripheral.generic;
|
package dan200.computercraft.shared.peripheral.generic;
|
||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.core.asm.NamedMethod;
|
|
||||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
|
||||||
import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods;
|
import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
@ -15,10 +13,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
|||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class GenericPeripheralProvider {
|
public class GenericPeripheralProvider {
|
||||||
interface Lookup<T> {
|
interface Lookup<T> {
|
||||||
@ -31,53 +26,17 @@ public class GenericPeripheralProvider {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static IPeripheral getPeripheral(Level world, BlockPos pos, Direction side, @Nullable BlockEntity blockEntity) {
|
public static IPeripheral getPeripheral(Level level, BlockPos pos, Direction side, @Nullable BlockEntity blockEntity) {
|
||||||
if (blockEntity == null) return null;
|
if (blockEntity == null) return null;
|
||||||
|
|
||||||
var saturated = new GenericPeripheralBuilder();
|
var builder = new GenericPeripheralBuilder();
|
||||||
|
builder.addMethods(blockEntity);
|
||||||
var tileMethods = PeripheralMethod.GENERATOR.getMethods(blockEntity.getClass());
|
|
||||||
if (!tileMethods.isEmpty()) saturated.addMethods(blockEntity, tileMethods);
|
|
||||||
|
|
||||||
for (var lookup : lookups) {
|
for (var lookup : lookups) {
|
||||||
var contents = lookup.find(world, pos, blockEntity.getBlockState(), blockEntity, side);
|
var contents = lookup.find(level, pos, blockEntity.getBlockState(), blockEntity, side);
|
||||||
if (contents == null) continue;
|
if (contents != null) builder.addMethods(contents);
|
||||||
|
|
||||||
var methods = PeripheralMethod.GENERATOR.getMethods(contents.getClass());
|
|
||||||
if (!methods.isEmpty()) saturated.addMethods(contents, methods);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return saturated.toPeripheral(blockEntity);
|
return builder.toPeripheral(blockEntity, side);
|
||||||
}
|
|
||||||
|
|
||||||
private static class GenericPeripheralBuilder {
|
|
||||||
private @Nullable String name;
|
|
||||||
private final Set<String> additionalTypes = new HashSet<>(0);
|
|
||||||
private final ArrayList<SaturatedMethod> methods = new ArrayList<>(0);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
IPeripheral toPeripheral(BlockEntity tile) {
|
|
||||||
if (methods.isEmpty()) return null;
|
|
||||||
|
|
||||||
methods.trimToSize();
|
|
||||||
return new GenericPeripheral(tile, name, additionalTypes, methods);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addMethods(Object target, List<NamedMethod<PeripheralMethod>> methods) {
|
|
||||||
var saturatedMethods = this.methods;
|
|
||||||
saturatedMethods.ensureCapacity(saturatedMethods.size() + methods.size());
|
|
||||||
for (var method : methods) {
|
|
||||||
saturatedMethods.add(new SaturatedMethod(target, method));
|
|
||||||
|
|
||||||
// If we have a peripheral type, use it. Always pick the smallest one, so it's consistent (assuming mods
|
|
||||||
// don't change).
|
|
||||||
var type = method.genericType();
|
|
||||||
if (type != null && type.getPrimaryType() != null) {
|
|
||||||
var name = type.getPrimaryType();
|
|
||||||
if (this.name == null || this.name.compareTo(name) > 0) this.name = name;
|
|
||||||
}
|
|
||||||
if (type != null) additionalTypes.addAll(type.getAdditionalTypes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.shared.peripheral.generic;
|
|
||||||
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class SidedGenericPeripheral extends GenericPeripheral {
|
|
||||||
private final Direction direction;
|
|
||||||
|
|
||||||
SidedGenericPeripheral(BlockEntity tile, Direction direction, @Nullable String name, Set<String> additionalTypes, List<SaturatedMethod> methods) {
|
|
||||||
super(tile, name, additionalTypes, methods);
|
|
||||||
this.direction = direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Direction direction() {
|
|
||||||
return direction;
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,7 +12,6 @@ import dan200.computercraft.api.peripheral.GenericPeripheral;
|
|||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.peripheral.PeripheralType;
|
import dan200.computercraft.api.peripheral.PeripheralType;
|
||||||
import dan200.computercraft.shared.peripheral.generic.SidedGenericPeripheral;
|
|
||||||
import dan200.computercraft.shared.platform.FabricContainerTransfer;
|
import dan200.computercraft.shared.platform.FabricContainerTransfer;
|
||||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage;
|
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage;
|
||||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
|
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
|
||||||
@ -157,7 +156,7 @@ public class InventoryMethods implements GenericPeripheral {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private static SlottedStorage<ItemVariant> extractHandler(IPeripheral peripheral) {
|
private static SlottedStorage<ItemVariant> extractHandler(IPeripheral peripheral) {
|
||||||
var object = peripheral.getTarget();
|
var object = peripheral.getTarget();
|
||||||
var direction = peripheral instanceof SidedGenericPeripheral sided ? sided.direction() : null;
|
var direction = peripheral instanceof dan200.computercraft.shared.peripheral.generic.GenericPeripheral sided ? sided.side() : null;
|
||||||
|
|
||||||
if (object instanceof BlockEntity blockEntity) {
|
if (object instanceof BlockEntity blockEntity) {
|
||||||
if (blockEntity.isRemoved()) return null;
|
if (blockEntity.isRemoved()) return null;
|
||||||
|
@ -5,18 +5,16 @@
|
|||||||
package dan200.computercraft.shared.peripheral.generic;
|
package dan200.computercraft.shared.peripheral.generic;
|
||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.core.asm.NamedMethod;
|
|
||||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
|
||||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
import net.minecraftforge.common.util.NonNullConsumer;
|
import net.minecraftforge.common.util.NonNullConsumer;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class GenericPeripheralProvider {
|
public class GenericPeripheralProvider {
|
||||||
private static final ArrayList<Capability<?>> capabilities = new ArrayList<>();
|
private static final ArrayList<Capability<?>> capabilities = new ArrayList<>();
|
||||||
@ -27,57 +25,20 @@ public class GenericPeripheralProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static IPeripheral getPeripheral(Level world, BlockPos pos, Direction side, NonNullConsumer<Object> invalidate) {
|
public static IPeripheral getPeripheral(Level level, BlockPos pos, Direction side, NonNullConsumer<Object> invalidate) {
|
||||||
var tile = world.getBlockEntity(pos);
|
var blockEntity = level.getBlockEntity(pos);
|
||||||
if (tile == null) return null;
|
if (blockEntity == null) return null;
|
||||||
|
|
||||||
var saturated = new GenericPeripheralBuilder();
|
var builder = new GenericPeripheralBuilder();
|
||||||
|
builder.addMethods(blockEntity);
|
||||||
var tileMethods = PeripheralMethod.GENERATOR.getMethods(tile.getClass());
|
|
||||||
if (!tileMethods.isEmpty()) saturated.addMethods(tile, tileMethods);
|
|
||||||
|
|
||||||
for (var capability : capabilities) {
|
for (var capability : capabilities) {
|
||||||
var wrapper = CapabilityUtil.getCapability(tile, capability, side);
|
var wrapper = CapabilityUtil.getCapability(blockEntity, capability, side);
|
||||||
wrapper.ifPresent(contents -> {
|
wrapper.ifPresent(contents -> {
|
||||||
var capabilityMethods = PeripheralMethod.GENERATOR.getMethods(contents.getClass());
|
if (builder.addMethods(contents)) CapabilityUtil.addListener(wrapper, invalidate);
|
||||||
if (capabilityMethods.isEmpty()) return;
|
|
||||||
|
|
||||||
saturated.addMethods(contents, capabilityMethods);
|
|
||||||
CapabilityUtil.addListener(wrapper, invalidate);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return saturated.toPeripheral(tile);
|
return builder.toPeripheral(blockEntity, side);
|
||||||
}
|
|
||||||
|
|
||||||
private static class GenericPeripheralBuilder {
|
|
||||||
private @Nullable String name;
|
|
||||||
private final Set<String> additionalTypes = new HashSet<>(0);
|
|
||||||
private final ArrayList<SaturatedMethod> methods = new ArrayList<>(0);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
IPeripheral toPeripheral(BlockEntity tile) {
|
|
||||||
if (methods.isEmpty()) return null;
|
|
||||||
|
|
||||||
methods.trimToSize();
|
|
||||||
return new GenericPeripheral(tile, name, additionalTypes, methods);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addMethods(Object target, List<NamedMethod<PeripheralMethod>> methods) {
|
|
||||||
var saturatedMethods = this.methods;
|
|
||||||
saturatedMethods.ensureCapacity(saturatedMethods.size() + methods.size());
|
|
||||||
for (var method : methods) {
|
|
||||||
saturatedMethods.add(new SaturatedMethod(target, method));
|
|
||||||
|
|
||||||
// If we have a peripheral type, use it. Always pick the smallest one, so it's consistent (assuming mods
|
|
||||||
// don't change).
|
|
||||||
var type = method.genericType();
|
|
||||||
if (type != null && type.getPrimaryType() != null) {
|
|
||||||
var name = type.getPrimaryType();
|
|
||||||
if (this.name == null || this.name.compareTo(name) > 0) this.name = name;
|
|
||||||
}
|
|
||||||
if (type != null) additionalTypes.addAll(type.getAdditionalTypes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user