mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-13 11:40:29 +00:00
Make Generic methods per-ComputerContext
- Move the class cache out of Generator into MethodSupplierImpl. This means we cache class generation globally (that's really expensive!), but the class -> method list lookup is local. - Move the global GenericSource/GenericMethod registry out of core, passing in the list of generic methods to the ComputerContext. I'm not entirely thrilled by the slight overlap of MethodSupplierImpl and Generator here, something to clean up in the future.
This commit is contained in:
parent
591a7eca23
commit
910a63214e
@ -19,7 +19,6 @@ import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||
import dan200.computercraft.api.redstone.BundledRedstoneProvider;
|
||||
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.core.asm.GenericMethod;
|
||||
import dan200.computercraft.core.filesystem.WritableFileMount;
|
||||
import dan200.computercraft.impl.detail.DetailRegistryImpl;
|
||||
import dan200.computercraft.impl.network.wired.WiredNodeImpl;
|
||||
@ -78,7 +77,7 @@ public abstract class AbstractComputerCraftAPI implements ComputerCraftAPIServic
|
||||
|
||||
@Override
|
||||
public final void registerGenericSource(GenericSource source) {
|
||||
GenericMethod.register(source);
|
||||
GenericSources.register(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -11,19 +11,24 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The global factory for {@link ILuaAPIFactory}s.
|
||||
*
|
||||
* @see dan200.computercraft.core.ComputerContext.Builder#apiFactories(Collection)
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
||||
*/
|
||||
public final class ApiFactories {
|
||||
private ApiFactories() {
|
||||
}
|
||||
|
||||
private static final Collection<ILuaAPIFactory> factories = new LinkedHashSet<>();
|
||||
private static final Collection<ILuaAPIFactory> factoriesView = Collections.unmodifiableCollection(factories);
|
||||
|
||||
public static synchronized void register(ILuaAPIFactory factory) {
|
||||
static synchronized void register(ILuaAPIFactory factory) {
|
||||
Objects.requireNonNull(factory, "provider cannot be null");
|
||||
factories.add(factory);
|
||||
}
|
||||
|
||||
public static Collection<ILuaAPIFactory> getAll() {
|
||||
return factoriesView;
|
||||
return Collections.unmodifiableCollection(factories);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.impl;
|
||||
|
||||
import dan200.computercraft.api.lua.GenericSource;
|
||||
import dan200.computercraft.core.asm.GenericMethod;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The global registry for {@link GenericSource}s.
|
||||
*
|
||||
* @see dan200.computercraft.core.ComputerContext.Builder#genericMethods(Collection)
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerGenericSource(GenericSource)
|
||||
*/
|
||||
public final class GenericSources {
|
||||
private GenericSources() {
|
||||
}
|
||||
|
||||
private static final Collection<GenericSource> sources = new LinkedHashSet<>();
|
||||
|
||||
static synchronized void register(GenericSource source) {
|
||||
Objects.requireNonNull(source, "provider cannot be null");
|
||||
sources.add(source);
|
||||
}
|
||||
|
||||
public static Collection<GenericMethod> getAllMethods() {
|
||||
return sources.stream().flatMap(GenericMethod::getMethods).toList();
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import dan200.computercraft.core.methods.MethodSupplier;
|
||||
import dan200.computercraft.core.methods.PeripheralMethod;
|
||||
import dan200.computercraft.impl.AbstractComputerCraftAPI;
|
||||
import dan200.computercraft.impl.ApiFactories;
|
||||
import dan200.computercraft.impl.GenericSources;
|
||||
import dan200.computercraft.shared.CommonHooks;
|
||||
import dan200.computercraft.shared.computer.metrics.GlobalMetrics;
|
||||
import dan200.computercraft.shared.config.ConfigSpec;
|
||||
@ -74,6 +75,7 @@ public final class ServerContext {
|
||||
.mainThreadScheduler(mainThread)
|
||||
.luaFactory(luaMachine)
|
||||
.apiFactories(ApiFactories.getAll())
|
||||
.genericMethods(GenericSources.getAllMethods())
|
||||
.build();
|
||||
idAssigner = new IDAssigner(storageDir.resolve("ids.json"));
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
package dan200.computercraft.core;
|
||||
|
||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||
import dan200.computercraft.core.asm.GenericMethod;
|
||||
import dan200.computercraft.core.asm.LuaMethodSupplier;
|
||||
import dan200.computercraft.core.asm.PeripheralMethodSupplier;
|
||||
import dan200.computercraft.core.computer.ComputerThread;
|
||||
@ -165,6 +166,7 @@ public final class ComputerContext {
|
||||
private @Nullable MainThreadScheduler mainThreadScheduler;
|
||||
private @Nullable ILuaMachine.Factory luaFactory;
|
||||
private @Nullable List<ILuaAPIFactory> apiFactories;
|
||||
private @Nullable List<GenericMethod> genericMethods;
|
||||
|
||||
Builder(GlobalEnvironment environment) {
|
||||
this.environment = environment;
|
||||
@ -225,6 +227,21 @@ public final class ComputerContext {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the set of {@link GenericMethod}s used by the {@linkplain MethodSupplier method suppliers}.
|
||||
*
|
||||
* @param genericMethods A list of API factories.
|
||||
* @return {@code this}, for chaining
|
||||
* @see ComputerContext#luaMethods()
|
||||
* @see ComputerContext#peripheralMethods()
|
||||
*/
|
||||
public Builder genericMethods(Collection<GenericMethod> genericMethods) {
|
||||
Objects.requireNonNull(genericMethods);
|
||||
if (this.genericMethods != null) throw new IllegalStateException("Main-thread scheduler already specified");
|
||||
this.genericMethods = List.copyOf(genericMethods);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ComputerContext}.
|
||||
*
|
||||
@ -237,8 +254,8 @@ public final class ComputerContext {
|
||||
mainThreadScheduler == null ? new NoWorkMainThreadScheduler() : mainThreadScheduler,
|
||||
luaFactory == null ? CobaltLuaMachine::new : luaFactory,
|
||||
apiFactories == null ? List.of() : apiFactories,
|
||||
LuaMethodSupplier.create(),
|
||||
PeripheralMethodSupplier.create()
|
||||
LuaMethodSupplier.create(genericMethods == null ? List.of() : genericMethods),
|
||||
PeripheralMethodSupplier.create(genericMethods == null ? List.of() : genericMethods)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,6 @@ import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.primitives.Primitives;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import dan200.computercraft.api.lua.*;
|
||||
import dan200.computercraft.api.peripheral.PeripheralType;
|
||||
import dan200.computercraft.core.methods.NamedMethod;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Type;
|
||||
@ -21,11 +19,8 @@ import org.slf4j.LoggerFactory;
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
|
||||
@ -55,10 +50,6 @@ final class Generator<T> {
|
||||
|
||||
private final Function<T, T> wrap;
|
||||
|
||||
private final LoadingCache<Class<?>, List<NamedMethod<T>>> classCache = CacheBuilder
|
||||
.newBuilder()
|
||||
.build(CacheLoader.from(catching(this::build, Collections.emptyList())));
|
||||
|
||||
private final LoadingCache<Method, Optional<T>> methodCache = CacheBuilder
|
||||
.newBuilder()
|
||||
.build(CacheLoader.from(catching(this::build, Optional.empty())));
|
||||
@ -75,58 +66,8 @@ final class Generator<T> {
|
||||
this.methodDesc = methodDesc.toString();
|
||||
}
|
||||
|
||||
public List<NamedMethod<T>> getMethods(Class<?> klass) {
|
||||
try {
|
||||
return classCache.get(klass);
|
||||
} catch (ExecutionException e) {
|
||||
LOG.error("Error getting methods for {}.", klass.getName(), e.getCause());
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private List<NamedMethod<T>> build(Class<?> klass) {
|
||||
ArrayList<NamedMethod<T>> methods = null;
|
||||
for (var method : klass.getMethods()) {
|
||||
var annotation = method.getAnnotation(LuaFunction.class);
|
||||
if (annotation == null) continue;
|
||||
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
LOG.warn("LuaFunction method {}.{} should be an instance method.", method.getDeclaringClass(), method.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
var instance = methodCache.getUnchecked(method).orElse(null);
|
||||
if (instance == null) continue;
|
||||
|
||||
if (methods == null) methods = new ArrayList<>();
|
||||
addMethod(methods, method, annotation, null, instance);
|
||||
}
|
||||
|
||||
for (var method : GenericMethod.all()) {
|
||||
if (!method.target.isAssignableFrom(klass)) continue;
|
||||
|
||||
var instance = methodCache.getUnchecked(method.method).orElse(null);
|
||||
if (instance == null) continue;
|
||||
|
||||
if (methods == null) methods = new ArrayList<>();
|
||||
addMethod(methods, method.method, method.annotation, method.peripheralType, instance);
|
||||
}
|
||||
|
||||
if (methods == null) return Collections.emptyList();
|
||||
methods.trimToSize();
|
||||
return Collections.unmodifiableList(methods);
|
||||
}
|
||||
|
||||
private void addMethod(List<NamedMethod<T>> methods, Method method, LuaFunction annotation, @Nullable PeripheralType genericType, T instance) {
|
||||
var names = annotation.value();
|
||||
var isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread();
|
||||
if (names.length == 0) {
|
||||
methods.add(new NamedMethod<>(method.getName(), instance, isSimple, genericType));
|
||||
} else {
|
||||
for (var name : names) {
|
||||
methods.add(new NamedMethod<>(name, instance, isSimple, genericType));
|
||||
}
|
||||
}
|
||||
Optional<T> getMethod(Method method) {
|
||||
return methodCache.getUnchecked(method);
|
||||
}
|
||||
|
||||
private Optional<T> build(Method method) {
|
||||
@ -337,7 +278,7 @@ final class Generator<T> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("Guava")
|
||||
private static <T, U> com.google.common.base.Function<T, U> catching(Function<T, U> function, U def) {
|
||||
static <T, U> com.google.common.base.Function<T, U> catching(Function<T, U> function, U def) {
|
||||
return x -> {
|
||||
try {
|
||||
return function.apply(x);
|
||||
|
@ -14,16 +14,14 @@ import org.slf4j.LoggerFactory;
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A generic method is a method belonging to a {@link GenericSource} with a known target.
|
||||
*/
|
||||
public class GenericMethod {
|
||||
public final class GenericMethod {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GenericMethod.class);
|
||||
|
||||
final Method method;
|
||||
@ -31,37 +29,24 @@ public class GenericMethod {
|
||||
final Class<?> target;
|
||||
final @Nullable PeripheralType peripheralType;
|
||||
|
||||
private static final List<GenericSource> sources = new ArrayList<>();
|
||||
private static @Nullable List<GenericMethod> cache;
|
||||
|
||||
GenericMethod(Method method, LuaFunction annotation, Class<?> target, @Nullable PeripheralType peripheralType) {
|
||||
private GenericMethod(Method method, LuaFunction annotation, Class<?> target, @Nullable PeripheralType peripheralType) {
|
||||
this.method = method;
|
||||
this.annotation = annotation;
|
||||
this.target = target;
|
||||
this.peripheralType = peripheralType;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return method.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all public static methods annotated with {@link LuaFunction} which belong to a {@link GenericSource}.
|
||||
*
|
||||
* @param source The given generic source.
|
||||
* @return All available generic methods.
|
||||
*/
|
||||
static List<GenericMethod> all() {
|
||||
if (cache != null) return cache;
|
||||
return cache = sources.stream().flatMap(GenericMethod::getMethods).toList();
|
||||
}
|
||||
|
||||
public static synchronized void register(GenericSource source) {
|
||||
Objects.requireNonNull(source, "Source cannot be null");
|
||||
|
||||
if (cache != null) {
|
||||
LOG.warn("Registering a generic source {} after cache has been built. This source will be ignored.", cache);
|
||||
}
|
||||
|
||||
sources.add(source);
|
||||
}
|
||||
|
||||
private static Stream<GenericMethod> getMethods(GenericSource source) {
|
||||
public static Stream<GenericMethod> getMethods(GenericSource source) {
|
||||
Class<?> klass = source.getClass();
|
||||
var type = source instanceof GenericPeripheral generic ? generic.getType() : null;
|
||||
|
||||
|
@ -6,16 +6,21 @@ package dan200.computercraft.core.asm;
|
||||
|
||||
import dan200.computercraft.api.lua.IDynamicLuaObject;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.core.ComputerContext;
|
||||
import dan200.computercraft.core.methods.LuaMethod;
|
||||
import dan200.computercraft.core.methods.MethodSupplier;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Provides a {@link MethodSupplier} for {@link LuaMethod}s.
|
||||
* <p>
|
||||
* This is used by {@link ComputerContext} to construct {@linkplain ComputerContext#peripheralMethods() the context-wide
|
||||
* method supplier}. It should not be used directly.
|
||||
*/
|
||||
public final class LuaMethodSupplier {
|
||||
@VisibleForTesting
|
||||
static final Generator<LuaMethod> GENERATOR = new Generator<>(LuaMethod.class, List.of(ILuaContext.class),
|
||||
private static final Generator<LuaMethod> GENERATOR = new Generator<>(LuaMethod.class, List.of(ILuaContext.class),
|
||||
m -> (target, context, args) -> context.executeMainThreadTask(() -> ResultHelpers.checkNormalResult(m.apply(target, context, args.escapes())))
|
||||
);
|
||||
private static final IntCache<LuaMethod> DYNAMIC = new IntCache<>(
|
||||
@ -25,8 +30,8 @@ public final class LuaMethodSupplier {
|
||||
private LuaMethodSupplier() {
|
||||
}
|
||||
|
||||
public static MethodSupplier<LuaMethod> create() {
|
||||
return new MethodSupplierImpl<>(GENERATOR, DYNAMIC, x -> x instanceof IDynamicLuaObject dynamic
|
||||
public static MethodSupplier<LuaMethod> create(List<GenericMethod> genericMethods) {
|
||||
return new MethodSupplierImpl<>(genericMethods, GENERATOR, DYNAMIC, x -> x instanceof IDynamicLuaObject dynamic
|
||||
? Objects.requireNonNull(dynamic.getMethodNames(), "Dynamic methods cannot be null")
|
||||
: null
|
||||
);
|
||||
|
@ -4,17 +4,49 @@
|
||||
|
||||
package dan200.computercraft.core.asm;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.api.peripheral.PeripheralType;
|
||||
import dan200.computercraft.core.methods.MethodSupplier;
|
||||
import dan200.computercraft.core.methods.NamedMethod;
|
||||
import dan200.computercraft.core.methods.ObjectSource;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static dan200.computercraft.core.asm.Generator.catching;
|
||||
|
||||
final class MethodSupplierImpl<T> implements MethodSupplier<T> {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MethodSupplierImpl.class);
|
||||
|
||||
private final List<GenericMethod> genericMethods;
|
||||
private final Generator<T> generator;
|
||||
private final IntCache<T> dynamic;
|
||||
private final Function<Object, String[]> dynamicMethods;
|
||||
|
||||
MethodSupplierImpl(Generator<T> generator, IntCache<T> dynamic, Function<Object, String[]> dynamicMethods) {
|
||||
private final LoadingCache<Class<?>, List<NamedMethod<T>>> classCache = CacheBuilder
|
||||
.newBuilder()
|
||||
.build(CacheLoader.from(catching(this::getMethodsImpl, List.of())));
|
||||
|
||||
MethodSupplierImpl(
|
||||
List<GenericMethod> genericMethods,
|
||||
Generator<T> generator,
|
||||
IntCache<T> dynamic,
|
||||
Function<Object, String[]> dynamicMethods
|
||||
) {
|
||||
this.genericMethods = genericMethods;
|
||||
this.generator = generator;
|
||||
this.dynamic = dynamic;
|
||||
this.dynamicMethods = dynamicMethods;
|
||||
@ -22,7 +54,7 @@ final class MethodSupplierImpl<T> implements MethodSupplier<T> {
|
||||
|
||||
@Override
|
||||
public boolean forEachSelfMethod(Object object, UntargetedConsumer<T> consumer) {
|
||||
var methods = generator.getMethods(object.getClass());
|
||||
var methods = getMethods(object.getClass());
|
||||
for (var method : methods) consumer.accept(method.name(), method.method(), method);
|
||||
|
||||
var dynamicMethods = this.dynamicMethods.apply(object);
|
||||
@ -35,14 +67,14 @@ final class MethodSupplierImpl<T> implements MethodSupplier<T> {
|
||||
|
||||
@Override
|
||||
public boolean forEachMethod(Object object, TargetedConsumer<T> consumer) {
|
||||
var methods = generator.getMethods(object.getClass());
|
||||
var methods = getMethods(object.getClass());
|
||||
for (var method : methods) consumer.accept(object, method.name(), method.method(), method);
|
||||
|
||||
var hasMethods = !methods.isEmpty();
|
||||
|
||||
if (object instanceof ObjectSource source) {
|
||||
for (var extra : source.getExtra()) {
|
||||
var extraMethods = generator.getMethods(extra.getClass());
|
||||
var extraMethods = getMethods(extra.getClass());
|
||||
if (!extraMethods.isEmpty()) hasMethods = true;
|
||||
for (var method : extraMethods) consumer.accept(object, method.name(), method.method(), method);
|
||||
}
|
||||
@ -58,4 +90,63 @@ final class MethodSupplierImpl<T> implements MethodSupplier<T> {
|
||||
|
||||
return hasMethods;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
List<NamedMethod<T>> getMethods(Class<?> klass) {
|
||||
try {
|
||||
return classCache.get(klass);
|
||||
} catch (ExecutionException e) {
|
||||
LOG.error("Error getting methods for {}.", klass.getName(), e.getCause());
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
private List<NamedMethod<T>> getMethodsImpl(Class<?> klass) {
|
||||
ArrayList<NamedMethod<T>> methods = null;
|
||||
|
||||
// Find all methods on the current class
|
||||
for (var method : klass.getMethods()) {
|
||||
var annotation = method.getAnnotation(LuaFunction.class);
|
||||
if (annotation == null) continue;
|
||||
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
LOG.warn("LuaFunction method {}.{} should be an instance method.", method.getDeclaringClass(), method.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
var instance = generator.getMethod(method).orElse(null);
|
||||
if (instance == null) continue;
|
||||
|
||||
if (methods == null) methods = new ArrayList<>();
|
||||
addMethod(methods, method, annotation, null, instance);
|
||||
}
|
||||
|
||||
// Inject generic methods
|
||||
for (var method : genericMethods) {
|
||||
if (!method.target.isAssignableFrom(klass)) continue;
|
||||
|
||||
var instance = generator.getMethod(method.method).orElse(null);
|
||||
if (instance == null) continue;
|
||||
|
||||
if (methods == null) methods = new ArrayList<>();
|
||||
addMethod(methods, method.method, method.annotation, method.peripheralType, instance);
|
||||
}
|
||||
|
||||
if (methods == null) return List.of();
|
||||
methods.trimToSize();
|
||||
return Collections.unmodifiableList(methods);
|
||||
}
|
||||
|
||||
private void addMethod(List<NamedMethod<T>> methods, Method method, LuaFunction annotation, @Nullable PeripheralType genericType, T instance) {
|
||||
var names = annotation.value();
|
||||
var isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread();
|
||||
if (names.length == 0) {
|
||||
methods.add(new NamedMethod<>(method.getName(), instance, isSimple, genericType));
|
||||
} else {
|
||||
for (var name : names) {
|
||||
methods.add(new NamedMethod<>(name, instance, isSimple, genericType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,12 +7,19 @@ package dan200.computercraft.core.asm;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
|
||||
import dan200.computercraft.core.ComputerContext;
|
||||
import dan200.computercraft.core.methods.MethodSupplier;
|
||||
import dan200.computercraft.core.methods.PeripheralMethod;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Provides a {@link MethodSupplier} for {@link PeripheralMethod}s.
|
||||
* <p>
|
||||
* This is used by {@link ComputerContext} to construct {@linkplain ComputerContext#peripheralMethods() the context-wide
|
||||
* method supplier}. It should not be used directly.
|
||||
*/
|
||||
public class PeripheralMethodSupplier {
|
||||
private static final Generator<PeripheralMethod> GENERATOR = new Generator<>(PeripheralMethod.class, List.of(ILuaContext.class, IComputerAccess.class),
|
||||
m -> (target, context, computer, args) -> context.executeMainThreadTask(() -> ResultHelpers.checkNormalResult(m.apply(target, context, computer, args.escapes())))
|
||||
@ -21,8 +28,8 @@ public class PeripheralMethodSupplier {
|
||||
method -> (instance, context, computer, args) -> ((IDynamicPeripheral) instance).callMethod(computer, context, method, args)
|
||||
);
|
||||
|
||||
public static MethodSupplier<PeripheralMethod> create() {
|
||||
return new MethodSupplierImpl<>(GENERATOR, DYNAMIC, x -> x instanceof IDynamicPeripheral dynamic
|
||||
public static MethodSupplier<PeripheralMethod> create(List<GenericMethod> genericMethods) {
|
||||
return new MethodSupplierImpl<>(genericMethods, GENERATOR, DYNAMIC, x -> x instanceof IDynamicPeripheral dynamic
|
||||
? Objects.requireNonNull(dynamic.getMethodNames(), "Dynamic methods cannot be null")
|
||||
: null
|
||||
);
|
||||
|
@ -12,10 +12,11 @@ import dan200.computercraft.core.asm.LuaMethodSupplier;
|
||||
import dan200.computercraft.core.methods.LuaMethod;
|
||||
import dan200.computercraft.core.methods.MethodSupplier;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ObjectWrapper implements ILuaContext {
|
||||
private static final MethodSupplier<LuaMethod> LUA_METHODS = LuaMethodSupplier.create();
|
||||
private static final MethodSupplier<LuaMethod> LUA_METHODS = LuaMethodSupplier.create(List.of());
|
||||
|
||||
private final Object object;
|
||||
private final Map<String, LuaMethod> methodMap;
|
||||
|
@ -14,6 +14,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -23,7 +24,7 @@ import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class GeneratorTest {
|
||||
private static final Generator<LuaMethod> GENERATOR = LuaMethodSupplier.GENERATOR;
|
||||
private static final MethodSupplierImpl<LuaMethod> GENERATOR = (MethodSupplierImpl<LuaMethod>) LuaMethodSupplier.create(List.of());
|
||||
|
||||
@Test
|
||||
public void testBasic() {
|
||||
|
Loading…
Reference in New Issue
Block a user