1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 20:20: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; 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.Config;
import dan200.computercraft.shared.Registry; import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
@ -14,37 +12,15 @@ import net.minecraftforge.fml.common.Mod;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.OptionalInt;
import java.util.concurrent.TimeUnit;
@Mod(ComputerCraft.MOD_ID) @Mod(ComputerCraft.MOD_ID)
public final class ComputerCraft { public final class ComputerCraft {
public static final String MOD_ID = "computercraft"; public static final String MOD_ID = "computercraft";
public static int computerSpaceLimit = 1000 * 1000; public static int computerSpaceLimit = 1000 * 1000;
public static int floppySpaceLimit = 125 * 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 boolean commandRequireCreative = true;
public static int computerThreads = 1; 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 boolean enableCommandBlock = false;
public static int modemRange = 64; 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; package dan200.computercraft.core.apis;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount; import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IWorkMonitor; import dan200.computercraft.api.peripheral.IWorkMonitor;
import dan200.computercraft.core.filesystem.FileSystemException; import dan200.computercraft.core.filesystem.FileSystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.HashSet; import java.util.HashSet;
@ -18,6 +19,8 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
public abstract class ComputerAccess implements IComputerAccess { public abstract class ComputerAccess implements IComputerAccess {
private static final Logger LOG = LoggerFactory.getLogger(ComputerAccess.class);
private final IAPIEnvironment environment; private final IAPIEnvironment environment;
private final Set<String> mounts = new HashSet<>(); private final Set<String> mounts = new HashSet<>();
@ -28,7 +31,7 @@ public abstract class ComputerAccess implements IComputerAccess {
public void unmountAll() { public void unmountAll() {
var fileSystem = environment.getFileSystem(); var fileSystem = environment.getFileSystem();
if (!mounts.isEmpty()) { 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) { for (var mount : mounts) {

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@
*/ */
package dan200.computercraft.core.apis.http.request; 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.IAPIEnvironment;
import dan200.computercraft.core.apis.http.HTTPRequestException; import dan200.computercraft.core.apis.http.HTTPRequestException;
import dan200.computercraft.core.apis.http.NetworkUtils; 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.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*; import io.netty.handler.codec.http.*;
import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.ReadTimeoutHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
@ -34,6 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* Represents an in-progress HTTP request. * Represents an in-progress HTTP request.
*/ */
public class HttpRequest extends Resource<HttpRequest> { 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 SUCCESS_EVENT = "http_success";
private static final String FAILURE_EVENT = "http_failure"; private static final String FAILURE_EVENT = "http_failure";
@ -171,7 +174,7 @@ public class HttpRequest extends Resource<HttpRequest> {
failure(e.getMessage()); failure(e.getMessage());
} catch (Exception e) { } catch (Exception e) {
failure(NetworkUtils.toFriendlyError(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; 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.ArrayByteChannel;
import dan200.computercraft.core.apis.handles.BinaryReadableHandle; import dan200.computercraft.core.apis.handles.BinaryReadableHandle;
import dan200.computercraft.core.apis.handles.EncodedReadableHandle; 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.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*; import io.netty.handler.codec.http.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Closeable; import java.io.Closeable;
import java.net.URI; import java.net.URI;
@ -29,6 +31,8 @@ import java.util.Map;
import static dan200.computercraft.core.apis.http.request.HttpRequest.getHeaderSize; import static dan200.computercraft.core.apis.http.request.HttpRequest.getHeaderSize;
public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpObject> implements Closeable { 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}. * Same as {@link io.netty.handler.codec.MessageAggregator}.
*/ */
@ -158,7 +162,7 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 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)); request.failure(NetworkUtils.toFriendlyError(cause));
} }

View File

@ -6,7 +6,7 @@
package dan200.computercraft.core.apis.http.websocket; package dan200.computercraft.core.apis.http.websocket;
import com.google.common.base.Strings; 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.IAPIEnvironment;
import dan200.computercraft.core.apis.http.HTTPRequestException; import dan200.computercraft.core.apis.http.HTTPRequestException;
import dan200.computercraft.core.apis.http.NetworkUtils; 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.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker; import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketVersion; import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.net.URI; import java.net.URI;
@ -36,6 +38,8 @@ import java.util.concurrent.Future;
* Provides functionality to verify and connect to a remote websocket. * Provides functionality to verify and connect to a remote websocket.
*/ */
public class Websocket extends Resource<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 * 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. * working with larger messages (especially within a Lua VM) is absurd.
@ -151,7 +155,7 @@ public class Websocket extends Resource<Websocket> {
failure(e.getMessage()); failure(e.getMessage());
} catch (Exception e) { } catch (Exception e) {
failure(NetworkUtils.toFriendlyError(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.cache.LoadingCache;
import com.google.common.primitives.Primitives; import com.google.common.primitives.Primitives;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.IArguments; import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction; 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.ClassWriter;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -35,6 +36,8 @@ import java.util.function.Function;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
public final class Generator<T> { 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 AtomicInteger METHOD_ID = new AtomicInteger();
private static final String METHOD_NAME = "apply"; private static final String METHOD_NAME = "apply";
@ -79,7 +82,7 @@ public final class Generator<T> {
try { try {
return classCache.get(klass); return classCache.get(klass);
} catch (ExecutionException e) { } 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(); return Collections.emptyList();
} }
} }
@ -92,7 +95,7 @@ public final class Generator<T> {
if (annotation == null) continue; if (annotation == null) continue;
if (Modifier.isStatic(method.getModifiers())) { 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; continue;
} }
@ -137,32 +140,32 @@ public final class Generator<T> {
// Instance methods must be final - this prevents them being overridden and potentially exposed twice. // Instance methods must be final - this prevents them being overridden and potentially exposed twice.
if (!Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) { 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)) { 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(); return Optional.empty();
} }
if (!Modifier.isPublic(method.getDeclaringClass().getModifiers())) { 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(); return Optional.empty();
} }
ComputerCraft.log.debug("Generating method wrapper for {}.", name); LOG.debug("Generating method wrapper for {}.", name);
var exceptions = method.getExceptionTypes(); var exceptions = method.getExceptionTypes();
for (var exception : exceptions) { for (var exception : exceptions) {
if (exception != LuaException.class) { 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(); return Optional.empty();
} }
} }
var annotation = method.getAnnotation(LuaFunction.class); var annotation = method.getAnnotation(LuaFunction.class);
if (annotation.unsafe() && annotation.mainThread()) { 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(); return Optional.empty();
} }
@ -180,7 +183,7 @@ public final class Generator<T> {
var instance = klass.asSubclass(base).getDeclaredConstructor().newInstance(); var instance = klass.asSubclass(base).getDeclaredConstructor().newInstance();
return Optional.of(annotation.mainThread() ? wrap.apply(instance) : instance); return Optional.of(annotation.mainThread() ? wrap.apply(instance) : instance);
} catch (ReflectiveOperationException | ClassFormatError | RuntimeException e) { } 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(); return Optional.empty();
} }
@ -317,7 +320,7 @@ public final class Generator<T> {
return true; return true;
} }
ComputerCraft.log.error("Unknown parameter type {} for method {}.{}.", LOG.error("Unknown parameter type {} for method {}.{}.",
arg.getName(), method.getDeclaringClass().getName(), method.getName()); arg.getName(), method.getDeclaringClass().getName(), method.getName());
return null; return null;
} }
@ -330,7 +333,7 @@ public final class Generator<T> {
} catch (Exception | LinkageError e) { } catch (Exception | LinkageError e) {
// LinkageError due to possible codegen bugs and NoClassDefFoundError. The latter occurs when fetching // 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. // 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; return def;
} }
}; };

View File

@ -5,11 +5,12 @@
*/ */
package dan200.computercraft.core.asm; package dan200.computercraft.core.asm;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.GenericSource; import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.peripheral.GenericPeripheral; import dan200.computercraft.api.peripheral.GenericPeripheral;
import dan200.computercraft.api.peripheral.PeripheralType; import dan200.computercraft.api.peripheral.PeripheralType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.lang.reflect.Method; 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. * A generic method is a method belonging to a {@link GenericSource} with a known target.
*/ */
public class GenericMethod { public class GenericMethod {
private static final Logger LOG = LoggerFactory.getLogger(GenericMethod.class);
final Method method; final Method method;
final LuaFunction annotation; final LuaFunction annotation;
final Class<?> target; final Class<?> target;
@ -53,7 +56,7 @@ public class GenericMethod {
Objects.requireNonNull(source, "Source cannot be null"); Objects.requireNonNull(source, "Source cannot be null");
if (cache != 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); sources.add(source);
@ -69,13 +72,13 @@ public class GenericMethod {
if (annotation == null) return null; if (annotation == null) return null;
if (!Modifier.isStatic(method.getModifiers())) { 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; return null;
} }
var types = method.getGenericParameterTypes(); var types = method.getGenericParameterTypes();
if (types.length == 0) { 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; return null;
} }

View File

@ -5,9 +5,10 @@
*/ */
package dan200.computercraft.core.asm; package dan200.computercraft.core.asm;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.LuaTable; import dan200.computercraft.api.lua.LuaTable;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.lang.reflect.*; import java.lang.reflect.*;
@ -18,6 +19,7 @@ import java.util.Optional;
import static org.objectweb.asm.Opcodes.ICONST_0; import static org.objectweb.asm.Opcodes.ICONST_0;
final class Reflect { final class Reflect {
private static final Logger LOG = LoggerFactory.getLogger(Reflect.class);
static final java.lang.reflect.Type OPTIONAL_IN = Optional.class.getTypeParameters()[0]; static final java.lang.reflect.Type OPTIONAL_IN = Optional.class.getTypeParameters()[0];
private Reflect() { private Reflect() {
@ -54,7 +56,7 @@ final class Reflect {
continue; 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; return null;
} }
} }
@ -64,7 +66,7 @@ final class Reflect {
continue; 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; return null;
} }
} }

View File

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

View File

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

View File

@ -5,14 +5,17 @@
*/ */
package dan200.computercraft.core.computer; package dan200.computercraft.core.computer;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask; import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.core.Logging;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
class LuaContext implements ILuaContext { class LuaContext implements ILuaContext {
private static final Logger LOG = LoggerFactory.getLogger(LuaContext.class);
private final Computer computer; private final Computer computer;
LuaContext(Computer computer) { LuaContext(Computer computer) {
@ -38,7 +41,7 @@ class LuaContext implements ILuaContext {
} catch (LuaException e) { } catch (LuaException e) {
computer.queueEvent("task_complete", new Object[]{ taskID, false, e.getMessage() }); computer.queueEvent("task_complete", new Object[]{ taskID, false, e.getMessage() });
} catch (Exception t) { } 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[]{ computer.queueEvent("task_complete", new Object[]{
taskID, false, "Java Exception Thrown: " + t, taskID, false, "Java Exception Thrown: " + t,
}); });

View File

@ -5,7 +5,7 @@
*/ */
package dan200.computercraft.core.computer.mainthread; package dan200.computercraft.core.computer.mainthread;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.metrics.MetricsObserver; import dan200.computercraft.core.metrics.MetricsObserver;
import java.util.HashSet; 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 * {@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 * (those run by tile entities, etc...) will also consume the budget
* <p> * <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). * 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 { public final class MainThread implements MainThreadScheduler {
@ -80,7 +80,7 @@ public final class MainThread implements MainThreadScheduler {
var newRuntime = minimumTime; var newRuntime = minimumTime;
// Slow down new computers a little bit. // 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); 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 // 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. // and we'll skip a whole tick - bringing the average back down again.
currentTick++; currentTick++;
budget = Math.min(budget + ComputerCraft.maxMainGlobalTime, ComputerCraft.maxMainGlobalTime); budget = Math.min(budget + CoreConfig.maxMainGlobalTime, CoreConfig.maxMainGlobalTime);
canExecute = budget > 0; canExecute = budget > 0;
// Cool down any warm computers. // Cool down any warm computers.

View File

@ -5,8 +5,8 @@
*/ */
package dan200.computercraft.core.computer.mainthread; package dan200.computercraft.core.computer.mainthread;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IWorkMonitor; import dan200.computercraft.api.peripheral.IWorkMonitor;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.computer.Computer; import dan200.computercraft.core.computer.Computer;
import dan200.computercraft.core.metrics.Metrics; import dan200.computercraft.core.metrics.Metrics;
import dan200.computercraft.core.metrics.MetricsObserver; 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 * those run elsewhere (such as during the turtle's tick). In order to handle this, the executor goes through three
* stages: * stages:
* <p> * <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 * 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. * time-frame or the global time frame has expired.
* <p> * <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 * {@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). * execute tile entity tasks, in order to prevent the main thread from exhausting work every tick).
* <p> * <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 * {@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 * 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. * entity or main thread.
* <p> * <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. * second, but one task source will not prevent others from executing.
* *
* @see MainThread * @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. // #tickCooling() isn't called, and so we didn't overrun the previous tick.
if (currentTick != scheduler.currentTick()) { if (currentTick != scheduler.currentTick()) {
currentTick = scheduler.currentTick(); currentTick = scheduler.currentTick();
budget = ComputerCraft.maxMainComputerTime; budget = CoreConfig.maxMainComputerTime;
} }
budget -= time; 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. * @return Whether this executor has cooled down, and so is safe to run again.
*/ */
boolean tickCooling() { boolean tickCooling() {
state = State.COOLING; state = State.COOLING;
currentTick = scheduler.currentTick(); currentTick = scheduler.currentTick();
budget = Math.min(budget + ComputerCraft.maxMainComputerTime, ComputerCraft.maxMainComputerTime); budget = Math.min(budget + CoreConfig.maxMainComputerTime, CoreConfig.maxMainComputerTime);
if (budget < ComputerCraft.maxMainComputerTime) return false; if (budget < CoreConfig.maxMainComputerTime) return false;
state = State.COOL; state = State.COOL;
synchronized (queueLock) { synchronized (queueLock) {

View File

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

View File

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

View File

@ -5,11 +5,13 @@
*/ */
package dan200.computercraft.core.lua; package dan200.computercraft.core.lua;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.core.Logging;
import dan200.computercraft.core.asm.LuaMethod; import dan200.computercraft.core.asm.LuaMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.squiddev.cobalt.LuaError; import org.squiddev.cobalt.LuaError;
import org.squiddev.cobalt.LuaState; import org.squiddev.cobalt.LuaState;
import org.squiddev.cobalt.Varargs; 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. * 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 { class BasicFunction extends VarArgFunction {
private static final Logger LOG = LoggerFactory.getLogger(BasicFunction.class);
private final CobaltLuaMachine machine; private final CobaltLuaMachine machine;
private final LuaMethod method; private final LuaMethod method;
private final Object instance; private final Object instance;
@ -44,9 +47,7 @@ class BasicFunction extends VarArgFunction {
} catch (LuaException e) { } catch (LuaException e) {
throw wrap(e); throw wrap(e);
} catch (Throwable t) { } catch (Throwable t) {
if (ComputerCraft.logComputerErrors) { LOG.error(Logging.JAVA_ERROR, "Error calling {} on {}", name, instance, t);
ComputerCraft.log.error("Error calling " + name + " on " + instance, t);
}
throw new LuaError("Java Exception Thrown: " + t, 0); throw new LuaError("Java Exception Thrown: " + t, 0);
} finally { } finally {
arguments.close(); arguments.close();

View File

@ -5,16 +5,19 @@
*/ */
package dan200.computercraft.core.lua; package dan200.computercraft.core.lua;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.IDynamicLuaObject; import dan200.computercraft.api.lua.IDynamicLuaObject;
import dan200.computercraft.api.lua.ILuaAPI; import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaFunction; 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.LuaMethod;
import dan200.computercraft.core.asm.ObjectSource; import dan200.computercraft.core.asm.ObjectSource;
import dan200.computercraft.core.computer.TimeoutState; import dan200.computercraft.core.computer.TimeoutState;
import dan200.computercraft.core.metrics.Metrics; import dan200.computercraft.core.metrics.Metrics;
import dan200.computercraft.shared.util.ThreadUtils; import dan200.computercraft.shared.util.ThreadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.squiddev.cobalt.*; import org.squiddev.cobalt.*;
import org.squiddev.cobalt.compiler.CompileException; import org.squiddev.cobalt.compiler.CompileException;
import org.squiddev.cobalt.compiler.LoadState; 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; import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKYIELD;
public class CobaltLuaMachine implements ILuaMachine { public class CobaltLuaMachine implements ILuaMachine {
private static final Logger LOG = LoggerFactory.getLogger(CobaltLuaMachine.class);
private static final ThreadPoolExecutor COROUTINES = new ThreadPoolExecutor( private static final ThreadPoolExecutor COROUTINES = new ThreadPoolExecutor(
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE,
5L, TimeUnit.MINUTES, 5L, TimeUnit.MINUTES,
@ -102,8 +107,8 @@ public class CobaltLuaMachine implements ILuaMachine {
// Add version globals // Add version globals
globals.rawset("_VERSION", valueOf("Lua 5.1")); globals.rawset("_VERSION", valueOf("Lua 5.1"));
globals.rawset("_HOST", valueOf(environment.hostString())); globals.rawset("_HOST", valueOf(environment.hostString()));
globals.rawset("_CC_DEFAULT_SETTINGS", valueOf(ComputerCraft.defaultComputerSettings)); globals.rawset("_CC_DEFAULT_SETTINGS", valueOf(CoreConfig.defaultComputerSettings));
if (ComputerCraft.disableLua51Features) { if (CoreConfig.disableLua51Features) {
globals.rawset("_CC_DISABLE_LUA51_FEATURES", Constants.TRUE); 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 // Add the methods of an API to the global table
var table = wrapLuaObject(api); var table = wrapLuaObject(api);
if (table == null) { 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(); table = new LuaTable();
} }
@ -134,7 +139,7 @@ public class CobaltLuaMachine implements ILuaMachine {
close(); close();
return MachineResult.error(e); return MachineResult.error(e);
} catch (Exception e) { } catch (Exception e) {
ComputerCraft.log.warn("Could not load bios.lua", e); LOG.warn("Could not load bios.lua", e);
close(); close();
return MachineResult.GENERIC_ERROR; return MachineResult.GENERIC_ERROR;
} }
@ -180,7 +185,7 @@ public class CobaltLuaMachine implements ILuaMachine {
return MachineResult.TIMEOUT; return MachineResult.TIMEOUT;
} catch (LuaError e) { } catch (LuaError e) {
close(); close();
ComputerCraft.log.warn("Top level coroutine errored", e); LOG.warn("Top level coroutine errored", e);
return MachineResult.error(e); return MachineResult.error(e);
} }
} }
@ -294,9 +299,7 @@ public class CobaltLuaMachine implements ILuaMachine {
return wrapped; return wrapped;
} }
if (ComputerCraft.logComputerErrors) { LOG.warn(Logging.JAVA_ERROR, "Received unknown type '{}', returning nil.", object.getClass().getName());
ComputerCraft.log.warn("Received unknown type '{}', returning nil.", object.getClass().getName());
}
return Constants.NIL; 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. * @param hostString A {@linkplain GlobalEnvironment#getHostString() host string} to identify the current environment.
* @see ILuaMachine.Factory * @see ILuaMachine.Factory
*/ */
public record MachineEnvironment(ILuaContext context, MetricsObserver metrics, TimeoutState timeout, public record MachineEnvironment(
String hostString) { ILuaContext context,
MetricsObserver metrics,
TimeoutState timeout,
String hostString
) {
} }

View File

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

View File

@ -3,12 +3,15 @@
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * 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.Config;
import com.electronwill.nightconfig.core.InMemoryCommentedFormat; import com.electronwill.nightconfig.core.InMemoryCommentedFormat;
import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig;
import dan200.computercraft.ComputerCraft; 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 javax.annotation.Nullable;
import java.util.Locale; import java.util.Locale;

View File

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

View File

@ -11,6 +11,7 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.detail.BlockReference; import dan200.computercraft.api.detail.BlockReference;
import dan200.computercraft.api.detail.VanillaDetailRegistries; import dan200.computercraft.api.detail.VanillaDetailRegistries;
import dan200.computercraft.api.lua.*; import dan200.computercraft.api.lua.*;
import dan200.computercraft.core.Logging;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer; import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.util.NBTUtil; import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
@ -56,7 +57,7 @@ public class CommandAPI implements ILuaAPI {
var result = commandManager.performPrefixedCommand(computer.getSource(), command); var result = commandManager.performPrefixedCommand(computer.getSource(), command);
return new Object[]{ result > 0, receiver.copyOutput(), result }; return new Object[]{ result > 0, receiver.copyOutput(), result };
} catch (Throwable t) { } 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) }; 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.core.terminal.Terminal;
import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf; 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) { 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(); setChanged();
} }
@ -80,7 +88,10 @@ public class NetworkedTerminal extends Terminal {
nbt.putString("term_textBgColour_" + n, backgroundColour[n].toString()); 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; 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(); setChanged();
} }
} }

View File

@ -5,13 +5,10 @@
*/ */
package dan200.computercraft.shared.util; package dan200.computercraft.shared.util;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class Palette { public class Palette {
private static final int PALETTE_SIZE = 16; public static final int PALETTE_SIZE = 16;
private final boolean colour; private final boolean colour;
private final double[][] colours = new double[PALETTE_SIZE][3]; 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) { 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][0] = r;
colours[i][1] = g; colours[i][1] = g;
colours[i][2] = b; colours[i][2] = b;
@ -47,7 +44,7 @@ public class Palette {
} }
public double[] getColour(int i) { 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) { 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() { public void resetColours() {
@ -89,42 +86,4 @@ public class Palette {
(rgb & 0xFF) / 255.0f, (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 @BeforeEach
public void before() throws IOException { public void before() throws IOException {
ComputerCraft.logComputerErrors = true;
if (Files.deleteIfExists(REPORT_PATH)) ComputerCraft.log.info("Deleted previous coverage report."); if (Files.deleteIfExists(REPORT_PATH)) ComputerCraft.log.info("Deleted previous coverage report.");
var term = new Terminal(80, 100, true); var term = new Terminal(80, 100, true);

View File

@ -5,7 +5,7 @@
*/ */
package dan200.computercraft.core.apis.http.options; 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.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource; 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" "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) { 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) { 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.LuaException;
import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.core.ComputerContext; import dan200.computercraft.core.ComputerContext;
import dan200.computercraft.core.CoreConfig;
import dan200.computercraft.core.computer.mainthread.MainThread; import dan200.computercraft.core.computer.mainthread.MainThread;
import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.test.core.computer.BasicEnvironment; 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) { public static void run(IWritableMount mount, Consumer<Computer> setup, int maxTicks) {
ComputerCraft.logComputerErrors = true; CoreConfig.maxMainComputerTime = CoreConfig.maxMainGlobalTime = Integer.MAX_VALUE;
ComputerCraft.maxMainComputerTime = ComputerCraft.maxMainGlobalTime = Integer.MAX_VALUE;
var term = new Terminal(ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight, true); var term = new Terminal(ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight, true);
var mainThread = new MainThread(); var mainThread = new MainThread();

View File

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