1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-26 07:03:22 +00:00

Prepare dan200.computercraft.core for splitting off

- Move core-specific config options to a separate CoreConfig class.
 - Use class-specific loggers, instead of a global one.
 - Use log markers instead of a logComputerErrors option.
This commit is contained in:
Jonathan Coates 2022-11-04 19:56:45 +00:00
parent 6cc86b0ae5
commit e4e528e5bf
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
33 changed files with 300 additions and 209 deletions

View File

@ -5,8 +5,6 @@
*/
package dan200.computercraft;
import dan200.computercraft.core.apis.http.options.Action;
import dan200.computercraft.core.apis.http.options.AddressRule;
import dan200.computercraft.shared.Config;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
@ -14,37 +12,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.OptionalInt;
import java.util.concurrent.TimeUnit;
@Mod(ComputerCraft.MOD_ID)
public final class ComputerCraft {
public static final String MOD_ID = "computercraft";
public static int computerSpaceLimit = 1000 * 1000;
public static int floppySpaceLimit = 125 * 1000;
public static int maximumFilesOpen = 128;
public static boolean disableLua51Features = false;
public static String defaultComputerSettings = "";
public static boolean logComputerErrors = true;
public static boolean commandRequireCreative = true;
public static int computerThreads = 1;
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(10);
public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(5);
public static boolean httpEnabled = true;
public static boolean httpWebsocketEnabled = true;
public static List<AddressRule> httpRules = List.of(
AddressRule.parse("$private", OptionalInt.empty(), Action.DENY.toPartial()),
AddressRule.parse("*", OptionalInt.empty(), Action.ALLOW.toPartial())
);
public static int httpMaxRequests = 16;
public static int httpMaxWebsockets = 4;
public static int httpDownloadBandwidth = 32 * 1024 * 1024;
public static int httpUploadBandwidth = 32 * 1024 * 1024;
public static boolean enableCommandBlock = false;
public static int modemRange = 64;

View File

@ -0,0 +1,42 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core;
import dan200.computercraft.core.apis.http.options.Action;
import dan200.computercraft.core.apis.http.options.AddressRule;
import java.util.List;
import java.util.OptionalInt;
import java.util.concurrent.TimeUnit;
/**
* Config options for ComputerCraft's Lua runtime.
*/
public final class CoreConfig {
// TODO: Ideally this would be an instance in {@link ComputerContext}, but sharing this everywhere it needs to be is
// tricky.
private CoreConfig() {
}
public static int maximumFilesOpen = 128;
public static boolean disableLua51Features = false;
public static String defaultComputerSettings = "";
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(10);
public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(5);
public static boolean httpEnabled = true;
public static boolean httpWebsocketEnabled = true;
public static List<AddressRule> httpRules = List.of(
AddressRule.parse("$private", OptionalInt.empty(), Action.DENY.toPartial()),
AddressRule.parse("*", OptionalInt.empty(), Action.ALLOW.toPartial())
);
public static int httpMaxRequests = 16;
public static int httpMaxWebsockets = 4;
public static int httpDownloadBandwidth = 32 * 1024 * 1024;
public static int httpUploadBandwidth = 32 * 1024 * 1024;
}

View File

@ -0,0 +1,26 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
/**
* Shared log markers for ComputerCraft.
*/
public final class Logging {
public static final Marker COMPUTER_ERROR = MarkerFactory.getMarker("COMPUTER_ERROR");
public static final Marker HTTP_ERROR = MarkerFactory.getMarker("COMPUTER_ERROR.HTTP");
public static final Marker JAVA_ERROR = MarkerFactory.getMarker("COMPUTER_ERROR.JAVA");
static {
HTTP_ERROR.add(COMPUTER_ERROR);
JAVA_ERROR.add(JAVA_ERROR);
}
private Logging() {
}
}

View File

@ -5,12 +5,13 @@
*/
package dan200.computercraft.core.apis;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IWorkMonitor;
import dan200.computercraft.core.filesystem.FileSystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.util.HashSet;
@ -18,6 +19,8 @@
import java.util.Set;
public abstract class ComputerAccess implements IComputerAccess {
private static final Logger LOG = LoggerFactory.getLogger(ComputerAccess.class);
private final IAPIEnvironment environment;
private final Set<String> mounts = new HashSet<>();
@ -28,7 +31,7 @@ protected ComputerAccess(IAPIEnvironment environment) {
public void unmountAll() {
var fileSystem = environment.getFileSystem();
if (!mounts.isEmpty()) {
ComputerCraft.log.warn("Peripheral or API called mount but did not call unmount for {}", mounts);
LOG.warn("Peripheral or API called mount but did not call unmount for {}", mounts);
}
for (var mount : mounts) {

View File

@ -5,11 +5,11 @@
*/
package dan200.computercraft.core.apis;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.apis.http.*;
import dan200.computercraft.core.apis.http.request.HttpRequest;
import dan200.computercraft.core.apis.http.websocket.Websocket;
@ -36,8 +36,8 @@ public class HTTPAPI implements ILuaAPI {
private final IAPIEnvironment apiEnvironment;
private final ResourceGroup<CheckUrl> checkUrls = new ResourceGroup<>(ResourceGroup.DEFAULT);
private final ResourceGroup<HttpRequest> requests = new ResourceQueue<>(() -> ComputerCraft.httpMaxRequests);
private final ResourceGroup<Websocket> websockets = new ResourceGroup<>(() -> ComputerCraft.httpMaxWebsockets);
private final ResourceGroup<HttpRequest> requests = new ResourceQueue<>(() -> CoreConfig.httpMaxRequests);
private final ResourceGroup<Websocket> websockets = new ResourceGroup<>(() -> CoreConfig.httpMaxWebsockets);
public HTTPAPI(IAPIEnvironment environment) {
apiEnvironment = environment;
@ -137,7 +137,7 @@ public final Object[] checkURL(String address) throws LuaException {
@LuaFunction
public final Object[] websocket(String address, Optional<Map<?, ?>> headerTbl) throws LuaException {
if (!ComputerCraft.httpWebsocketEnabled) {
if (!CoreConfig.httpWebsocketEnabled) {
throw new LuaException("Websocket connections are disabled");
}

View File

@ -5,7 +5,7 @@
*/
package dan200.computercraft.core.apis.http;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.apis.http.options.Action;
import dan200.computercraft.core.apis.http.options.AddressRule;
import dan200.computercraft.core.apis.http.options.Options;
@ -22,6 +22,8 @@
import io.netty.handler.timeout.ReadTimeoutException;
import io.netty.handler.traffic.AbstractTrafficShapingHandler;
import io.netty.handler.traffic.GlobalTrafficShapingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.net.ssl.SSLException;
@ -37,6 +39,8 @@
* Just a shared object for executing simple HTTP related tasks.
*/
public final class NetworkUtils {
private static final Logger LOG = LoggerFactory.getLogger(NetworkUtils.class);
public static final ScheduledThreadPoolExecutor EXECUTOR = new ScheduledThreadPoolExecutor(
4,
ThreadUtils.builder("Network")
@ -50,7 +54,7 @@ public final class NetworkUtils {
);
public static final AbstractTrafficShapingHandler SHAPING_HANDLER = new GlobalTrafficShapingHandler(
EXECUTOR, ComputerCraft.httpUploadBandwidth, ComputerCraft.httpDownloadBandwidth
EXECUTOR, CoreConfig.httpUploadBandwidth, CoreConfig.httpDownloadBandwidth
);
static {
@ -75,7 +79,7 @@ private static TrustManagerFactory getTrustManager() {
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
} catch (Exception e) {
ComputerCraft.log.error("Cannot setup trust manager", e);
LOG.error("Cannot setup trust manager", e);
}
return trustManager = tmf;
@ -92,7 +96,7 @@ public static SslContext getSslContext() throws HTTPRequestException {
.trustManager(getTrustManager())
.build();
} catch (SSLException e) {
ComputerCraft.log.error("Cannot construct SSL context", e);
LOG.error("Cannot construct SSL context", e);
triedSslContext = true;
sslContext = null;
@ -102,7 +106,7 @@ public static SslContext getSslContext() throws HTTPRequestException {
}
public static void reloadConfig() {
SHAPING_HANDLER.configure(ComputerCraft.httpUploadBandwidth, ComputerCraft.httpDownloadBandwidth);
SHAPING_HANDLER.configure(CoreConfig.httpUploadBandwidth, CoreConfig.httpDownloadBandwidth);
}
public static void reset() {
@ -150,7 +154,7 @@ public static InetSocketAddress getAddress(String host, int port, boolean ssl) t
* @throws HTTPRequestException If the host is not permitted
*/
public static Options getOptions(String host, InetSocketAddress address) throws HTTPRequestException {
var options = AddressRule.apply(ComputerCraft.httpRules, host, address);
var options = AddressRule.apply(CoreConfig.httpRules, host, address);
if (options.action == Action.DENY) throw new HTTPRequestException("Domain not permitted");
return options;
}

View File

@ -6,7 +6,8 @@
package dan200.computercraft.core.apis.http.options;
import com.google.common.net.InetAddresses;
import dan200.computercraft.ComputerCraft;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@ -18,6 +19,8 @@
* @see AddressRule#apply(Iterable, String, InetSocketAddress) for the actual handling of this rule.
*/
interface AddressPredicate {
Logger LOG = LoggerFactory.getLogger(AddressPredicate.class);
default boolean matches(String domain) {
return false;
}
@ -53,7 +56,7 @@ public static HostRange parse(String addressStr, String prefixSizeStr) {
try {
prefixSize = Integer.parseInt(prefixSizeStr);
} catch (NumberFormatException e) {
ComputerCraft.log.error(
LOG.error(
"Malformed http whitelist/blacklist entry '{}': Cannot extract size of CIDR mask from '{}'.",
addressStr + '/' + prefixSizeStr, prefixSizeStr
);
@ -64,7 +67,7 @@ public static HostRange parse(String addressStr, String prefixSizeStr) {
try {
address = InetAddresses.forString(addressStr);
} catch (IllegalArgumentException e) {
ComputerCraft.log.error(
LOG.error(
"Malformed http whitelist/blacklist entry '{}': Cannot extract IP address from '{}'.",
addressStr + '/' + prefixSizeStr, prefixSizeStr
);

View File

@ -5,7 +5,7 @@
*/
package dan200.computercraft.core.apis.http.request;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.Logging;
import dan200.computercraft.core.apis.IAPIEnvironment;
import dan200.computercraft.core.apis.http.HTTPRequestException;
import dan200.computercraft.core.apis.http.NetworkUtils;
@ -21,6 +21,8 @@
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URISyntaxException;
@ -34,6 +36,7 @@
* Represents an in-progress HTTP request.
*/
public class HttpRequest extends Resource<HttpRequest> {
private static final Logger LOG = LoggerFactory.getLogger(HttpRequest.class);
private static final String SUCCESS_EVENT = "http_success";
private static final String FAILURE_EVENT = "http_failure";
@ -171,7 +174,7 @@ protected void initChannel(SocketChannel ch) {
failure(e.getMessage());
} catch (Exception e) {
failure(NetworkUtils.toFriendlyError(e));
if (ComputerCraft.logComputerErrors) ComputerCraft.log.error("Error in HTTP request", e);
LOG.error(Logging.HTTP_ERROR, "Error in HTTP request", e);
}
}

View File

@ -5,7 +5,7 @@
*/
package dan200.computercraft.core.apis.http.request;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.Logging;
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
import dan200.computercraft.core.apis.handles.BinaryReadableHandle;
import dan200.computercraft.core.apis.handles.EncodedReadableHandle;
@ -17,6 +17,8 @@
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.net.URI;
@ -29,6 +31,8 @@
import static dan200.computercraft.core.apis.http.request.HttpRequest.getHeaderSize;
public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpObject> implements Closeable {
private static final Logger LOG = LoggerFactory.getLogger(HttpRequestHandler.class);
/**
* Same as {@link io.netty.handler.codec.MessageAggregator}.
*/
@ -158,7 +162,7 @@ public void channelRead0(ChannelHandlerContext ctx, HttpObject message) {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (ComputerCraft.logComputerErrors) ComputerCraft.log.error("Error handling HTTP response", cause);
LOG.error(Logging.HTTP_ERROR, "Error handling HTTP response", cause);
request.failure(NetworkUtils.toFriendlyError(cause));
}

View File

@ -6,7 +6,7 @@
package dan200.computercraft.core.apis.http.websocket;
import com.google.common.base.Strings;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.Logging;
import dan200.computercraft.core.apis.IAPIEnvironment;
import dan200.computercraft.core.apis.http.HTTPRequestException;
import dan200.computercraft.core.apis.http.NetworkUtils;
@ -26,6 +26,8 @@
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.ref.WeakReference;
import java.net.URI;
@ -36,6 +38,8 @@
* Provides functionality to verify and connect to a remote websocket.
*/
public class Websocket extends Resource<Websocket> {
private static final Logger LOG = LoggerFactory.getLogger(Websocket.class);
/**
* We declare the maximum size to be 2^30 bytes. While messages can be much longer, we set an arbitrary limit as
* working with larger messages (especially within a Lua VM) is absurd.
@ -151,7 +155,7 @@ protected void initChannel(SocketChannel ch) {
failure(e.getMessage());
} catch (Exception e) {
failure(NetworkUtils.toFriendlyError(e));
if (ComputerCraft.logComputerErrors) ComputerCraft.log.error("Error in websocket", e);
LOG.error(Logging.HTTP_ERROR, "Error in websocket", e);
}
}

View File

@ -10,7 +10,6 @@
import com.google.common.cache.LoadingCache;
import com.google.common.primitives.Primitives;
import com.google.common.reflect.TypeToken;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
@ -19,6 +18,8 @@
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -35,6 +36,8 @@
import static org.objectweb.asm.Opcodes.*;
public final class Generator<T> {
private static final Logger LOG = LoggerFactory.getLogger(Generator.class);
private static final AtomicInteger METHOD_ID = new AtomicInteger();
private static final String METHOD_NAME = "apply";
@ -79,7 +82,7 @@ public List<NamedMethod<T>> getMethods(@Nonnull Class<?> klass) {
try {
return classCache.get(klass);
} catch (ExecutionException e) {
ComputerCraft.log.error("Error getting methods for {}.", klass.getName(), e.getCause());
LOG.error("Error getting methods for {}.", klass.getName(), e.getCause());
return Collections.emptyList();
}
}
@ -92,7 +95,7 @@ private List<NamedMethod<T>> build(Class<?> klass) {
if (annotation == null) continue;
if (Modifier.isStatic(method.getModifiers())) {
ComputerCraft.log.warn("LuaFunction method {}.{} should be an instance method.", method.getDeclaringClass(), method.getName());
LOG.warn("LuaFunction method {}.{} should be an instance method.", method.getDeclaringClass(), method.getName());
continue;
}
@ -137,32 +140,32 @@ private Optional<T> build(Method method) {
// Instance methods must be final - this prevents them being overridden and potentially exposed twice.
if (!Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) {
ComputerCraft.log.warn("Lua Method {} should be final.", name);
LOG.warn("Lua Method {} should be final.", name);
}
if (!Modifier.isPublic(modifiers)) {
ComputerCraft.log.error("Lua Method {} should be a public method.", name);
LOG.error("Lua Method {} should be a public method.", name);
return Optional.empty();
}
if (!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
ComputerCraft.log.error("Lua Method {} should be on a public class.", name);
LOG.error("Lua Method {} should be on a public class.", name);
return Optional.empty();
}
ComputerCraft.log.debug("Generating method wrapper for {}.", name);
LOG.debug("Generating method wrapper for {}.", name);
var exceptions = method.getExceptionTypes();
for (var exception : exceptions) {
if (exception != LuaException.class) {
ComputerCraft.log.error("Lua Method {} cannot throw {}.", name, exception.getName());
LOG.error("Lua Method {} cannot throw {}.", name, exception.getName());
return Optional.empty();
}
}
var annotation = method.getAnnotation(LuaFunction.class);
if (annotation.unsafe() && annotation.mainThread()) {
ComputerCraft.log.error("Lua Method {} cannot use unsafe and mainThread", name);
LOG.error("Lua Method {} cannot use unsafe and mainThread", name);
return Optional.empty();
}
@ -180,7 +183,7 @@ private Optional<T> build(Method method) {
var instance = klass.asSubclass(base).getDeclaredConstructor().newInstance();
return Optional.of(annotation.mainThread() ? wrap.apply(instance) : instance);
} catch (ReflectiveOperationException | ClassFormatError | RuntimeException e) {
ComputerCraft.log.error("Error generating wrapper for {}.", name, e);
LOG.error("Error generating wrapper for {}.", name, e);
return Optional.empty();
}
@ -317,7 +320,7 @@ private Boolean loadArg(MethodVisitor mw, Class<?> target, Method method, boolea
return true;
}
ComputerCraft.log.error("Unknown parameter type {} for method {}.{}.",
LOG.error("Unknown parameter type {} for method {}.{}.",
arg.getName(), method.getDeclaringClass().getName(), method.getName());
return null;
}
@ -330,7 +333,7 @@ private static <T, U> com.google.common.base.Function<T, U> catching(Function<T,
} catch (Exception | LinkageError e) {
// LinkageError due to possible codegen bugs and NoClassDefFoundError. The latter occurs when fetching
// methods on a class which references non-existent (i.e. client-only) types.
ComputerCraft.log.error("Error generating @LuaFunctions", e);
LOG.error("Error generating @LuaFunctions", e);
return def;
}
};

View File

@ -5,11 +5,12 @@
*/
package dan200.computercraft.core.asm;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.peripheral.GenericPeripheral;
import dan200.computercraft.api.peripheral.PeripheralType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.lang.reflect.Method;
@ -24,6 +25,8 @@
* A generic method is a method belonging to a {@link GenericSource} with a known target.
*/
public class GenericMethod {
private static final Logger LOG = LoggerFactory.getLogger(GenericMethod.class);
final Method method;
final LuaFunction annotation;
final Class<?> target;
@ -53,7 +56,7 @@ public static synchronized void register(@Nonnull GenericSource source) {
Objects.requireNonNull(source, "Source cannot be null");
if (cache != null) {
ComputerCraft.log.warn("Registering a generic source {} after cache has been built. This source will be ignored.", cache);
LOG.warn("Registering a generic source {} after cache has been built. This source will be ignored.", cache);
}
sources.add(source);
@ -69,13 +72,13 @@ private static Stream<GenericMethod> getMethods(GenericSource source) {
if (annotation == null) return null;
if (!Modifier.isStatic(method.getModifiers())) {
ComputerCraft.log.error("GenericSource method {}.{} should be static.", method.getDeclaringClass(), method.getName());
LOG.error("GenericSource method {}.{} should be static.", method.getDeclaringClass(), method.getName());
return null;
}
var types = method.getGenericParameterTypes();
if (types.length == 0) {
ComputerCraft.log.error("GenericSource method {}.{} has no parameters.", method.getDeclaringClass(), method.getName());
LOG.error("GenericSource method {}.{} has no parameters.", method.getDeclaringClass(), method.getName());
return null;
}

View File

@ -5,9 +5,10 @@
*/
package dan200.computercraft.core.asm;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.LuaTable;
import org.objectweb.asm.MethodVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.lang.reflect.*;
@ -18,6 +19,7 @@
import static org.objectweb.asm.Opcodes.ICONST_0;
final class Reflect {
private static final Logger LOG = LoggerFactory.getLogger(Reflect.class);
static final java.lang.reflect.Type OPTIONAL_IN = Optional.class.getTypeParameters()[0];
private Reflect() {
@ -54,7 +56,7 @@ static Class<?> getRawType(Method method, Type root, boolean allowParameter) {
continue;
}
ComputerCraft.log.error("Method {}.{} has generic type {} with non-wildcard argument {}.", method.getDeclaringClass(), method.getName(), root, arg);
LOG.error("Method {}.{} has generic type {} with non-wildcard argument {}.", method.getDeclaringClass(), method.getName(), root, arg);
return null;
}
}
@ -64,7 +66,7 @@ static Class<?> getRawType(Method method, Type root, boolean allowParameter) {
continue;
}
ComputerCraft.log.error("Method {}.{} has unknown generic type {}.", method.getDeclaringClass(), method.getName(), root);
LOG.error("Method {}.{} has unknown generic type {}.", method.getDeclaringClass(), method.getName(), root);
return null;
}
}

View File

@ -5,11 +5,11 @@
*/
package dan200.computercraft.core.computer;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.core.ComputerContext;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.apis.*;
import dan200.computercraft.core.filesystem.FileSystem;
import dan200.computercraft.core.filesystem.FileSystemException;
@ -19,6 +19,8 @@
import dan200.computercraft.core.metrics.MetricsObserver;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.IoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -51,6 +53,7 @@
* method. This should only be called when the computer is actually on ({@link #isOn}).
*/
final class ComputerExecutor {
private static final Logger LOG = LoggerFactory.getLogger(ComputerExecutor.class);
private static final int QUEUE_LIMIT = 256;
private final Computer computer;
@ -175,7 +178,7 @@ final class ComputerExecutor {
apis.add(new FSAPI(environment));
apis.add(new PeripheralAPI(environment));
apis.add(new OSAPI(environment));
if (ComputerCraft.httpEnabled) apis.add(new HTTPAPI(environment));
if (CoreConfig.httpEnabled) apis.add(new HTTPAPI(environment));
// Load in the externally registered APIs.
for (var factory : ApiFactories.getAll()) {
@ -341,7 +344,7 @@ private FileSystem createFileSystem() {
return filesystem;
} catch (FileSystemException e) {
if (filesystem != null) filesystem.close();
ComputerCraft.log.error("Cannot mount computer filesystem", e);
LOG.error("Cannot mount computer filesystem", e);
displayFailure("Cannot mount computer system", null);
return null;

View File

@ -7,9 +7,11 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.errorprone.annotations.concurrent.GuardedBy;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.ComputerContext;
import dan200.computercraft.core.Logging;
import dan200.computercraft.shared.util.ThreadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -52,6 +54,7 @@
* @see ComputerExecutor For how computers actually do execution.
*/
public final class ComputerThread {
private static final Logger LOG = LoggerFactory.getLogger(ComputerThread.class);
private static final ThreadFactory monitorFactory = ThreadUtils.factory("Computer-Monitor");
private static final ThreadFactory workerFactory = ThreadUtils.factory("Computer-Worker");
@ -160,7 +163,7 @@ public ComputerThread(int threadCount) {
@GuardedBy("threadLock")
private void addWorker(int index) {
ComputerCraft.log.trace("Spawning new worker {}.", index);
LOG.trace("Spawning new worker {}.", index);
(workers[index] = new Worker(index)).owner.start();
workerCount++;
}
@ -176,7 +179,7 @@ private void ensureRunning() {
threadLock.lock();
try {
ComputerCraft.log.trace("Possibly spawning a worker or monitor.");
LOG.trace("Possibly spawning a worker or monitor.");
if (monitor == null || !monitor.isAlive()) (monitor = monitorFactory.newThread(new Monitor())).start();
if (idleWorkers.get() == 0 || workerCount < workers.length) {
@ -355,7 +358,7 @@ private void afterWork(Worker runner, ComputerExecutor executor) {
var currentThread = executor.executingThread.getAndSet(null);
if (currentThread != runner.owner) {
ComputerCraft.log.error(
LOG.error(
"Expected computer #{} to be running on {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.",
executor.getComputer().getID(),
runner.owner.getName(),
@ -422,7 +425,7 @@ private void workerFinished(Worker worker) {
// worker finishes normally.
if (!worker.running.getAndSet(false)) return;
ComputerCraft.log.trace("Worker {} finished.", worker.index);
LOG.trace("Worker {} finished.", worker.index);
var executor = worker.currentExecutor.getAndSet(null);
if (executor != null) executor.afterWork();
@ -432,7 +435,7 @@ private void workerFinished(Worker worker) {
workerCount--;
if (workers[worker.index] != worker) {
ComputerCraft.log.error("Worker {} closed, but new runner has been spawned.", worker.index);
LOG.error("Worker {} closed, but new runner has been spawned.", worker.index);
} else if (state.get() == RUNNING || (state.get() == STOPPING && hasPendingWork())) {
addWorker(worker.index);
workerCount++;
@ -453,11 +456,11 @@ private void workerFinished(Worker worker) {
private final class Monitor implements Runnable {
@Override
public void run() {
ComputerCraft.log.trace("Monitor starting.");
LOG.trace("Monitor starting.");
try {
runImpl();
} finally {
ComputerCraft.log.trace("Monitor shutting down. Current state is {}.", state.get());
LOG.trace("Monitor shutting down. Current state is {}.", state.get());
}
}
@ -470,7 +473,7 @@ private void runImpl() {
// flags, which are far less granular.
monitorWakeup.awaitNanos(isBusy() ? scaledPeriod() : MONITOR_WAKEUP);
} catch (InterruptedException e) {
ComputerCraft.log.error("Monitor thread interrupted. Computers may behave very badly!", e);
LOG.error("Monitor thread interrupted. Computers may behave very badly!", e);
break;
} finally {
computerLock.unlock();
@ -592,7 +595,7 @@ private void runImpl() {
while (!executor.executingThread.compareAndSet(null, owner)) {
var existing = executor.executingThread.get();
if (existing != null) {
ComputerCraft.log.error(
LOG.error(
"Trying to run computer #{} on thread {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.",
executor.getComputer().getID(), owner.getName(), existing.getName()
);
@ -614,7 +617,7 @@ private void runImpl() {
try {
executor.work();
} catch (Exception | LinkageError | VirtualMachineError e) {
ComputerCraft.log.error("Error running task on computer #" + executor.getComputer().getID(), e);
LOG.error("Error running task on computer #" + executor.getComputer().getID(), e);
// Tear down the computer immediately. There's no guarantee it's well-behaved from now on.
executor.fastFail();
} finally {
@ -625,7 +628,7 @@ private void runImpl() {
}
private void reportTimeout(ComputerExecutor executor, long time) {
if (!ComputerCraft.logComputerErrors) return;
if (!LOG.isErrorEnabled(Logging.COMPUTER_ERROR)) return;
// Attempt to debounce stack trace reporting, limiting ourselves to one every second. There's no need to be
// ultra-precise in our atomics, as long as one of them wins!
@ -654,7 +657,7 @@ private void reportTimeout(ComputerExecutor executor, long time) {
executor.printState(builder);
ComputerCraft.log.warn(builder.toString());
LOG.warn(builder.toString());
}
}
}

View File

@ -5,14 +5,17 @@
*/
package dan200.computercraft.core.computer;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.core.Logging;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
class LuaContext implements ILuaContext {
private static final Logger LOG = LoggerFactory.getLogger(LuaContext.class);
private final Computer computer;
LuaContext(Computer computer) {
@ -38,7 +41,7 @@ public long issueMainThreadTask(@Nonnull final ILuaTask task) throws LuaExceptio
} catch (LuaException e) {
computer.queueEvent("task_complete", new Object[]{ taskID, false, e.getMessage() });
} catch (Exception t) {
if (ComputerCraft.logComputerErrors) ComputerCraft.log.error("Error running task", t);
LOG.error(Logging.JAVA_ERROR, "Error running task", t);
computer.queueEvent("task_complete", new Object[]{
taskID, false, "Java Exception Thrown: " + t,
});

View File

@ -5,7 +5,7 @@
*/
package dan200.computercraft.core.computer.mainthread;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.metrics.MetricsObserver;
import java.util.HashSet;
@ -21,7 +21,7 @@
* {@link MainThread} starts cool, and runs as many tasks as it can in the current {@link #budget}ns. Any external tasks
* (those run by tile entities, etc...) will also consume the budget
* <p>
* Next tick, we add {@link ComputerCraft#maxMainGlobalTime} to our budget (clamp it to that value too). If we're still
* Next tick, we add {@link CoreConfig#maxMainGlobalTime} to our budget (clamp it to that value too). If we're still
* over budget, then we should not execute <em>any</em> work (either as part of {@link MainThread} or externally).
*/
public final class MainThread implements MainThreadScheduler {
@ -80,7 +80,7 @@ void queue(MainThreadExecutor executor) {
var newRuntime = minimumTime;
// Slow down new computers a little bit.
if (executor.virtualTime == 0) newRuntime += ComputerCraft.maxMainComputerTime;
if (executor.virtualTime == 0) newRuntime += CoreConfig.maxMainComputerTime;
executor.virtualTime = Math.max(newRuntime, executor.virtualTime);
@ -111,7 +111,7 @@ public void tick() {
// Of course, we'll go over the MAX_TICK_TIME most of the time, but eventually that overrun will accumulate
// and we'll skip a whole tick - bringing the average back down again.
currentTick++;
budget = Math.min(budget + ComputerCraft.maxMainGlobalTime, ComputerCraft.maxMainGlobalTime);
budget = Math.min(budget + CoreConfig.maxMainGlobalTime, CoreConfig.maxMainGlobalTime);
canExecute = budget > 0;
// Cool down any warm computers.

View File

@ -5,8 +5,8 @@
*/
package dan200.computercraft.core.computer.mainthread;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IWorkMonitor;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.computer.Computer;
import dan200.computercraft.core.metrics.Metrics;
import dan200.computercraft.core.metrics.MetricsObserver;
@ -23,7 +23,7 @@
* those run elsewhere (such as during the turtle's tick). In order to handle this, the executor goes through three
* stages:
* <p>
* When {@link State#COOL}, the computer is allocated {@link ComputerCraft#maxMainComputerTime}ns to execute any work
* When {@link State#COOL}, the computer is allocated {@link CoreConfig#maxMainComputerTime}ns to execute any work
* this tick. At the beginning of the tick, we execute as many {@link MainThread} tasks as possible, until our
* time-frame or the global time frame has expired.
* <p>
@ -34,13 +34,13 @@
* {@link State#HOT}. This means it will no longer be able to execute {@link MainThread} tasks (though will still
* execute tile entity tasks, in order to prevent the main thread from exhausting work every tick).
* <p>
* At the beginning of the next tick, we increment the budget e by {@link ComputerCraft#maxMainComputerTime} and any
* At the beginning of the next tick, we increment the budget e by {@link CoreConfig#maxMainComputerTime} and any
* {@link State#HOT} executors are marked as {@link State#COOLING}. They will remain cooling until their budget is fully
* replenished (is equal to {@link ComputerCraft#maxMainComputerTime}). Note, this is different to {@link MainThread},
* replenished (is equal to {@link CoreConfig#maxMainComputerTime}). Note, this is different to {@link MainThread},
* which allows running when it has any budget left. When cooling, <em>no</em> tasks are executed - be they on the tile
* entity or main thread.
* <p>
* This mechanism means that, on average, computers will use at most {@link ComputerCraft#maxMainComputerTime}ns per
* This mechanism means that, on average, computers will use at most {@link CoreConfig#maxMainComputerTime}ns per
* second, but one task source will not prevent others from executing.
*
* @see MainThread
@ -190,7 +190,7 @@ private void consumeTime(long time) {
// #tickCooling() isn't called, and so we didn't overrun the previous tick.
if (currentTick != scheduler.currentTick()) {
currentTick = scheduler.currentTick();
budget = ComputerCraft.maxMainComputerTime;
budget = CoreConfig.maxMainComputerTime;
}
budget -= time;
@ -203,15 +203,15 @@ private void consumeTime(long time) {
}
/**
* Move this executor forward one tick, replenishing the budget by {@link ComputerCraft#maxMainComputerTime}.
* Move this executor forward one tick, replenishing the budget by {@link CoreConfig#maxMainComputerTime}.
*
* @return Whether this executor has cooled down, and so is safe to run again.
*/
boolean tickCooling() {
state = State.COOLING;
currentTick = scheduler.currentTick();
budget = Math.min(budget + ComputerCraft.maxMainComputerTime, ComputerCraft.maxMainComputerTime);
if (budget < ComputerCraft.maxMainComputerTime) return false;
budget = Math.min(budget + CoreConfig.maxMainComputerTime, CoreConfig.maxMainComputerTime);
if (budget < CoreConfig.maxMainComputerTime) return false;
state = State.COOL;
synchronized (queueLock) {

View File

@ -6,9 +6,10 @@
package dan200.computercraft.core.filesystem;
import com.google.common.collect.Sets;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.FileOperationException;
import dan200.computercraft.api.filesystem.IWritableMount;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.io.File;
@ -23,6 +24,7 @@
import java.util.Set;
public class FileMount implements IWritableMount {
private static final Logger LOG = LoggerFactory.getLogger(FileMount.class);
private static final int MINIMUM_FILE_SIZE = 500;
private static final Set<OpenOption> READ_OPTIONS = Collections.singleton(StandardOpenOption.READ);
private static final Set<OpenOption> WRITE_OPTIONS = Sets.newHashSet(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
@ -330,7 +332,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
ComputerCraft.log.error("Error computing file size for {}", file, exc);
LOG.error("Error computing file size for {}", file, exc);
return FileVisitResult.CONTINUE;
}
}
@ -343,7 +345,7 @@ private static long measureUsedSpace(File file) {
Files.walkFileTree(file.toPath(), visitor);
return visitor.size;
} catch (IOException e) {
ComputerCraft.log.error("Error computing file size for {}", file, e);
LOG.error("Error computing file size for {}", file, e);
return 0;
}
}

View File

@ -6,10 +6,10 @@
package dan200.computercraft.core.filesystem;
import com.google.common.io.ByteStreams;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.IFileSystem;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.shared.util.IoUtil;
import javax.annotation.Nonnull;
@ -329,8 +329,8 @@ private void cleanup() {
private synchronized <T extends Closeable> FileSystemWrapper<T> openFile(@Nonnull MountWrapper mount, @Nonnull Channel channel, @Nonnull T file) throws FileSystemException {
synchronized (openFiles) {
if (ComputerCraft.maximumFilesOpen > 0 &&
openFiles.size() >= ComputerCraft.maximumFilesOpen) {
if (CoreConfig.maximumFilesOpen > 0 &&
openFiles.size() >= CoreConfig.maximumFilesOpen) {
IoUtil.closeQuietly(file);
IoUtil.closeQuietly(channel);
throw new FileSystemException("Too many files already open");

View File

@ -5,11 +5,13 @@
*/
package dan200.computercraft.core.lua;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.core.Logging;
import dan200.computercraft.core.asm.LuaMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.squiddev.cobalt.LuaError;
import org.squiddev.cobalt.LuaState;
import org.squiddev.cobalt.Varargs;
@ -21,6 +23,7 @@
* As we never yield, we do not need to push a function to the stack, which removes a small amount of overhead.
*/
class BasicFunction extends VarArgFunction {
private static final Logger LOG = LoggerFactory.getLogger(BasicFunction.class);
private final CobaltLuaMachine machine;
private final LuaMethod method;
private final Object instance;
@ -44,9 +47,7 @@ public Varargs invoke(LuaState luaState, Varargs args) throws LuaError {
} catch (LuaException e) {
throw wrap(e);
} catch (Throwable t) {
if (ComputerCraft.logComputerErrors) {
ComputerCraft.log.error("Error calling " + name + " on " + instance, t);
}
LOG.error(Logging.JAVA_ERROR, "Error calling {} on {}", name, instance, t);
throw new LuaError("Java Exception Thrown: " + t, 0);
} finally {
arguments.close();

View File

@ -5,16 +5,19 @@
*/
package dan200.computercraft.core.lua;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.IDynamicLuaObject;
import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaFunction;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.Logging;
import dan200.computercraft.core.asm.LuaMethod;
import dan200.computercraft.core.asm.ObjectSource;
import dan200.computercraft.core.computer.TimeoutState;
import dan200.computercraft.core.metrics.Metrics;
import dan200.computercraft.shared.util.ThreadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.squiddev.cobalt.*;
import org.squiddev.cobalt.compiler.CompileException;
import org.squiddev.cobalt.compiler.LoadState;
@ -39,6 +42,8 @@
import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKYIELD;
public class CobaltLuaMachine implements ILuaMachine {
private static final Logger LOG = LoggerFactory.getLogger(CobaltLuaMachine.class);
private static final ThreadPoolExecutor COROUTINES = new ThreadPoolExecutor(
0, Integer.MAX_VALUE,
5L, TimeUnit.MINUTES,
@ -102,8 +107,8 @@ public CobaltLuaMachine(MachineEnvironment environment) {
// Add version globals
globals.rawset("_VERSION", valueOf("Lua 5.1"));
globals.rawset("_HOST", valueOf(environment.hostString()));
globals.rawset("_CC_DEFAULT_SETTINGS", valueOf(ComputerCraft.defaultComputerSettings));
if (ComputerCraft.disableLua51Features) {
globals.rawset("_CC_DEFAULT_SETTINGS", valueOf(CoreConfig.defaultComputerSettings));
if (CoreConfig.disableLua51Features) {
globals.rawset("_CC_DISABLE_LUA51_FEATURES", Constants.TRUE);
}
}
@ -113,7 +118,7 @@ public void addAPI(@Nonnull ILuaAPI api) {
// Add the methods of an API to the global table
var table = wrapLuaObject(api);
if (table == null) {
ComputerCraft.log.warn("API {} does not provide any methods", api);
LOG.warn("API {} does not provide any methods", api);
table = new LuaTable();
}
@ -134,7 +139,7 @@ public MachineResult loadBios(@Nonnull InputStream bios) {
close();
return MachineResult.error(e);
} catch (Exception e) {
ComputerCraft.log.warn("Could not load bios.lua", e);
LOG.warn("Could not load bios.lua", e);
close();
return MachineResult.GENERIC_ERROR;
}
@ -180,7 +185,7 @@ public MachineResult handleEvent(String eventName, Object[] arguments) {
return MachineResult.TIMEOUT;
} catch (LuaError e) {
close();
ComputerCraft.log.warn("Top level coroutine errored", e);
LOG.warn("Top level coroutine errored", e);
return MachineResult.error(e);
}
}
@ -294,9 +299,7 @@ private LuaValue toValue(@Nullable Object object, @Nullable Map<Object, LuaValue
return wrapped;
}
if (ComputerCraft.logComputerErrors) {
ComputerCraft.log.warn("Received unknown type '{}', returning nil.", object.getClass().getName());
}
LOG.warn(Logging.JAVA_ERROR, "Received unknown type '{}', returning nil.", object.getClass().getName());
return Constants.NIL;
}

View File

@ -21,6 +21,10 @@
* @param hostString A {@linkplain GlobalEnvironment#getHostString() host string} to identify the current environment.
* @see ILuaMachine.Factory
*/
public record MachineEnvironment(ILuaContext context, MetricsObserver metrics, TimeoutState timeout,
String hostString) {
public record MachineEnvironment(
ILuaContext context,
MetricsObserver metrics,
TimeoutState timeout,
String hostString
) {
}

View File

@ -5,12 +5,14 @@
*/
package dan200.computercraft.core.lua;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.ILuaCallback;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.core.Logging;
import dan200.computercraft.core.asm.LuaMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.squiddev.cobalt.*;
import org.squiddev.cobalt.debug.DebugFrame;
import org.squiddev.cobalt.function.ResumableVarArgFunction;
@ -22,6 +24,8 @@
* and resuming the supplied continuation.
*/
class ResultInterpreterFunction extends ResumableVarArgFunction<ResultInterpreterFunction.Container> {
private static final Logger LOG = LoggerFactory.getLogger(ResultInterpreterFunction.class);
@Nonnull
static class Container {
ILuaCallback callback;
@ -56,9 +60,7 @@ protected Varargs invoke(LuaState state, DebugFrame debugFrame, Varargs args) th
} catch (LuaException e) {
throw wrap(e, 0);
} catch (Throwable t) {
if (ComputerCraft.logComputerErrors) {
ComputerCraft.log.error("Error calling " + name + " on " + instance, t);
}
LOG.error(Logging.JAVA_ERROR, "Error calling {} on {}", name, instance, t);
throw new LuaError("Java Exception Thrown: " + t, 0);
} finally {
arguments.close();
@ -82,9 +84,7 @@ protected Varargs resumeThis(LuaState state, Container container, Varargs args)
} catch (LuaException e) {
throw wrap(e, container.errorAdjust);
} catch (Throwable t) {
if (ComputerCraft.logComputerErrors) {
ComputerCraft.log.error("Error calling " + name + " on " + container.callback, t);
}
LOG.error(Logging.JAVA_ERROR, "Error calling {} on {}", name, container.callback, t);
throw new LuaError("Java Exception Thrown: " + t, 0);
}

View File

@ -3,12 +3,15 @@
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core.apis.http.options;
package dan200.computercraft.shared;
import com.electronwill.nightconfig.core.Config;
import com.electronwill.nightconfig.core.InMemoryCommentedFormat;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.apis.http.options.Action;
import dan200.computercraft.core.apis.http.options.AddressRule;
import dan200.computercraft.core.apis.http.options.PartialOptions;
import javax.annotation.Nullable;
import java.util.Locale;

View File

@ -7,9 +7,10 @@
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.Logging;
import dan200.computercraft.core.apis.http.NetworkUtils;
import dan200.computercraft.core.apis.http.options.Action;
import dan200.computercraft.core.apis.http.options.AddressRuleConfig;
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
@ -18,6 +19,9 @@
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.filter.MarkerFilter;
import java.util.Arrays;
import java.util.List;
@ -82,10 +86,14 @@ public final class Config {
private static final ForgeConfigSpec serverSpec;
private static final ForgeConfigSpec clientSpec;
private static MarkerFilter logFilter = MarkerFilter.createFilter(Logging.COMPUTER_ERROR.getName(), Filter.Result.ACCEPT, Filter.Result.NEUTRAL);
private Config() {
}
static {
LoggerContext.getContext().addFilter(logFilter);
var builder = new ForgeConfigSpec.Builder();
{ // General computers
@ -102,27 +110,27 @@ private Config() {
maximumFilesOpen = builder
.comment("Set how many files a computer can have open at the same time. Set to 0 for unlimited.")
.translation(TRANSLATION_PREFIX + "maximum_open_files")
.defineInRange("maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE);
.defineInRange("maximum_open_files", CoreConfig.maximumFilesOpen, 0, Integer.MAX_VALUE);
disableLua51Features = builder
.comment("""
Set this to true to disable Lua 5.1 functions that will be removed in a future
update. Useful for ensuring forward compatibility of your programs now.""")
.define("disable_lua51_features", ComputerCraft.disableLua51Features);
.define("disable_lua51_features", CoreConfig.disableLua51Features);
defaultComputerSettings = builder
.comment("""
A comma separated list of default system settings to set on new computers.
Example: "shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false"
will disable all autocompletion.""")
.define("default_computer_settings", ComputerCraft.defaultComputerSettings);
.define("default_computer_settings", CoreConfig.defaultComputerSettings);
logComputerErrors = builder
.comment("""
Log exceptions thrown by peripherals and other Lua objects. This makes it easier
for mod authors to debug problems, but may result in log spam should people use
buggy methods.""")
.define("log_computer_errors", ComputerCraft.logComputerErrors);
.define("log_computer_errors", true);
commandRequireCreative = builder
.comment("""
@ -151,14 +159,14 @@ private Config() {
milliseconds.
Note, we will quite possibly go over this limit, as there's no way to tell how
long a will take - this aims to be the upper bound of the average time.""")
.defineInRange("max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis(ComputerCraft.maxMainGlobalTime), 1, Integer.MAX_VALUE);
.defineInRange("max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis(CoreConfig.maxMainGlobalTime), 1, Integer.MAX_VALUE);
maxMainComputerTime = builder
.comment("""
The ideal maximum time a computer can execute for in a tick, in milliseconds.
Note, we will quite possibly go over this limit, as there's no way to tell how
long a will take - this aims to be the upper bound of the average time.""")
.defineInRange("max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis(ComputerCraft.maxMainComputerTime), 1, Integer.MAX_VALUE);
.defineInRange("max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis(CoreConfig.maxMainComputerTime), 1, Integer.MAX_VALUE);
builder.pop();
}
@ -172,11 +180,11 @@ private Config() {
Enable the "http" API on Computers. This also disables the "pastebin" and "wget"
programs, that many users rely on. It's recommended to leave this on and use the
"rules" config option to impose more fine-grained control.""")
.define("enabled", ComputerCraft.httpEnabled);
.define("enabled", CoreConfig.httpEnabled);
httpWebsocketEnabled = builder
.comment("Enable use of http websockets. This requires the \"http_enable\" option to also be true.")
.define("websocket_enabled", ComputerCraft.httpWebsocketEnabled);
.define("websocket_enabled", CoreConfig.httpWebsocketEnabled);
httpRules = builder
.comment("""
@ -197,11 +205,11 @@ CIDR notation ("127.0.0.0/8").
The number of http requests a computer can make at one time. Additional requests
will be queued, and sent when the running requests have finished. Set to 0 for
unlimited.""")
.defineInRange("max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE);
.defineInRange("max_requests", CoreConfig.httpMaxRequests, 0, Integer.MAX_VALUE);
httpMaxWebsockets = builder
.comment("The number of websockets a computer can have open at one time. Set to 0 for unlimited.")
.defineInRange("max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE);
.defineInRange("max_websockets", CoreConfig.httpMaxWebsockets, 1, Integer.MAX_VALUE);
builder
.comment("Limits bandwidth used by computers.")
@ -209,11 +217,11 @@ CIDR notation ("127.0.0.0/8").
httpDownloadBandwidth = builder
.comment("The number of bytes which can be downloaded in a second. This is shared across all computers. (bytes/s).")
.defineInRange("global_download", ComputerCraft.httpDownloadBandwidth, 1, Integer.MAX_VALUE);
.defineInRange("global_download", CoreConfig.httpDownloadBandwidth, 1, Integer.MAX_VALUE);
httpUploadBandwidth = builder
.comment("The number of bytes which can be uploaded in a second. This is shared across all computers. (bytes/s).")
.defineInRange("global_upload", ComputerCraft.httpUploadBandwidth, 1, Integer.MAX_VALUE);
.defineInRange("global_upload", CoreConfig.httpUploadBandwidth, 1, Integer.MAX_VALUE);
builder.pop();
@ -349,28 +357,38 @@ private static void syncServer() {
// General
ComputerCraft.computerSpaceLimit = computerSpaceLimit.get();
ComputerCraft.floppySpaceLimit = floppySpaceLimit.get();
ComputerCraft.maximumFilesOpen = maximumFilesOpen.get();
ComputerCraft.disableLua51Features = disableLua51Features.get();
ComputerCraft.defaultComputerSettings = defaultComputerSettings.get();
CoreConfig.maximumFilesOpen = maximumFilesOpen.get();
CoreConfig.disableLua51Features = disableLua51Features.get();
CoreConfig.defaultComputerSettings = defaultComputerSettings.get();
ComputerCraft.computerThreads = computerThreads.get();
ComputerCraft.logComputerErrors = logComputerErrors.get();
ComputerCraft.commandRequireCreative = commandRequireCreative.get();
// Execution
ComputerCraft.computerThreads = computerThreads.get();
ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(maxMainGlobalTime.get());
ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(maxMainComputerTime.get());
CoreConfig.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(maxMainGlobalTime.get());
CoreConfig.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(maxMainComputerTime.get());
// Update our log filter if needed.
var logFilter = MarkerFilter.createFilter(
Logging.COMPUTER_ERROR.getName(),
logComputerErrors.get() ? Filter.Result.ACCEPT : Filter.Result.DENY,
Filter.Result.NEUTRAL
);
if (!logFilter.equals(Config.logFilter)) {
LoggerContext.getContext().removeFilter(Config.logFilter);
LoggerContext.getContext().addFilter(Config.logFilter = logFilter);
}
// HTTP
ComputerCraft.httpEnabled = httpEnabled.get();
ComputerCraft.httpWebsocketEnabled = httpWebsocketEnabled.get();
ComputerCraft.httpRules = httpRules.get().stream()
CoreConfig.httpEnabled = httpEnabled.get();
CoreConfig.httpWebsocketEnabled = httpWebsocketEnabled.get();
CoreConfig.httpRules = httpRules.get().stream()
.map(AddressRuleConfig::parseRule).filter(Objects::nonNull).toList();
ComputerCraft.httpMaxRequests = httpMaxRequests.get();
ComputerCraft.httpMaxWebsockets = httpMaxWebsockets.get();
ComputerCraft.httpDownloadBandwidth = httpDownloadBandwidth.get();
ComputerCraft.httpUploadBandwidth = httpUploadBandwidth.get();
CoreConfig.httpMaxRequests = httpMaxRequests.get();
CoreConfig.httpMaxWebsockets = httpMaxWebsockets.get();
CoreConfig.httpDownloadBandwidth = httpDownloadBandwidth.get();
CoreConfig.httpUploadBandwidth = httpUploadBandwidth.get();
NetworkUtils.reloadConfig();
// Peripheral

View File

@ -11,6 +11,7 @@
import dan200.computercraft.api.detail.BlockReference;
import dan200.computercraft.api.detail.VanillaDetailRegistries;
import dan200.computercraft.api.lua.*;
import dan200.computercraft.core.Logging;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.commands.CommandSourceStack;
@ -56,7 +57,7 @@ private Object[] doCommand(String command) {
var result = commandManager.performPrefixedCommand(computer.getSource(), command);
return new Object[]{ result > 0, receiver.copyOutput(), result };
} catch (Throwable t) {
if (ComputerCraft.logComputerErrors) ComputerCraft.log.error("Error running command.", t);
ComputerCraft.log.error(Logging.JAVA_ERROR, "Error running command.", t);
return new Object[]{ false, createOutput("Java Exception Thrown: " + t) };
}
}

View File

@ -7,6 +7,7 @@
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
@ -39,7 +40,9 @@ public synchronized void write(FriendlyByteBuf buffer) {
}
}
palette.write(buffer);
for (var i = 0; i < Palette.PALETTE_SIZE; i++) {
for (var channel : palette.getColour(i)) buffer.writeByte((int) (channel * 0xFF) & 0xFF);
}
}
public synchronized void read(FriendlyByteBuf buffer) {
@ -64,7 +67,12 @@ public synchronized void read(FriendlyByteBuf buffer) {
}
}
palette.read(buffer);
for (var i = 0; i < Palette.PALETTE_SIZE; i++) {
var r = (buffer.readByte() & 0xFF) / 255.0;
var g = (buffer.readByte() & 0xFF) / 255.0;
var b = (buffer.readByte() & 0xFF) / 255.0;
palette.setColour(i, r, g, b);
}
setChanged();
}
@ -80,7 +88,10 @@ public synchronized CompoundTag writeToNBT(CompoundTag nbt) {
nbt.putString("term_textBgColour_" + n, backgroundColour[n].toString());
}
palette.writeToNBT(nbt);
var rgb8 = new int[Palette.PALETTE_SIZE];
for (var i = 0; i < Palette.PALETTE_SIZE; i++) rgb8[i] = Palette.encodeRGB8(palette.getColour(i));
nbt.putIntArray("term_palette", rgb8);
return nbt;
}
@ -106,7 +117,16 @@ public synchronized void readFromNBT(CompoundTag nbt) {
}
}
palette.readFromNBT(nbt);
if (nbt.contains("term_palette")) {
var rgb8 = nbt.getIntArray("term_palette");
if (rgb8.length == Palette.PALETTE_SIZE) {
for (var i = 0; i < Palette.PALETTE_SIZE; i++) {
var colours = Palette.decodeRGB8(rgb8[i]);
palette.setColour(i, colours[0], colours[1], colours[2]);
}
}
}
setChanged();
}
}

View File

@ -5,13 +5,10 @@
*/
package dan200.computercraft.shared.util;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import javax.annotation.Nonnull;
public class Palette {
private static final int PALETTE_SIZE = 16;
public static final int PALETTE_SIZE = 16;
private final boolean colour;
private final double[][] colours = new double[PALETTE_SIZE][3];
@ -27,7 +24,7 @@ public Palette(boolean colour) {
}
public void setColour(int i, double r, double g, double b) {
if (i < 0 || i >= colours.length) return;
if (i < 0 || i >= PALETTE_SIZE) return;
colours[i][0] = r;
colours[i][1] = g;
colours[i][2] = b;
@ -47,7 +44,7 @@ public void setColour(int i, Colour colour) {
}
public double[] getColour(int i) {
return i >= 0 && i < colours.length ? colours[i] : null;
return i >= 0 && i < PALETTE_SIZE ? colours[i] : null;
}
/**
@ -65,7 +62,7 @@ public byte[] getRenderColours(int i) {
}
public void resetColour(int i) {
if (i >= 0 && i < colours.length) setColour(i, Colour.VALUES[i]);
if (i >= 0 && i < PALETTE_SIZE) setColour(i, Colour.VALUES[i]);
}
public void resetColours() {
@ -89,42 +86,4 @@ public static double[] decodeRGB8(int rgb) {
(rgb & 0xFF) / 255.0f,
};
}
public void write(FriendlyByteBuf buffer) {
for (var colour : colours) {
for (var channel : colour) buffer.writeByte((int) (channel * 0xFF) & 0xFF);
}
}
public void read(FriendlyByteBuf buffer) {
for (var i = 0; i < PALETTE_SIZE; i++) {
var r = (buffer.readByte() & 0xFF) / 255.0;
var g = (buffer.readByte() & 0xFF) / 255.0;
var b = (buffer.readByte() & 0xFF) / 255.0;
setColour(i, r, g, b);
}
}
public CompoundTag writeToNBT(CompoundTag nbt) {
var rgb8 = new int[colours.length];
for (var i = 0; i < colours.length; i++) {
rgb8[i] = encodeRGB8(colours[i]);
}
nbt.putIntArray("term_palette", rgb8);
return nbt;
}
public void readFromNBT(CompoundTag nbt) {
if (!nbt.contains("term_palette")) return;
var rgb8 = nbt.getIntArray("term_palette");
if (rgb8.length != colours.length) return;
for (var i = 0; i < colours.length; i++) {
var colours = decodeRGB8(rgb8[i]);
setColour(i, colours[0], colours[1], colours[2]);
}
}
}

View File

@ -85,8 +85,6 @@ public class ComputerTestDelegate {
@BeforeEach
public void before() throws IOException {
ComputerCraft.logComputerErrors = true;
if (Files.deleteIfExists(REPORT_PATH)) ComputerCraft.log.info("Deleted previous coverage report.");
var term = new Terminal(80, 100, true);

View File

@ -5,7 +5,7 @@
*/
package dan200.computercraft.core.apis.http.options;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.CoreConfig;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@ -35,7 +35,7 @@ public void matchesPort() {
"172.17.0.1", "192.168.1.114", "[0:0:0:0:0:ffff:c0a8:172]", "10.0.0.1"
})
public void blocksLocalDomains(String domain) {
assertEquals(apply(ComputerCraft.httpRules, domain, 80).action, Action.DENY);
assertEquals(apply(CoreConfig.httpRules, domain, 80).action, Action.DENY);
}
private Options apply(Iterable<AddressRule> rules, String host, int port) {

View File

@ -12,6 +12,7 @@
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.core.ComputerContext;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.computer.mainthread.MainThread;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.test.core.computer.BasicEnvironment;
@ -43,8 +44,7 @@ public static void run(String program, int maxTimes) {
}
public static void run(IWritableMount mount, Consumer<Computer> setup, int maxTicks) {
ComputerCraft.logComputerErrors = true;
ComputerCraft.maxMainComputerTime = ComputerCraft.maxMainGlobalTime = Integer.MAX_VALUE;
CoreConfig.maxMainComputerTime = CoreConfig.maxMainGlobalTime = Integer.MAX_VALUE;
var term = new Terminal(ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight, true);
var mainThread = new MainThread();

View File

@ -1,6 +1,6 @@
package dan200.computercraft.core.http
import dan200.computercraft.ComputerCraft
import dan200.computercraft.core.CoreConfig
import dan200.computercraft.core.apis.HTTPAPI
import dan200.computercraft.core.apis.http.options.Action
import dan200.computercraft.core.apis.http.options.AddressRule
@ -21,13 +21,13 @@ class TestHttpApi {
@JvmStatic
@BeforeAll
fun before() {
ComputerCraft.httpRules = listOf(AddressRule.parse("*", null, Action.ALLOW.toPartial()))
CoreConfig.httpRules = listOf(AddressRule.parse("*", null, Action.ALLOW.toPartial()))
}
@JvmStatic
@AfterAll
fun after() {
ComputerCraft.httpRules = Collections.unmodifiableList(
CoreConfig.httpRules = Collections.unmodifiableList(
listOf(
AddressRule.parse("\$private", null, Action.DENY.toPartial()),
AddressRule.parse("*", null, Action.ALLOW.toPartial()),