1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 12:10:30 +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 net.minecraftforge.fml.common.Mod;
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.Objects;
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 @@ public abstract class ComputerAccess implements IComputerAccess {
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 class HTTPAPI implements ILuaAPI {
@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.ssl.SslContextBuilder;
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 @@ import java.util.concurrent.TimeUnit;
* 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 @@ public final class NetworkUtils {
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 final class NetworkUtils {
.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 final class NetworkUtils {
}
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 final class NetworkUtils {
* @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 @@ import java.util.regex.Pattern;
* @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 @@ interface AddressPredicate {
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 @@ interface AddressPredicate {
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.SocketChannel;
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 @@ import java.util.concurrent.atomic.AtomicInteger;
* 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 @@ public class HttpRequest extends Resource<HttpRequest> {
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.buffer.CompositeByteBuf;
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 java.util.Map;
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 final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
@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.HttpHeaders;
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 @@ import java.util.concurrent.Future;
* 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 @@ public class Websocket extends Resource<Websocket> {
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.CacheLoader;
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 dan200.computercraft.api.peripheral.PeripheralType;
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 java.util.function.Function;
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 final class Generator<T> {
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 @@ public final class Generator<T> {
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 @@ public final class Generator<T> {
// 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 @@ public final class Generator<T> {
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 @@ public final class Generator<T> {
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 @@ public final class Generator<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 @@ import java.util.stream.Stream;
* 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 class GenericMethod {
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 @@ public class GenericMethod {
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 java.util.Optional;
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 @@ final class Reflect {
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 @@ final class Reflect {
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.Metrics;
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 @@ import java.util.concurrent.locks.ReentrantLock;
* 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 @@ final class ComputerExecutor {
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 @@ package dan200.computercraft.core.computer;
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 @@ import java.util.concurrent.locks.ReentrantLock;
* @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 final class ComputerThread {
@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 @@ public final class ComputerThread {
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 @@ public final class ComputerThread {
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 @@ public final class ComputerThread {
// 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 @@ public final class ComputerThread {
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 @@ public final class ComputerThread {
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 @@ public final class ComputerThread {
// 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 @@ public final class ComputerThread {
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 @@ public final class ComputerThread {
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 @@ public final class ComputerThread {
}
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 @@ public final class ComputerThread {
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 @@ class LuaContext implements ILuaContext {
} 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 @@ import java.util.TreeSet;
* {@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 @@ public final class MainThread implements MainThreadScheduler {
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 final class MainThread implements MainThreadScheduler {
// 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 @@ import java.util.concurrent.TimeUnit;
* 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 @@ import java.util.concurrent.TimeUnit;
* {@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 @@ final class MainThreadExecutor implements MainThreadScheduler.Executor {
// #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 @@ final class MainThreadExecutor implements MainThreadScheduler.Executor {
}
/**
* 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.OptionalLong;
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 class FileMount implements IWritableMount {
@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 @@ public class FileMount implements IWritableMount {
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 @@ public class FileSystem {
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 @@ import org.squiddev.cobalt.function.VarArgFunction;
* 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 @@ class BasicFunction extends VarArgFunction {
} 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_HOOKED;
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 class CobaltLuaMachine implements ILuaMachine {
// 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 class CobaltLuaMachine implements ILuaMachine {
// 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 class CobaltLuaMachine implements ILuaMachine {
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 class CobaltLuaMachine implements ILuaMachine {
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 @@ public class CobaltLuaMachine implements ILuaMachine {
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 @@ import dan200.computercraft.core.metrics.MetricsObserver;
* @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 @@ import javax.annotation.Nonnull;
* 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 @@ class ResultInterpreterFunction extends ResumableVarArgFunction<ResultInterprete
} 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 @@ class ResultInterpreterFunction extends ResumableVarArgFunction<ResultInterprete
} 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 @@ package dan200.computercraft.shared;
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.ModLoadingContext;
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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class Config {
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 @@ public final class Config {
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 @@ public final class Config {
// 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.ComputerCraft;
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 @@ public class CommandAPI implements ILuaAPI {
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 @@ package dan200.computercraft.shared.computer.terminal;
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 class NetworkedTerminal extends Terminal {
}
}
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 class NetworkedTerminal extends Terminal {
}
}
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 class NetworkedTerminal extends Terminal {
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 class NetworkedTerminal extends Terminal {
}
}
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 class Palette {
}
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 class Palette {
}
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 class Palette {
}
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 class Palette {
(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 class AddressRuleTest {
"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.ILuaAPI;
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 class ComputerBootstrap {
}
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()),