mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 20:20:30 +00:00
Merge branch 'mc-1.16.x' into mc-1.17.x
This commit is contained in:
commit
af966179ce
@ -17,7 +17,7 @@ plugins {
|
||||
id "com.github.hierynomus.license" version "0.16.1"
|
||||
id "com.matthewprenger.cursegradle" version "1.4.0"
|
||||
id "com.github.breadmoirai.github-release" version "2.2.12"
|
||||
id "org.jetbrains.kotlin.jvm" version "1.5.21"
|
||||
id "org.jetbrains.kotlin.jvm" version "1.6.0"
|
||||
id "com.modrinth.minotaur" version "1.2.1"
|
||||
}
|
||||
|
||||
@ -162,13 +162,13 @@ dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
|
||||
testImplementation 'org.hamcrest:hamcrest:2.2'
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21'
|
||||
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1'
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.0'
|
||||
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
|
||||
|
||||
testModImplementation sourceSets.main.output
|
||||
testModExtra 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21'
|
||||
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.1'
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.2'
|
||||
}
|
||||
|
||||
// Compile tasks
|
||||
|
@ -2,7 +2,7 @@
|
||||
module: [kind=event] redstone
|
||||
---
|
||||
|
||||
The @{redstone} event is fired whenever any redstone inputs on the computer change.
|
||||
The @{event!redstone} event is fired whenever any redstone inputs on the computer change.
|
||||
|
||||
## Example
|
||||
Prints a message when a redstone input changes:
|
||||
|
@ -1,7 +1,7 @@
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
|
||||
# Mod properties
|
||||
mod_version=1.98.2
|
||||
mod_version=1.99.0
|
||||
|
||||
# Minecraft properties (update mods.toml when changing)
|
||||
mc_version=1.17.1
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
269
gradlew
vendored
269
gradlew
vendored
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -17,67 +17,101 @@
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MSYS* | MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
@ -106,80 +140,95 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
402
package-lock.json
generated
402
package-lock.json
generated
@ -16,10 +16,45 @@
|
||||
"@rollup/plugin-typescript": "^8.2.5",
|
||||
"requirejs": "^2.3.6",
|
||||
"rollup": "^2.33.1",
|
||||
"terser": "^5.3.8",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"typescript": "^4.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz",
|
||||
"integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.16.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.15.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz",
|
||||
"integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz",
|
||||
"integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.15.7",
|
||||
"chalk": "^2.0.0",
|
||||
"js-tokens": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-typescript": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz",
|
||||
@ -61,18 +96,74 @@
|
||||
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.11.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz",
|
||||
"integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
|
||||
@ -111,6 +202,15 @@
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
|
||||
@ -123,6 +223,53 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker": {
|
||||
"version": "26.6.2",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
|
||||
"integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"merge-stream": "^2.0.0",
|
||||
"supports-color": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
@ -142,14 +289,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.5.15",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.5.15.tgz",
|
||||
"integrity": "sha512-5chK29n6QcJc3m1lVrKQSQ+V7K1Gb8HeQY6FViQ5AxCAEGu3DaHffWNDkC9+miZgsLvbvU9rxbV1qinGHMHzqA==",
|
||||
"version": "10.6.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.6.1.tgz",
|
||||
"integrity": "sha512-ydCg+ISIq70vqiThvNWStZWLRjR9U2awP/JAmGdWUKm9+Tyuy+MqVdAIyEByeIspAVtD4GWC/SJtxO8XD4knVA==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/requirejs": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
|
||||
@ -177,9 +333,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "2.60.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.60.0.tgz",
|
||||
"integrity": "sha512-cHdv9GWd58v58rdseC8e8XIaPUo8a9cgZpnCMMDGZFDZKEODOiPPEQFXLriWr/TjXzhPPmG5bkAztPsOARIcGQ==",
|
||||
"version": "2.60.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.60.1.tgz",
|
||||
"integrity": "sha512-akwfnpjY0rXEDSn1UTVfKXJhPsEBu+imi1gqBA1ZkHGydUnkV/fWCC90P7rDaLEW8KTwBcS1G3N4893Ndz+jwg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
@ -191,6 +347,50 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-terser": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
|
||||
"integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
"jest-worker": "^26.2.1",
|
||||
"serialize-javascript": "^4.0.0",
|
||||
"terser": "^5.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
@ -219,6 +419,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.10.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz",
|
||||
@ -264,6 +476,32 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz",
|
||||
"integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.16.0"
|
||||
}
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.15.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz",
|
||||
"integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz",
|
||||
"integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-validator-identifier": "^7.15.7",
|
||||
"chalk": "^2.0.0",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-typescript": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz",
|
||||
@ -291,18 +529,65 @@
|
||||
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.11.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz",
|
||||
"integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
|
||||
@ -331,6 +616,12 @@
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
|
||||
@ -340,6 +631,46 @@
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"jest-worker": {
|
||||
"version": "26.6.2",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
|
||||
"integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"merge-stream": "^2.0.0",
|
||||
"supports-color": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
@ -353,9 +684,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"preact": {
|
||||
"version": "10.5.15",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.5.15.tgz",
|
||||
"integrity": "sha512-5chK29n6QcJc3m1lVrKQSQ+V7K1Gb8HeQY6FViQ5AxCAEGu3DaHffWNDkC9+miZgsLvbvU9rxbV1qinGHMHzqA=="
|
||||
"version": "10.6.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.6.1.tgz",
|
||||
"integrity": "sha512-ydCg+ISIq70vqiThvNWStZWLRjR9U2awP/JAmGdWUKm9+Tyuy+MqVdAIyEByeIspAVtD4GWC/SJtxO8XD4knVA=="
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"requirejs": {
|
||||
"version": "2.3.6",
|
||||
@ -374,14 +714,41 @@
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.60.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.60.0.tgz",
|
||||
"integrity": "sha512-cHdv9GWd58v58rdseC8e8XIaPUo8a9cgZpnCMMDGZFDZKEODOiPPEQFXLriWr/TjXzhPPmG5bkAztPsOARIcGQ==",
|
||||
"version": "2.60.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.60.1.tgz",
|
||||
"integrity": "sha512-akwfnpjY0rXEDSn1UTVfKXJhPsEBu+imi1gqBA1ZkHGydUnkV/fWCC90P7rDaLEW8KTwBcS1G3N4893Ndz+jwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"rollup-plugin-terser": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
|
||||
"integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
"jest-worker": "^26.2.1",
|
||||
"serialize-javascript": "^4.0.0",
|
||||
"terser": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
@ -406,6 +773,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.10.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz",
|
||||
|
@ -12,7 +12,7 @@
|
||||
"@rollup/plugin-typescript": "^8.2.5",
|
||||
"requirejs": "^2.3.6",
|
||||
"rollup": "^2.33.1",
|
||||
"terser": "^5.3.8",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"typescript": "^4.0.5"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { readFileSync, promises as fs } from "fs";
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
|
||||
const input = "src/web";
|
||||
const requirejs = readFileSync("node_modules/requirejs/require.js");
|
||||
@ -12,7 +13,14 @@ export default {
|
||||
file: "build/rollup/index.js",
|
||||
// We bundle requirejs (and config) into the header. It's rather gross
|
||||
// but also works reasonably well.
|
||||
banner: `${requirejs}\nrequire.config({ paths: { copycat: "https://copy-cat.squiddev.cc" } });`,
|
||||
// Also suffix a ?v=${date} onto the end in the event we need to require a specific copy-cat version.
|
||||
banner: `
|
||||
${requirejs}
|
||||
require.config({
|
||||
paths: { copycat: "https://copy-cat.squiddev.cc" },
|
||||
urlArgs: function(id) { return id == "copycat/embed" ? "?v=20211127" : ""; }
|
||||
});
|
||||
`,
|
||||
format: "amd",
|
||||
preferConst: true,
|
||||
amd: {
|
||||
@ -27,22 +35,6 @@ export default {
|
||||
|
||||
{
|
||||
name: "cc-tweaked",
|
||||
async options(options) {
|
||||
// Generate .d.ts files for all /mount files. This is the worst way to do it,
|
||||
// but we need to run before the TS pass.
|
||||
const template = "declare const contents : string;\nexport default contents;\n";
|
||||
const files = await fs.readdir(`${input}/mount`);
|
||||
|
||||
await Promise.all(files
|
||||
.filter(x => path.extname(x) !== ".ts")
|
||||
.map(async file => {
|
||||
const path = `${input}/mount/${file}.d.ts`;
|
||||
const contents = await fs.readFile(path, { encoding: "utf-8" }).catch(() => "");
|
||||
if (contents !== template) await fs.writeFile(path, template);
|
||||
})
|
||||
);
|
||||
return options;
|
||||
},
|
||||
async transform(code, file) {
|
||||
// Allow loading files in /mount.
|
||||
const ext = path.extname(file);
|
||||
@ -50,6 +42,8 @@ export default {
|
||||
? `export default ${JSON.stringify(code)};\n`
|
||||
: null;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
terser(),
|
||||
],
|
||||
};
|
||||
|
@ -10,6 +10,8 @@ import net.minecraftforge.common.capabilities.Capability;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The interface that defines a peripheral.
|
||||
@ -31,6 +33,18 @@ public interface IPeripheral
|
||||
@Nonnull
|
||||
String getType();
|
||||
|
||||
/**
|
||||
* Return additional types/traits associated with this object.
|
||||
*
|
||||
* @return A collection of additional object traits.
|
||||
* @see PeripheralType#getAdditionalTypes()
|
||||
*/
|
||||
@Nonnull
|
||||
default Set<String> getAdditionalTypes()
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is called when when a computer is attaching to the peripheral.
|
||||
*
|
||||
|
@ -6,9 +6,13 @@
|
||||
package dan200.computercraft.api.peripheral;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The type of a {@link GenericPeripheral}.
|
||||
@ -18,13 +22,19 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
public final class PeripheralType
|
||||
{
|
||||
private static final PeripheralType UNTYPED = new PeripheralType( null );
|
||||
private static final PeripheralType UNTYPED = new PeripheralType( null, Collections.emptySet() );
|
||||
|
||||
private final String type;
|
||||
private final Set<String> additionalTypes;
|
||||
|
||||
public PeripheralType( String type )
|
||||
public PeripheralType( String type, Set<String> additionalTypes )
|
||||
{
|
||||
this.type = type;
|
||||
this.additionalTypes = additionalTypes;
|
||||
if( additionalTypes.contains( null ) )
|
||||
{
|
||||
throw new IllegalArgumentException( "All additional types must be non-null" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,7 +56,55 @@ public final class PeripheralType
|
||||
public static PeripheralType ofType( @Nonnull String type )
|
||||
{
|
||||
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||
return new PeripheralType( type );
|
||||
return new PeripheralType( type, Collections.emptySet() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new non-empty peripheral type with additional traits.
|
||||
*
|
||||
* @param type The name of the type.
|
||||
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||
* @return The constructed peripheral type.
|
||||
*/
|
||||
public static PeripheralType ofType( @Nonnull String type, Collection<String> additionalTypes )
|
||||
{
|
||||
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||
return new PeripheralType( type, ImmutableSet.copyOf( additionalTypes ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new non-empty peripheral type with additional traits.
|
||||
*
|
||||
* @param type The name of the type.
|
||||
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||
* @return The constructed peripheral type.
|
||||
*/
|
||||
public static PeripheralType ofType( @Nonnull String type, @Nonnull String... additionalTypes )
|
||||
{
|
||||
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||
return new PeripheralType( type, ImmutableSet.copyOf( additionalTypes ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new peripheral type with no primary type but additional traits.
|
||||
*
|
||||
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||
* @return The constructed peripheral type.
|
||||
*/
|
||||
public static PeripheralType ofAdditional( Collection<String> additionalTypes )
|
||||
{
|
||||
return new PeripheralType( null, ImmutableSet.copyOf( additionalTypes ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new peripheral type with no primary type but additional traits.
|
||||
*
|
||||
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||
* @return The constructed peripheral type.
|
||||
*/
|
||||
public static PeripheralType ofAdditional( @Nonnull String... additionalTypes )
|
||||
{
|
||||
return new PeripheralType( null, ImmutableSet.copyOf( additionalTypes ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,4 +117,15 @@ public final class PeripheralType
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any additional types or "traits" of this peripheral. These effectively act as a standard set of interfaces
|
||||
* a peripheral might have.
|
||||
*
|
||||
* @return All additional types.
|
||||
*/
|
||||
public Set<String> getAdditionalTypes()
|
||||
{
|
||||
return additionalTypes;
|
||||
}
|
||||
}
|
||||
|
@ -484,7 +484,7 @@ public class FSAPI implements ILuaAPI
|
||||
*
|
||||
* This string is formatted like a normal path string, but can include any
|
||||
* number of wildcards ({@code *}) to look for files matching anything.
|
||||
* For example, {@code rom/* /command*} will look for any path starting with
|
||||
* For example, <code>rom/*/command*</code> will look for any path starting with
|
||||
* {@code command} inside any subdirectory of {@code /rom}.
|
||||
*
|
||||
* @param path The wildcard-qualified path to search for.
|
||||
|
@ -17,6 +17,7 @@ import dan200.computercraft.core.asm.NamedMethod;
|
||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.shared.util.LuaUtil;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -36,6 +37,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
private final IPeripheral peripheral;
|
||||
|
||||
private final String type;
|
||||
private final Set<String> additionalTypes;
|
||||
private final Map<String, PeripheralMethod> methodMap;
|
||||
private boolean attached;
|
||||
|
||||
@ -47,6 +49,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
attached = false;
|
||||
|
||||
type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" );
|
||||
additionalTypes = peripheral.getAdditionalTypes();
|
||||
|
||||
methodMap = PeripheralAPI.getMethods( peripheral );
|
||||
}
|
||||
@ -61,6 +64,11 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
return type;
|
||||
}
|
||||
|
||||
public Set<String> getAdditionalTypes()
|
||||
{
|
||||
return additionalTypes;
|
||||
}
|
||||
|
||||
public Collection<String> getMethods()
|
||||
{
|
||||
return methodMap.keySet();
|
||||
@ -298,7 +306,23 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
synchronized( peripherals )
|
||||
{
|
||||
PeripheralWrapper p = peripherals[side.ordinal()];
|
||||
if( p != null ) return new Object[] { p.getType() };
|
||||
return p == null ? null : LuaUtil.consArray( p.getType(), p.getAdditionalTypes() );
|
||||
}
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final Object[] hasType( String sideName, String type )
|
||||
{
|
||||
ComputerSide side = ComputerSide.valueOfInsensitive( sideName );
|
||||
if( side == null ) return null;
|
||||
|
||||
synchronized( peripherals )
|
||||
{
|
||||
PeripheralWrapper p = peripherals[side.ordinal()];
|
||||
if( p != null )
|
||||
{
|
||||
return new Object[] { p.getType().equals( type ) || p.getAdditionalTypes().contains( type ) };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -38,13 +38,13 @@ public final class Peripherals
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static IPeripheral getPeripheral( Level world, BlockPos pos, Direction side, NonNullConsumer<LazyOptional<IPeripheral>> invalidate )
|
||||
public static IPeripheral getPeripheral( Level world, BlockPos pos, Direction side, NonNullConsumer<Object> invalidate )
|
||||
{
|
||||
return world.isInWorldBounds( pos ) && !world.isClientSide ? getPeripheralAt( world, pos, side, invalidate ) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static IPeripheral getPeripheralAt( Level world, BlockPos pos, Direction side, NonNullConsumer<LazyOptional<IPeripheral>> invalidate )
|
||||
private static IPeripheral getPeripheralAt( Level world, BlockPos pos, Direction side, NonNullConsumer<? super Object> invalidate )
|
||||
{
|
||||
BlockEntity block = world.getBlockEntity( pos );
|
||||
if( block != null )
|
||||
|
@ -59,7 +59,7 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
||||
super.onPlace( state, world, pos, oldState, isMoving );
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( tile instanceof TileComputerBase computer ) computer.updateInput();
|
||||
if( tile instanceof TileComputerBase computer ) computer.updateInputsImmediately( );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,14 +31,9 @@ import net.minecraft.world.Nameable;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.DiodeBlock;
|
||||
import net.minecraft.world.level.block.RedStoneWireBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -57,7 +52,9 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
private boolean on = false;
|
||||
boolean startOn = false;
|
||||
private boolean fresh = false;
|
||||
private final NonNullConsumer<LazyOptional<IPeripheral>>[] invalidate;
|
||||
|
||||
private int invalidSides = 0;
|
||||
private final NonNullConsumer<Object>[] invalidate;
|
||||
|
||||
private final ComputerFamily family;
|
||||
|
||||
@ -68,10 +65,11 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
|
||||
// We cache these so we can guarantee we only ever register one listener for adjacent capabilities.
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||
NonNullConsumer<LazyOptional<IPeripheral>>[] invalidate = this.invalidate = new NonNullConsumer[6];
|
||||
NonNullConsumer<Object>[] invalidate = this.invalidate = new NonNullConsumer[6];
|
||||
for( Direction direction : Direction.values() )
|
||||
{
|
||||
invalidate[direction.ordinal()] = o -> updateInput( direction );
|
||||
int mask = 1 << direction.ordinal();
|
||||
invalidate[direction.ordinal()] = o -> invalidSides |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,19 +141,26 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
@Override
|
||||
public void onNeighbourChange( @Nonnull BlockPos neighbour )
|
||||
{
|
||||
updateInput( neighbour );
|
||||
updateInputAt( neighbour );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour )
|
||||
{
|
||||
updateInput( neighbour );
|
||||
updateInputAt( neighbour );
|
||||
}
|
||||
|
||||
protected void serverTick()
|
||||
{
|
||||
ServerComputer computer = createServerComputer();
|
||||
if( computer == null ) return;
|
||||
|
||||
if( invalidSides != 0 )
|
||||
{
|
||||
for( Direction direction : DirectionUtil.FACINGS )
|
||||
{
|
||||
if( (invalidSides & (1 << direction.ordinal())) != 0 ) refreshPeripheral( computer, direction );
|
||||
}
|
||||
}
|
||||
|
||||
// If the computer isn't on and should be, then turn it on
|
||||
if( startOn || (fresh && on) )
|
||||
@ -222,89 +227,80 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
return localSide;
|
||||
}
|
||||
|
||||
private void updateSideInput( ServerComputer computer, Direction dir, BlockPos offset )
|
||||
private void updateRedstoneInput( @Nonnull ServerComputer computer, Direction dir, BlockPos targetPos )
|
||||
{
|
||||
Direction offsetSide = dir.getOpposite();
|
||||
ComputerSide localDir = remapToLocalSide( dir );
|
||||
|
||||
computer.setRedstoneInput( localDir, getRedstoneInput( level, offset, dir ) );
|
||||
computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( getLevel(), offset, offsetSide ) );
|
||||
if( !isPeripheralBlockedOnSide( localDir ) )
|
||||
{
|
||||
IPeripheral peripheral = Peripherals.getPeripheral( getLevel(), offset, offsetSide, invalidate[dir.ordinal()] );
|
||||
computer.setPeripheral( localDir, peripheral );
|
||||
}
|
||||
computer.setRedstoneInput( localDir, RedstoneUtil.getRedstoneInput( level, targetPos, dir ) );
|
||||
computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( getLevel(), targetPos, offsetSide ) );
|
||||
}
|
||||
|
||||
private void refreshPeripheral( @Nonnull ServerComputer computer, Direction dir )
|
||||
{
|
||||
invalidSides &= ~(1 << dir.ordinal());
|
||||
|
||||
ComputerSide localDir = remapToLocalSide( dir );
|
||||
if( isPeripheralBlockedOnSide( localDir ) ) return;
|
||||
|
||||
Direction offsetSide = dir.getOpposite();
|
||||
IPeripheral peripheral = Peripherals.getPeripheral( getLevel(), getBlockPos().relative( dir ), offsetSide, invalidate[dir.ordinal()] );
|
||||
computer.setPeripheral( localDir, peripheral );
|
||||
}
|
||||
|
||||
public void updateInputsImmediately()
|
||||
{
|
||||
ServerComputer computer = getServerComputer();
|
||||
if( computer != null ) updateInputsImmediately( computer );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the redstone input for an adjacent block.
|
||||
* Update all redstone and peripherals.
|
||||
*
|
||||
* @param world The world we exist in
|
||||
* @param pos The position of the neighbour
|
||||
* @param side The side we are reading from
|
||||
* @return The effective redstone power
|
||||
* @see DiodeBlock#getInputSignal(Level, BlockPos, BlockState)
|
||||
* This should only be really be called when the computer is being ticked (though there are some cases where it
|
||||
* won't be), as peripheral scanning requires adjacent tiles to be in a "correct" state - which may not be the case
|
||||
* if they're still updating!
|
||||
*
|
||||
* @param computer The current computer instance.
|
||||
*/
|
||||
protected static int getRedstoneInput( Level world, BlockPos pos, Direction side )
|
||||
private void updateInputsImmediately( @Nonnull ServerComputer computer )
|
||||
{
|
||||
int power = world.getSignal( pos, side );
|
||||
if( power >= 15 ) return power;
|
||||
|
||||
BlockState neighbour = world.getBlockState( pos );
|
||||
return neighbour.getBlock() == Blocks.REDSTONE_WIRE
|
||||
? Math.max( power, neighbour.getValue( RedStoneWireBlock.POWER ) )
|
||||
: power;
|
||||
}
|
||||
|
||||
public void updateInput()
|
||||
{
|
||||
if( getLevel() == null || getLevel().isClientSide ) return;
|
||||
|
||||
// Update all sides
|
||||
ServerComputer computer = getServerComputer();
|
||||
if( computer == null ) return;
|
||||
|
||||
BlockPos pos = computer.getPosition();
|
||||
BlockPos pos = getBlockPos();
|
||||
for( Direction dir : DirectionUtil.FACINGS )
|
||||
{
|
||||
updateSideInput( computer, dir, pos.relative( dir ) );
|
||||
updateRedstoneInput( computer, dir, pos.relative( dir ) );
|
||||
refreshPeripheral( computer, dir );
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInput( BlockPos neighbour )
|
||||
private void updateInputAt( @Nonnull BlockPos neighbour )
|
||||
{
|
||||
if( getLevel() == null || getLevel().isClientSide ) return;
|
||||
|
||||
ServerComputer computer = getServerComputer();
|
||||
if( computer == null ) return;
|
||||
|
||||
for( Direction dir : DirectionUtil.FACINGS )
|
||||
{
|
||||
BlockPos offset = worldPosition.relative( dir );
|
||||
BlockPos offset = getBlockPos().relative( dir );
|
||||
if( offset.equals( neighbour ) )
|
||||
{
|
||||
updateSideInput( computer, dir, offset );
|
||||
updateRedstoneInput( computer, dir, offset );
|
||||
invalidSides |= 1 << dir.ordinal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the position is not any adjacent one, update all inputs.
|
||||
updateInput();
|
||||
}
|
||||
|
||||
private void updateInput( Direction dir )
|
||||
{
|
||||
if( getLevel() == null || getLevel().isClientSide ) return;
|
||||
|
||||
ServerComputer computer = getServerComputer();
|
||||
if( computer == null ) return;
|
||||
|
||||
updateSideInput( computer, dir, worldPosition.relative( dir ) );
|
||||
// If the position is not any adjacent one, update all inputs. This is pretty terrible, but some redstone mods
|
||||
// handle this incorrectly.
|
||||
BlockPos pos = getBlockPos();
|
||||
for( Direction dir : DirectionUtil.FACINGS ) updateRedstoneInput( computer, dir, pos.relative( dir ) );
|
||||
invalidSides = (1 << 6) - 1; // Mark all peripherals as dirty.
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the block's state and propagate redstone output.
|
||||
*/
|
||||
public void updateOutput()
|
||||
{
|
||||
// Update redstone
|
||||
updateBlock();
|
||||
for( Direction dir : DirectionUtil.FACINGS )
|
||||
{
|
||||
@ -354,9 +350,10 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
return family;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ServerComputer createServerComputer()
|
||||
{
|
||||
if( getLevel().isClientSide ) return null;
|
||||
if( getLevel().isClientSide ) throw new IllegalStateException( "Cannot access server computer on the client." );
|
||||
|
||||
boolean changed = false;
|
||||
if( instanceID < 0 )
|
||||
@ -364,18 +361,21 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID();
|
||||
changed = true;
|
||||
}
|
||||
if( !ComputerCraft.serverComputerRegistry.contains( instanceID ) )
|
||||
|
||||
ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instanceID );
|
||||
if( computer == null )
|
||||
{
|
||||
ServerComputer computer = createComputer( instanceID, computerID );
|
||||
computer = createComputer( instanceID, computerID );
|
||||
ComputerCraft.serverComputerRegistry.add( instanceID, computer );
|
||||
fresh = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if( changed ) updateInput();
|
||||
return ComputerCraft.serverComputerRegistry.get( instanceID );
|
||||
if( changed ) updateInputsImmediately( computer );
|
||||
return computer;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ServerComputer getServerComputer()
|
||||
{
|
||||
return getLevel().isClientSide ? null : ComputerCraft.serverComputerRegistry.get( instanceID );
|
||||
|
@ -128,7 +128,7 @@ public class CommandBlockPeripheral implements IPeripheral, ICapabilityProvider
|
||||
public static void onCapability( AttachCapabilitiesEvent<BlockEntity> event )
|
||||
{
|
||||
BlockEntity tile = event.getObject();
|
||||
if( tile instanceof CommandBlockEntity )
|
||||
if( ComputerCraft.enableCommandBlock && tile instanceof CommandBlockEntity )
|
||||
{
|
||||
CommandBlockPeripheral peripheral = new CommandBlockPeripheral( (CommandBlockEntity) tile );
|
||||
event.addCapability( CAP_ID, peripheral );
|
||||
|
@ -18,18 +18,21 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
class GenericPeripheral implements IDynamicPeripheral
|
||||
{
|
||||
private final String type;
|
||||
private final Set<String> additionalTypes;
|
||||
private final BlockEntity tile;
|
||||
private final List<SaturatedMethod> methods;
|
||||
|
||||
GenericPeripheral( BlockEntity tile, String name, List<SaturatedMethod> methods )
|
||||
GenericPeripheral( BlockEntity tile, String name, Set<String> additionalTypes, List<SaturatedMethod> methods )
|
||||
{
|
||||
ResourceLocation type = tile.getType().getRegistryName();
|
||||
this.tile = tile;
|
||||
this.type = name != null ? name : (type != null ? type.toString() : "unknown");
|
||||
this.additionalTypes = additionalTypes;
|
||||
this.methods = methods;
|
||||
}
|
||||
|
||||
@ -56,6 +59,13 @@ class GenericPeripheral implements IDynamicPeripheral
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<String> getAdditionalTypes()
|
||||
{
|
||||
return additionalTypes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getTarget()
|
||||
|
@ -9,6 +9,7 @@ import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.PeripheralType;
|
||||
import dan200.computercraft.core.asm.NamedMethod;
|
||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.Level;
|
||||
@ -19,9 +20,7 @@ import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
public class GenericPeripheralProvider
|
||||
{
|
||||
@ -34,7 +33,7 @@ public class GenericPeripheralProvider
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static IPeripheral getPeripheral( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side, NonNullConsumer<LazyOptional<IPeripheral>> invalidate )
|
||||
public static IPeripheral getPeripheral( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side, NonNullConsumer<Object> invalidate )
|
||||
{
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( tile == null ) return null;
|
||||
@ -52,7 +51,7 @@ public class GenericPeripheralProvider
|
||||
if( capabilityMethods.isEmpty() ) return;
|
||||
|
||||
saturated.addMethods( contents, capabilityMethods );
|
||||
wrapper.addListener( cast( invalidate ) );
|
||||
CapabilityUtil.addListener( wrapper, invalidate );
|
||||
} );
|
||||
}
|
||||
|
||||
@ -61,15 +60,16 @@ public class GenericPeripheralProvider
|
||||
|
||||
private static class GenericPeripheralBuilder
|
||||
{
|
||||
String name;
|
||||
final ArrayList<SaturatedMethod> methods = new ArrayList<>( 0 );
|
||||
private String name;
|
||||
private final Set<String> additionalTypes = new HashSet<>( 0 );
|
||||
private final ArrayList<SaturatedMethod> methods = new ArrayList<>( 0 );
|
||||
|
||||
IPeripheral toPeripheral( BlockEntity tile )
|
||||
{
|
||||
if( methods.isEmpty() ) return null;
|
||||
|
||||
methods.trimToSize();
|
||||
return new GenericPeripheral( tile, name, methods );
|
||||
return new GenericPeripheral( tile, name, additionalTypes, methods );
|
||||
}
|
||||
|
||||
void addMethods( Object target, List<NamedMethod<PeripheralMethod>> methods )
|
||||
@ -88,13 +88,8 @@ public class GenericPeripheralProvider
|
||||
String name = type.getPrimaryType();
|
||||
if( this.name == null || this.name.compareTo( name ) > 0 ) this.name = name;
|
||||
}
|
||||
if( type != null ) additionalTypes.addAll( type.getAdditionalTypes() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||
private static <T> NonNullConsumer<T> cast( NonNullConsumer<?> consumer )
|
||||
{
|
||||
return (NonNullConsumer) consumer;
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,9 @@
|
||||
package dan200.computercraft.shared.peripheral.generic.methods;
|
||||
|
||||
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 net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.energy.IEnergyStorage;
|
||||
|
||||
@ -25,8 +26,15 @@ import javax.annotation.Nonnull;
|
||||
*
|
||||
* @cc.module energy_storage
|
||||
*/
|
||||
public class EnergyMethods implements GenericSource
|
||||
public class EnergyMethods implements GenericPeripheral
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
public PeripheralType getType()
|
||||
{
|
||||
return PeripheralType.ofAdditional( "energy_storage" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ResourceLocation id()
|
||||
|
@ -6,13 +6,15 @@
|
||||
package dan200.computercraft.shared.peripheral.generic.methods;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.GenericSource;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.api.peripheral.GenericPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.PeripheralType;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.FluidData;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
@ -34,8 +36,15 @@ import static dan200.computercraft.shared.peripheral.generic.methods.ArgumentHel
|
||||
*
|
||||
* @cc.module fluid_storage
|
||||
*/
|
||||
public class FluidMethods implements GenericSource
|
||||
public class FluidMethods implements GenericPeripheral
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
public PeripheralType getType()
|
||||
{
|
||||
return PeripheralType.ofAdditional( "fluid_storage" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ResourceLocation id()
|
||||
@ -155,13 +164,15 @@ public class FluidMethods implements GenericSource
|
||||
@Nullable
|
||||
private static IFluidHandler extractHandler( @Nullable Object object )
|
||||
{
|
||||
if( object instanceof ICapabilityProvider )
|
||||
if( object instanceof BlockEntity blockEntity && blockEntity.isRemoved() ) return null;
|
||||
|
||||
if( object instanceof ICapabilityProvider provider )
|
||||
{
|
||||
LazyOptional<IFluidHandler> cap = ((ICapabilityProvider) object).getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY );
|
||||
LazyOptional<IFluidHandler> cap = provider.getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY );
|
||||
if( cap.isPresent() ) return cap.orElseThrow( NullPointerException::new );
|
||||
}
|
||||
|
||||
if( object instanceof IFluidHandler ) return (IFluidHandler) object;
|
||||
if( object instanceof IFluidHandler handler ) return handler;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -6,16 +6,18 @@
|
||||
package dan200.computercraft.shared.peripheral.generic.methods;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.GenericSource;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.api.peripheral.GenericPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.PeripheralType;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.ItemData;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
@ -36,8 +38,15 @@ import static dan200.computercraft.shared.peripheral.generic.methods.ArgumentHel
|
||||
*
|
||||
* @cc.module inventory
|
||||
*/
|
||||
public class InventoryMethods implements GenericSource
|
||||
public class InventoryMethods implements GenericPeripheral
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
public PeripheralType getType()
|
||||
{
|
||||
return PeripheralType.ofAdditional( "inventory" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ResourceLocation id()
|
||||
@ -259,14 +268,16 @@ public class InventoryMethods implements GenericSource
|
||||
@Nullable
|
||||
private static IItemHandler extractHandler( @Nullable Object object )
|
||||
{
|
||||
if( object instanceof ICapabilityProvider )
|
||||
if( object instanceof BlockEntity blockEntity && blockEntity.isRemoved() ) return null;
|
||||
|
||||
if( object instanceof ICapabilityProvider provider )
|
||||
{
|
||||
LazyOptional<IItemHandler> cap = ((ICapabilityProvider) object).getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY );
|
||||
LazyOptional<IItemHandler> cap = provider.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY );
|
||||
if( cap.isPresent() ) return cap.orElseThrow( NullPointerException::new );
|
||||
}
|
||||
|
||||
if( object instanceof IItemHandler ) return (IItemHandler) object;
|
||||
if( object instanceof Container ) return new InvWrapper( (Container) object );
|
||||
if( object instanceof IItemHandler handler ) return handler;
|
||||
if( object instanceof Container container ) return new InvWrapper( container );
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,9 @@ public class TileCable extends TileGeneric
|
||||
}
|
||||
}
|
||||
|
||||
private boolean invalidPeripheral;
|
||||
private boolean peripheralAccessAllowed;
|
||||
private final WiredModemLocalPeripheral peripheral = new WiredModemLocalPeripheral( this::refreshPeripheral );
|
||||
private final WiredModemLocalPeripheral peripheral = new WiredModemLocalPeripheral( this::queueRefreshPeripheral );
|
||||
|
||||
private boolean destroyed = false;
|
||||
|
||||
@ -234,12 +235,20 @@ public class TileCable extends TileGeneric
|
||||
if( !level.isClientSide && peripheralAccessAllowed )
|
||||
{
|
||||
Direction facing = getDirection();
|
||||
if( getBlockPos().relative( facing ).equals( neighbour ) ) refreshPeripheral();
|
||||
if( getBlockPos().relative( facing ).equals( neighbour ) ) queueRefreshPeripheral();
|
||||
}
|
||||
}
|
||||
|
||||
private void queueRefreshPeripheral()
|
||||
{
|
||||
if( invalidPeripheral ) return;
|
||||
invalidPeripheral = true;
|
||||
TickScheduler.schedule( this );
|
||||
}
|
||||
|
||||
private void refreshPeripheral()
|
||||
{
|
||||
invalidPeripheral = false;
|
||||
if( level != null && !isRemoved() && peripheral.attach( level, getBlockPos(), getDirection() ) )
|
||||
{
|
||||
updateConnectedPeripherals();
|
||||
@ -310,6 +319,8 @@ public class TileCable extends TileGeneric
|
||||
{
|
||||
if( getLevel().isClientSide ) return;
|
||||
|
||||
if( invalidPeripheral ) refreshPeripheral();
|
||||
|
||||
if( modem.getModemState().pollChanged() ) updateBlockState();
|
||||
|
||||
if( !connectionsFormed )
|
||||
|
@ -108,13 +108,15 @@ public class TileWiredModemFull extends TileGeneric
|
||||
|
||||
private final NonNullConsumer<LazyOptional<IWiredElement>> connectedNodeChanged = x -> connectionsChanged();
|
||||
|
||||
private int invalidSides = 0;
|
||||
|
||||
public TileWiredModemFull( BlockEntityType<TileWiredModemFull> type, BlockPos pos, BlockState state )
|
||||
{
|
||||
super( type, pos, state );
|
||||
for( int i = 0; i < peripherals.length; i++ )
|
||||
{
|
||||
Direction facing = Direction.from3DDataValue( i );
|
||||
peripherals[i] = new WiredModemLocalPeripheral( () -> refreshPeripheral( facing ) );
|
||||
peripherals[i] = new WiredModemLocalPeripheral( () -> queueRefreshPeripheral( facing ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,13 +175,20 @@ public class TileWiredModemFull extends TileGeneric
|
||||
{
|
||||
for( Direction facing : DirectionUtil.FACINGS )
|
||||
{
|
||||
if( getBlockPos().relative( facing ).equals( neighbour ) ) refreshPeripheral( facing );
|
||||
if( getBlockPos().relative( facing ).equals( neighbour ) ) queueRefreshPeripheral( facing );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void queueRefreshPeripheral( @Nonnull Direction facing )
|
||||
{
|
||||
if( invalidSides == 0 ) TickScheduler.schedule( this );
|
||||
invalidSides |= 1 << facing.ordinal();
|
||||
}
|
||||
|
||||
private void refreshPeripheral( @Nonnull Direction facing )
|
||||
{
|
||||
invalidSides &= ~(1 << facing.ordinal());
|
||||
WiredModemLocalPeripheral peripheral = peripherals[facing.ordinal()];
|
||||
if( level != null && !isRemoved() && peripheral.attach( level, getBlockPos(), facing ) )
|
||||
{
|
||||
@ -262,6 +271,14 @@ public class TileWiredModemFull extends TileGeneric
|
||||
{
|
||||
if( getLevel().isClientSide ) return;
|
||||
|
||||
if( invalidSides != 0 )
|
||||
{
|
||||
for( Direction direction : DirectionUtil.FACINGS )
|
||||
{
|
||||
if( (invalidSides & (1 << direction.ordinal())) != 0 ) refreshPeripheral( direction );
|
||||
}
|
||||
}
|
||||
|
||||
if( modemState.pollChanged() ) updateBlockState();
|
||||
|
||||
if( !connectionsFormed )
|
||||
|
@ -15,7 +15,6 @@ import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -38,7 +37,7 @@ public final class WiredModemLocalPeripheral
|
||||
private String type;
|
||||
|
||||
private IPeripheral peripheral;
|
||||
private final NonNullConsumer<LazyOptional<IPeripheral>> invalidate;
|
||||
private final NonNullConsumer<Object> invalidate;
|
||||
|
||||
public WiredModemLocalPeripheral( @Nonnull Runnable invalidate )
|
||||
{
|
||||
|
@ -21,6 +21,7 @@ import dan200.computercraft.core.apis.PeripheralAPI;
|
||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemPeripheral;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.util.LuaUtil;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -118,13 +119,35 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
* @param name The peripheral's name.
|
||||
* @return The peripheral's name.
|
||||
* @cc.treturn string|nil The peripheral's type, or {@code nil} if it is not present.
|
||||
* @cc.changed 1.99 Peripherals can have multiple types - this function returns multiple values.
|
||||
* @see PeripheralAPI#getType
|
||||
*/
|
||||
@LuaFunction
|
||||
public final Object[] getTypeRemote( IComputerAccess computer, String name )
|
||||
{
|
||||
RemotePeripheralWrapper wrapper = getWrapper( computer, name );
|
||||
return wrapper != null ? new Object[] { wrapper.getType() } : null;
|
||||
return wrapper == null ? null : LuaUtil.consArray( wrapper.getType(), wrapper.getAdditionalTypes() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a peripheral is of a particular type.
|
||||
*
|
||||
* <blockquote><strong>Important:</strong> This function only appears on wired modems. Check {@link #isWireless}
|
||||
* returns false before calling it.</blockquote>
|
||||
*
|
||||
* @param computer The calling computer.
|
||||
* @param name The peripheral's name.
|
||||
* @param type The type to check.
|
||||
* @return The peripheral's name.
|
||||
* @cc.treturn boolean|nil If a peripheral has a particular type, or {@literal nil} if it is not present.
|
||||
* @cc.since 1.99
|
||||
* @see PeripheralAPI#getType
|
||||
*/
|
||||
@LuaFunction
|
||||
public final Object[] hasTypeRemote( IComputerAccess computer, String name, String type )
|
||||
{
|
||||
RemotePeripheralWrapper wrapper = getWrapper( computer, name );
|
||||
return wrapper == null ? null : new Object[] { wrapper.getType().equals( type ) || wrapper.getAdditionalTypes().contains( getType() ) };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -307,6 +330,7 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
private final String name;
|
||||
|
||||
private final String type;
|
||||
private final Set<String> additionalTypes;
|
||||
private final Map<String, PeripheralMethod> methodMap;
|
||||
|
||||
private volatile boolean attached;
|
||||
@ -320,6 +344,7 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
this.name = name;
|
||||
|
||||
type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" );
|
||||
additionalTypes = peripheral.getAdditionalTypes();
|
||||
methodMap = PeripheralAPI.getMethods( peripheral );
|
||||
}
|
||||
|
||||
@ -353,6 +378,11 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
return type;
|
||||
}
|
||||
|
||||
public Set<String> getAdditionalTypes()
|
||||
{
|
||||
return additionalTypes;
|
||||
}
|
||||
|
||||
public Collection<String> getMethodNames()
|
||||
{
|
||||
return methodMap.keySet();
|
||||
|
@ -331,8 +331,10 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
{
|
||||
if( dir.getAxis() == Direction.Axis.Y ) dir = Direction.NORTH;
|
||||
level.setBlockAndUpdate( worldPosition, getBlockState().setValue( BlockTurtle.FACING, dir ) );
|
||||
|
||||
updateOutput();
|
||||
updateInput();
|
||||
updateInputsImmediately();
|
||||
|
||||
onTileEntityChange();
|
||||
}
|
||||
|
||||
|
@ -332,16 +332,17 @@ public class TurtleBrain implements ITurtleAccess
|
||||
// Copy the old turtle state into the new turtle
|
||||
newTurtle.setLevel( world );
|
||||
newTurtle.transferStateFrom( oldOwner );
|
||||
newTurtle.createServerComputer().setLevel( world );
|
||||
newTurtle.createServerComputer().setPosition( pos );
|
||||
|
||||
ServerComputer computer = newTurtle.createServerComputer();
|
||||
computer.setLevel( world );
|
||||
computer.setPosition( pos );
|
||||
|
||||
// Remove the old turtle
|
||||
oldWorld.removeBlock( oldPos, false );
|
||||
|
||||
// Make sure everybody knows about it
|
||||
newTurtle.updateBlock();
|
||||
newTurtle.updateInput();
|
||||
newTurtle.updateOutput();
|
||||
newTurtle.updateInputsImmediately();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -613,16 +614,16 @@ public class TurtleBrain implements ITurtleAccess
|
||||
@Override
|
||||
public void setUpgrade( @Nonnull TurtleSide side, ITurtleUpgrade upgrade )
|
||||
{
|
||||
if( !setUpgradeDirect( side, upgrade ) ) return;
|
||||
if( !setUpgradeDirect( side, upgrade ) || owner.getLevel() == null ) return;
|
||||
|
||||
// This is a separate function to avoid updating the block when reading the NBT. We don't need to do this as
|
||||
// either the block is newly placed (and so won't have changed) or is being updated with /data, which calls
|
||||
// updateBlock for us.
|
||||
if( owner.getLevel() != null )
|
||||
{
|
||||
owner.updateBlock();
|
||||
owner.updateInput();
|
||||
}
|
||||
owner.updateBlock();
|
||||
|
||||
// Recompute peripherals in case an upgrade being removed has exposed a new peripheral.
|
||||
// TODO: Only update peripherals, or even only two sides?
|
||||
owner.updateInputsImmediately();
|
||||
}
|
||||
|
||||
private boolean setUpgradeDirect( @Nonnull TurtleSide side, ITurtleUpgrade upgrade )
|
||||
@ -644,7 +645,7 @@ public class TurtleBrain implements ITurtleAccess
|
||||
if( upgrade != null ) upgrades.put( side, upgrade );
|
||||
|
||||
// Notify clients and create peripherals
|
||||
if( owner.getLevel() != null )
|
||||
if( owner.getLevel() != null && !owner.getLevel().isClientSide )
|
||||
{
|
||||
updatePeripherals( owner.createServerComputer() );
|
||||
}
|
||||
|
@ -35,12 +35,20 @@ public final class CapabilityUtil
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void addListener( LazyOptional<T> p, NonNullConsumer<? super LazyOptional<T>> invalidate )
|
||||
{
|
||||
// We can make this safe with invalidate::accept, but then we're allocating it's just kind of absurd.
|
||||
@SuppressWarnings( "unchecked" )
|
||||
NonNullConsumer<LazyOptional<T>> safeInvalidate = (NonNullConsumer<LazyOptional<T>>) invalidate;
|
||||
p.addListener( safeInvalidate );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T unwrap( LazyOptional<T> p, NonNullConsumer<LazyOptional<T>> invalidate )
|
||||
public static <T> T unwrap( LazyOptional<T> p, NonNullConsumer<? super LazyOptional<T>> invalidate )
|
||||
{
|
||||
if( !p.isPresent() ) return null;
|
||||
|
||||
p.addListener( invalidate );
|
||||
addListener( p, invalidate );
|
||||
return p.orElseThrow( NullPointerException::new );
|
||||
}
|
||||
|
||||
|
23
src/main/java/dan200/computercraft/shared/util/LuaUtil.java
Normal file
23
src/main/java/dan200/computercraft/shared/util/LuaUtil.java
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class LuaUtil
|
||||
{
|
||||
public static Object[] consArray( Object value, Collection<?> rest )
|
||||
{
|
||||
if( rest.isEmpty() ) return new Object[] { value };
|
||||
|
||||
// I'm not proud of this code.
|
||||
Object[] out = new Object[rest.size() + 1];
|
||||
out[0] = value;
|
||||
int i = 1;
|
||||
for( Object additionalType : rest ) out[i++] = additionalType;
|
||||
return out;
|
||||
}
|
||||
}
|
@ -8,6 +8,9 @@ package dan200.computercraft.shared.util;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.DiodeBlock;
|
||||
import net.minecraft.world.level.block.RedStoneWireBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.event.ForgeEventFactory;
|
||||
|
||||
@ -15,6 +18,30 @@ import java.util.EnumSet;
|
||||
|
||||
public final class RedstoneUtil
|
||||
{
|
||||
private RedstoneUtil()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the redstone input for an adjacent block.
|
||||
*
|
||||
* @param world The world we exist in
|
||||
* @param pos The position of the neighbour
|
||||
* @param side The side we are reading from
|
||||
* @return The effective redstone power
|
||||
* @see DiodeBlock#getInputSignal(Level, BlockPos, BlockState)
|
||||
*/
|
||||
public static int getRedstoneInput( Level world, BlockPos pos, Direction side )
|
||||
{
|
||||
int power = world.getSignal( pos, side );
|
||||
if( power >= 15 ) return power;
|
||||
|
||||
BlockState neighbour = world.getBlockState( pos );
|
||||
return neighbour.getBlock() == Blocks.REDSTONE_WIRE
|
||||
? Math.max( power, neighbour.getValue( RedStoneWireBlock.POWER ) )
|
||||
: power;
|
||||
}
|
||||
|
||||
public static void propagateRedstoneOutput( Level world, BlockPos pos, Direction side )
|
||||
{
|
||||
// Propagate ordinary output. See BlockRedstoneDiode.notifyNeighbors
|
||||
|
@ -68,7 +68,7 @@ end
|
||||
-- @{paintutils.drawImage}, or `nil` if the file does not exist.
|
||||
-- @usage Load an image and draw it.
|
||||
--
|
||||
-- local image = paintutils.loadImage("test-image.nfp")
|
||||
-- local image = paintutils.loadImage("data/example.nfp")
|
||||
-- paintutils.drawImage(image, term.getCursorPos())
|
||||
function loadImage(path)
|
||||
expect(1, path, "string")
|
||||
|
@ -1,18 +1,90 @@
|
||||
--- The Peripheral API is for interacting with peripherals connected to the
|
||||
-- computer, such as the Disk Drive, the Advanced Monitor and Monitor.
|
||||
--
|
||||
-- Each peripheral block has a name, either referring to the side the peripheral
|
||||
-- can be found on, or a name on an adjacent wired network.
|
||||
--
|
||||
-- If the peripheral is next to the computer, its side is either `front`,
|
||||
-- `back`, `left`, `right`, `top` or `bottom`. If the peripheral is attached by
|
||||
-- a cable, its side will follow the format `type_id`, for example `printer_0`.
|
||||
--
|
||||
-- Peripheral functions are called *methods*, a term borrowed from Java.
|
||||
--
|
||||
-- @module peripheral
|
||||
-- @since 1.3
|
||||
-- @changed 1.51 Add support for wired modems.
|
||||
--[[- Peripherals are blocks (or turtle and pocket computer upgrades) which can
|
||||
be controlled by a computer. For instance, the @{speaker} peripheral allows a
|
||||
computer to play music and the @{monitor} peripheral allows you to display text
|
||||
in the world.
|
||||
|
||||
## Referencing peripherals
|
||||
|
||||
Computers can interact with adjacent peripherals. Each peripheral is given a
|
||||
name based on which direction it is in. For instance, a disk drive below your
|
||||
computer will be called `"bottom"` in your Lua code, one to the left called
|
||||
`"left"` , and so on for all 6 directions (`"bottom"`, `"top"`, `"left"`,
|
||||
`"right"`, `"front"`, `"back"`).
|
||||
|
||||
You can list the names of all peripherals with the `peripherals` program, or the
|
||||
@{peripheral.getNames} function.
|
||||
|
||||
It's also possible to use peripherals which are further away from your computer
|
||||
through the use of @{modem|Wired Modems}. Place one modem against your computer,
|
||||
run Networking Cable to your peripheral, and then place another modem against
|
||||
that block. You can then right click the modem to use (or *attach*) the
|
||||
peripheral. This will print a peripheral name to chat, which can then be used
|
||||
just like a direction name to access the peripheral. You can click on the message
|
||||
to copy the name to your clipboard.
|
||||
|
||||
## Using peripherals
|
||||
|
||||
Once you have the name of a peripheral, you can call functions on it using the
|
||||
@{peripheral.call} function. This takes the name of our peripheral, the name of
|
||||
the function we want to call, and then its arguments.
|
||||
|
||||
> Some bits of the peripheral API call peripheral functions *methods* instead
|
||||
> (for example, the @{peripheral.getMethods} function). Don't worry, they're the
|
||||
> same thing!
|
||||
|
||||
Let's say we have a monitor above our computer (and so "top") and want to
|
||||
@{monitor.write|write some text to it}. We'd write the following:
|
||||
|
||||
```lua
|
||||
peripheral.call("top", "write", "This is displayed on a monitor!")
|
||||
```
|
||||
|
||||
Once you start calling making a couple of peripheral calls this can get very
|
||||
repetitive, and so we can @{peripheral.wrap|wrap} a peripheral. This builds a
|
||||
table of all the peripheral's functions so you can use it like an API or module.
|
||||
|
||||
For instance, we could have written the above example as follows:
|
||||
|
||||
```lua
|
||||
local my_monitor = peripheral.wrap("top")
|
||||
my_monitor.write("This is displayed on a monitor!")
|
||||
```
|
||||
|
||||
## Finding peripherals
|
||||
|
||||
Sometimes when you're writing a program you don't care what a peripheral is
|
||||
called, you just need to know it's there. For instance, if you're writing a
|
||||
music player, you just need a speaker - it doesn't matter if it's above or below
|
||||
the computer.
|
||||
|
||||
Thankfully there's a quick way to do this: @{peripheral.find}. This takes a
|
||||
*peripheral type* and returns all the attached peripherals which are of this
|
||||
type.
|
||||
|
||||
What is a peripheral type though? This is a string which describes what a
|
||||
peripheral is, and so what functions are available on it. For instance, speakers
|
||||
are just called `"speaker"`, and monitors `"monitor"`. Some peripherals might
|
||||
have more than one type; a Minecraft chest is both a `"minecraft:chest"` and
|
||||
`"inventory"`.
|
||||
|
||||
You can get all the types a peripheral has with @{peripheral.getType}, and check
|
||||
a peripheral is a specific type with @{peripheral.hasType}.
|
||||
|
||||
To return to our original example, let's use @{peripheral.find} to find an
|
||||
attached speaker:
|
||||
|
||||
```lua
|
||||
local speaker = peripheral.find("speaker")
|
||||
speaker.playNote("harp")
|
||||
```
|
||||
|
||||
@module peripheral
|
||||
@see event!peripheral This event is fired whenever a new peripheral is attached.
|
||||
@see event!peripheral_detach This event is fired whenever a peripheral is detached.
|
||||
@since 1.3
|
||||
@changed 1.51 Add support for wired modems.
|
||||
@changed 1.99 Peripherals can have multiple types.
|
||||
]]
|
||||
|
||||
local expect = dofile("rom/modules/main/cc/expect.lua").expect
|
||||
|
||||
@ -33,7 +105,7 @@ function getNames()
|
||||
local side = sides[n]
|
||||
if native.isPresent(side) then
|
||||
table.insert(results, side)
|
||||
if native.getType(side) == "modem" and not native.call(side, "isWireless") then
|
||||
if native.hasType(side, "modem") and not native.call(side, "isWireless") then
|
||||
local remote = native.call(side, "getNamesRemote")
|
||||
for _, name in ipairs(remote) do
|
||||
table.insert(results, name)
|
||||
@ -58,7 +130,7 @@ function isPresent(name)
|
||||
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.getType(side) == "modem" and not native.call(side, "isWireless") and
|
||||
if native.hasType(side, "modem") and not native.call(side, "isWireless") and
|
||||
native.call(side, "isPresentRemote", name)
|
||||
then
|
||||
return true
|
||||
@ -67,12 +139,17 @@ function isPresent(name)
|
||||
return false
|
||||
end
|
||||
|
||||
--- Get the type of a wrapped peripheral, or a peripheral with the given name.
|
||||
--
|
||||
-- @tparam string|table peripheral The name of the peripheral to find, or a
|
||||
-- wrapped peripheral instance.
|
||||
-- @treturn string|nil The peripheral's type, or `nil` if it is not present.
|
||||
-- @changed 1.88.0 Accepts a wrapped peripheral as an argument.
|
||||
--[[- Get the types of a named or wrapped peripheral.
|
||||
|
||||
@tparam string|table peripheral The name of the peripheral to find, or a
|
||||
wrapped peripheral instance.
|
||||
@treturn string... The peripheral's types, or `nil` if it is not present.
|
||||
@changed 1.88.0 Accepts a wrapped peripheral as an argument.
|
||||
@changed 1.99 Now returns multiple types.
|
||||
@usage Get the type of a peripheral above this computer.
|
||||
|
||||
peripheral.getType("top")
|
||||
]]
|
||||
function getType(peripheral)
|
||||
expect(1, peripheral, "string", "table")
|
||||
if type(peripheral) == "string" then -- Peripheral name passed
|
||||
@ -81,7 +158,7 @@ function getType(peripheral)
|
||||
end
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.getType(side) == "modem" and not native.call(side, "isWireless") and
|
||||
if native.hasType(side, "modem") and not native.call(side, "isWireless") and
|
||||
native.call(side, "isPresentRemote", peripheral)
|
||||
then
|
||||
return native.call(side, "getTypeRemote", peripheral)
|
||||
@ -90,10 +167,43 @@ function getType(peripheral)
|
||||
return nil
|
||||
else
|
||||
local mt = getmetatable(peripheral)
|
||||
if not mt or mt.__name ~= "peripheral" or type(mt.type) ~= "string" then
|
||||
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
||||
error("bad argument #1 (table is not a peripheral)", 2)
|
||||
end
|
||||
return mt.type
|
||||
return table.unpack(mt.types)
|
||||
end
|
||||
end
|
||||
|
||||
--[[- Check if a peripheral is of a particular type.
|
||||
|
||||
@tparam string|table peripheral The name of the peripheral or a wrapped peripheral instance.
|
||||
@tparam string peripheral_type The type to check.
|
||||
|
||||
@treturn boolean|nil If a peripheral has a particular type, or `nil` if it is not present.
|
||||
@since 1.99
|
||||
]]
|
||||
function hasType(peripheral, peripheral_type)
|
||||
expect(1, peripheral, "string", "table")
|
||||
expect(2, peripheral_type, "string")
|
||||
if type(peripheral) == "string" then -- Peripheral name passed
|
||||
if native.isPresent(peripheral) then
|
||||
return native.hasType(peripheral, peripheral_type)
|
||||
end
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.hasType(side, "modem") and not native.call(side, "isWireless") and
|
||||
native.call(side, "isPresentRemote", peripheral)
|
||||
then
|
||||
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
else
|
||||
local mt = getmetatable(peripheral)
|
||||
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
||||
error("bad argument #1 (table is not a peripheral)", 2)
|
||||
end
|
||||
return mt.types[peripheral_type] ~= nil
|
||||
end
|
||||
end
|
||||
|
||||
@ -109,7 +219,7 @@ function getMethods(name)
|
||||
end
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.getType(side) == "modem" and not native.call(side, "isWireless") and
|
||||
if native.hasType(side, "modem") and not native.call(side, "isWireless") and
|
||||
native.call(side, "isPresentRemote", name)
|
||||
then
|
||||
return native.call(side, "getMethodsRemote", name)
|
||||
@ -151,7 +261,7 @@ function call(name, method, ...)
|
||||
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.getType(side) == "modem" and not native.call(side, "isWireless") and
|
||||
if native.hasType(side, "modem") and not native.call(side, "isWireless") and
|
||||
native.call(side, "isPresentRemote", name)
|
||||
then
|
||||
return native.call(side, "callRemote", name, method, ...)
|
||||
@ -160,15 +270,16 @@ function call(name, method, ...)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get a table containing functions pointing to the peripheral's methods, which
|
||||
-- can then be called as if using @{peripheral.call}.
|
||||
--- Get a table containing all functions available on a peripheral. These can
|
||||
-- then be called instead of using @{peripheral.call} every time.
|
||||
--
|
||||
-- @tparam string name The name of the peripheral to wrap.
|
||||
-- @treturn table|nil The table containing the peripheral's methods, or `nil` if
|
||||
-- there is no peripheral present with the given name.
|
||||
-- @usage Open the modem on the top of this computer.
|
||||
--
|
||||
-- peripheral.wrap("top").open(1)
|
||||
-- local modem = peripheral.wrap("top")
|
||||
-- modem.open(1)
|
||||
function wrap(name)
|
||||
expect(1, name, "string")
|
||||
|
||||
@ -177,10 +288,14 @@ function wrap(name)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- We store our types array as a list (for getType) and a lookup table (for hasType).
|
||||
local types = { peripheral.getType(name) }
|
||||
for i = 1, #types do types[types[i]] = true end
|
||||
local result = setmetatable({}, {
|
||||
__name = "peripheral",
|
||||
name = name,
|
||||
type = peripheral.getType(name),
|
||||
type = types[1],
|
||||
types = types,
|
||||
})
|
||||
for _, method in ipairs(methods) do
|
||||
result[method] = function(...)
|
||||
@ -222,7 +337,7 @@ function find(ty, filter)
|
||||
|
||||
local results = {}
|
||||
for _, name in ipairs(peripheral.getNames()) do
|
||||
if peripheral.getType(name) == ty then
|
||||
if peripheral.hasType(name, ty) then
|
||||
local wrapped = peripheral.wrap(name)
|
||||
if filter == nil or filter(name, wrapped) then
|
||||
table.insert(results, wrapped)
|
||||
|
@ -1,3 +1,34 @@
|
||||
# New features in CC: Tweaked 1.99.0
|
||||
|
||||
* Pocket computers in their offhand will open without showing a terminal. You can look around and interact with the world, but your keyboard will be forwarded to the computer. (Wojbie, MagGen-hub).
|
||||
* Peripherals can now have multiple types. `peripheral.getType` now returns multiple values, and `peripheral.hasType` checks if a peripheral has a specific type.
|
||||
* Add several missing keys to the `keys` table. (ralphgod3)
|
||||
* Add feature introduction/changed version information to the documentation. (MCJack123)
|
||||
* Increase the file upload limit to 512KiB.
|
||||
* Rednet can now handle computer IDs larger than 65535. (Ale32bit)
|
||||
* Optimise deduplication of rednet messages (MCJack123)
|
||||
* Make `term.blit` colours case insensitive. (Ocawesome101)
|
||||
* Add a new `about` program for easier version identification. (MCJack123)
|
||||
* Optimise peripheral calls in `rednet.run`. (xAnavrins)
|
||||
* Add dimension parameter to `commands.getBlockInfo`.
|
||||
* Add `cc.pretty.pretty_print` helper function (Lupus590).
|
||||
* Add back JEI integration.
|
||||
* Turtle and pocket computer upgrades can now be added and modified with data packs.
|
||||
* Various translation updates (MORIMORI3017, Ale2Bit, mindy15963)
|
||||
|
||||
And several bug fixes:
|
||||
* Fix various computer commands failing when OP level was 4.
|
||||
* Various documentation fixes. (xXTurnerLP, MCJack123)
|
||||
* Fix `textutils.serialize` not serialising infinity and nan values. (Wojbie)
|
||||
* Wired modems now correctly clean up mounts when a peripheral is detached.
|
||||
* Fix incorrect turtle and pocket computer upgrade recipes in the recipe book.
|
||||
* Fix speakers not playing sounds added via resource packs which are not registered in-game.
|
||||
* Fix speaker upgrades sending packets after the server has stopped.
|
||||
* Monitor sizing has been rewritten, hopefully making it more stable.
|
||||
* Peripherals are now invalidated when the computer ticks, rather than when the peripheral changes.
|
||||
* Fix printouts and pocket computers rendering at fullbright when in item frames.
|
||||
* All mod blocks now have an effective tool (pickaxe).
|
||||
|
||||
# New features in CC: Tweaked 1.98.2
|
||||
|
||||
* Add JP translation (MORIMORI0317)
|
||||
|
@ -1,13 +1,32 @@
|
||||
New features in CC: Tweaked 1.98.2
|
||||
New features in CC: Tweaked 1.99.0
|
||||
|
||||
* Add JP translation (MORIMORI0317)
|
||||
* Migrate several recipes to data generators.
|
||||
* Pocket computers in their offhand will open without showing a terminal. You can look around and interact with the world, but your keyboard will be forwarded to the computer. (Wojbie, MagGen-hub).
|
||||
* Peripherals can now have multiple types. `peripheral.getType` now returns multiple values, and `peripheral.hasType` checks if a peripheral has a specific type.
|
||||
* Add several missing keys to the `keys` table. (ralphgod3)
|
||||
* Add feature introduction/changed version information to the documentation. (MCJack123)
|
||||
* Increase the file upload limit to 512KiB.
|
||||
* Rednet can now handle computer IDs larger than 65535. (Ale32bit)
|
||||
* Optimise deduplication of rednet messages (MCJack123)
|
||||
* Make `term.blit` colours case insensitive. (Ocawesome101)
|
||||
* Add a new `about` program for easier version identification. (MCJack123)
|
||||
* Optimise peripheral calls in `rednet.run`. (xAnavrins)
|
||||
* Add dimension parameter to `commands.getBlockInfo`.
|
||||
* Add `cc.pretty.pretty_print` helper function (Lupus590).
|
||||
* Add back JEI integration.
|
||||
* Turtle and pocket computer upgrades can now be added and modified with data packs.
|
||||
* Various translation updates (MORIMORI3017, Ale2Bit, mindy15963)
|
||||
|
||||
Several bug fixes:
|
||||
* Fix volume speaker sounds are played at.
|
||||
* Fix several rendering issues when holding pocket computers and printouts in
|
||||
hand.
|
||||
* Ensure wired modems and cables join the wired network on chunk load.
|
||||
* Fix stack overflow when using wired networks.
|
||||
And several bug fixes:
|
||||
* Fix various computer commands failing when OP level was 4.
|
||||
* Various documentation fixes. (xXTurnerLP, MCJack123)
|
||||
* Fix `textutils.serialize` not serialising infinity and nan values. (Wojbie)
|
||||
* Wired modems now correctly clean up mounts when a peripheral is detached.
|
||||
* Fix incorrect turtle and pocket computer upgrade recipes in the recipe book.
|
||||
* Fix speakers not playing sounds added via resource packs which are not registered in-game.
|
||||
* Fix speaker upgrades sending packets after the server has stopped.
|
||||
* Monitor sizing has been rewritten, hopefully making it more stable.
|
||||
* Peripherals are now invalidated when the computer ticks, rather than when the peripheral changes.
|
||||
* Fix printouts and pocket computers rendering at fullbright when in item frames.
|
||||
* All mod blocks now have an effective tool (pickaxe).
|
||||
|
||||
Type "help changelog" to see the full version history.
|
||||
|
@ -9,8 +9,8 @@
|
||||
-- @usage Load an image from `example.nft` and draw it.
|
||||
--
|
||||
-- local nft = require "cc.image.nft"
|
||||
-- local image = assert(nft.load("example.nft"))
|
||||
-- nft.draw(image)
|
||||
-- local image = assert(nft.load("data/example.nft"))
|
||||
-- nft.draw(image, term.getCursorPos())
|
||||
|
||||
local expect = require "cc.expect".expect
|
||||
|
||||
@ -41,6 +41,7 @@ local function parse(image)
|
||||
end
|
||||
|
||||
line = line + 1
|
||||
foreground, background = "0", "f"
|
||||
else
|
||||
local next = image:find("[\n\30\31]", i) or #image + 1
|
||||
local seg_len = next - i
|
||||
|
@ -19,7 +19,7 @@ The structure of this module is based on [A Prettier Printer][prettier].
|
||||
@usage Print a table to the terminal
|
||||
|
||||
local pretty = require "cc.pretty"
|
||||
pretty.print(pretty.pretty({ 1, 2, 3 }))
|
||||
pretty.pretty_print({ 1, 2, 3 })
|
||||
|
||||
@usage Build a custom document and display it
|
||||
|
||||
@ -463,6 +463,7 @@ end
|
||||
--
|
||||
-- local pretty = require "cc.pretty"
|
||||
-- pretty.print(pretty.pretty({ 1, 2, 3 }))
|
||||
-- @see pretty_print for a shorthand to prettify and print an object.
|
||||
local function pretty(obj, options)
|
||||
expect(2, options, "table", "nil")
|
||||
options = options or {}
|
||||
@ -474,6 +475,33 @@ local function pretty(obj, options)
|
||||
return pretty_impl(obj, actual_options, {})
|
||||
end
|
||||
|
||||
--[[- A shortcut for calling @{pretty} and @{print} together.
|
||||
|
||||
@param obj The object to pretty-print.
|
||||
@tparam[opt] { function_args = boolean, function_source = boolean } options
|
||||
Controls how various properties are displayed.
|
||||
- `function_args`: Show the arguments to a function if known (`false` by default).
|
||||
- `function_source`: Show where the function was defined, instead of
|
||||
`function: xxxxxxxx` (`false` by default).
|
||||
@tparam[opt] number ribbon_frac The maximum fraction of the width that we should write in.
|
||||
|
||||
@usage Display a table on the screen.
|
||||
|
||||
local pretty = require "cc.pretty"
|
||||
pretty.pretty_print({ 1, 2, 3 })
|
||||
|
||||
@see pretty
|
||||
@see print
|
||||
@since 1.99
|
||||
]]
|
||||
local function pretty_print(obj, options, ribbon_frac)
|
||||
expect(2, options, "table", "nil")
|
||||
options = options or {}
|
||||
expect(3, ribbon_frac, "number", "nil")
|
||||
|
||||
return print(pretty(obj, options), ribbon_frac)
|
||||
end
|
||||
|
||||
return {
|
||||
empty = empty,
|
||||
space = space,
|
||||
@ -489,4 +517,6 @@ return {
|
||||
render = render,
|
||||
|
||||
pretty = pretty,
|
||||
|
||||
pretty_print = pretty_print,
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ print("Attached Peripherals:")
|
||||
if #tPeripherals > 0 then
|
||||
for n = 1, #tPeripherals do
|
||||
local sPeripheral = tPeripherals[n]
|
||||
print(sPeripheral .. " (" .. peripheral.getType(sPeripheral) .. ")")
|
||||
print(sPeripheral .. " (" .. table.concat({ peripheral.getType(sPeripheral) }, ", ") .. ")")
|
||||
end
|
||||
else
|
||||
print("None")
|
||||
|
@ -15,6 +15,7 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.ExperimentalTime
|
||||
|
||||
|
||||
|
@ -1,6 +1,13 @@
|
||||
describe("The peripheral library", function()
|
||||
local it_modem = peripheral.getType("top") == "modem" and it or pending
|
||||
|
||||
local multitype_peripheral = setmetatable({}, {
|
||||
__name = "peripheral",
|
||||
name = "top",
|
||||
type = "modem",
|
||||
types = { "modem", "inventory", modem = true, inventory = true },
|
||||
})
|
||||
|
||||
describe("peripheral.isPresent", function()
|
||||
it("validates arguments", function()
|
||||
peripheral.isPresent("")
|
||||
@ -26,6 +33,10 @@ describe("The peripheral library", function()
|
||||
expect.error(peripheral.getType, {}):eq("bad argument #1 (table is not a peripheral)")
|
||||
end)
|
||||
|
||||
it("returns nil when no peripheral is present", function()
|
||||
expect(peripheral.getType("bottom")):eq(nil)
|
||||
end)
|
||||
|
||||
it_modem("can get the type of a peripheral by side", function()
|
||||
expect(peripheral.getType("top")):eq("modem")
|
||||
end)
|
||||
@ -33,6 +44,38 @@ describe("The peripheral library", function()
|
||||
it_modem("can get the type of a wrapped peripheral", function()
|
||||
expect(peripheral.getType(peripheral.wrap("top"))):eq("modem")
|
||||
end)
|
||||
|
||||
it("can return multiple types", function()
|
||||
expect({ peripheral.getType(multitype_peripheral) }):same { "modem", "inventory" }
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("peripheral.hasType", function()
|
||||
it("validates arguments", function()
|
||||
peripheral.getType("")
|
||||
expect.error(peripheral.hasType, nil):eq("bad argument #1 (expected string or table, got nil)")
|
||||
expect.error(peripheral.hasType, {}, ""):eq("bad argument #1 (table is not a peripheral)")
|
||||
expect.error(peripheral.hasType, ""):eq("bad argument #2 (expected string, got nil)")
|
||||
end)
|
||||
|
||||
it("returns nil when no peripherals are present", function()
|
||||
expect(peripheral.hasType("bottom", "modem")):eq(nil)
|
||||
end)
|
||||
|
||||
it_modem("can check type of a peripheral by side", function()
|
||||
expect(peripheral.hasType("top", "modem")):eq(true)
|
||||
expect(peripheral.hasType("top", "not_a_modem")):eq(false)
|
||||
end)
|
||||
|
||||
it_modem("can check the type of a wrapped peripheral (true)", function()
|
||||
expect(peripheral.hasType(peripheral.wrap("top"), "modem")):eq(true)
|
||||
end)
|
||||
|
||||
it("can check the type of a wrapped peripheral (fake)", function()
|
||||
expect(peripheral.hasType(multitype_peripheral, "modem")):eq(true)
|
||||
expect(peripheral.hasType(multitype_peripheral, "inventory")):eq(true)
|
||||
expect(peripheral.hasType(multitype_peripheral, "something else")):eq(false)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("peripheral.getMethods", function()
|
||||
|
21
src/web/copy-cat.d.ts
vendored
21
src/web/copy-cat.d.ts
vendored
@ -1,21 +0,0 @@
|
||||
import { h, Component, render, ComponentChild } from "preact";
|
||||
|
||||
export { h, Component, render };
|
||||
|
||||
export type ComputerAccess = unknown;
|
||||
|
||||
export type MainProps = {
|
||||
hdFont?: boolean | string,
|
||||
persistId?: number,
|
||||
files?: { [filename: string]: string | ArrayBuffer },
|
||||
label?: string,
|
||||
width?: number,
|
||||
height?: number,
|
||||
resolve?: (computer: ComputerAccess) => void,
|
||||
}
|
||||
|
||||
declare class Computer extends Component<MainProps, unknown> {
|
||||
public render(props: MainProps, state: unknown): ComponentChild;
|
||||
}
|
||||
|
||||
export { Computer };
|
@ -4,15 +4,15 @@ import type { ComponentChild } from "preact";
|
||||
import settingsFile from "./mount/.settings";
|
||||
import startupFile from "./mount/startup.lua";
|
||||
import exprTemplate from "./mount/expr_template.lua";
|
||||
import exampleImage from "./mount/example.nfp";
|
||||
import exampleNfp from "./mount/example.nfp";
|
||||
import exampleNft from "./mount/example.nft";
|
||||
|
||||
const defaultFiles: { [filename: string]: string } = {
|
||||
".settings": settingsFile,
|
||||
"startup.lua": startupFile,
|
||||
|
||||
// TODO: Ideally this'd be in data/image.nfp or something, but copy-cat's
|
||||
// dir bootstrapping doesn't cope with that right now.
|
||||
"test-image.nfp": exampleImage
|
||||
"data/example.nfp": exampleNfp,
|
||||
"data/example.nft": exampleNft,
|
||||
};
|
||||
|
||||
const clamp = (value: number, min: number, max: number): number => {
|
||||
|
15
src/web/mount/example.nft
Normal file
15
src/web/mount/example.nft
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
4
|
||||
4
|
||||
4 4
|
||||
0 4 4>0 ls 4
|
||||
0 4 drom/ 4 0
|
||||
0 4 startup.lua 4
|
||||
0 4 4> 0hello 4
|
||||
0 4 aHello World! 0 4
|
||||
0 4 4
|
||||
0 4 4
|
||||
0 4 4
|
||||
0 4
|
||||
0 4 4
|
||||
0 4
|
45
src/web/typings.ts
Normal file
45
src/web/typings.ts
Normal file
@ -0,0 +1,45 @@
|
||||
declare module "*.lua" {
|
||||
const contents: string;
|
||||
export default contents;
|
||||
}
|
||||
|
||||
declare module "*.nfp" {
|
||||
const contents: string;
|
||||
export default contents;
|
||||
}
|
||||
|
||||
declare module "*.nft" {
|
||||
const contents: string;
|
||||
export default contents;
|
||||
}
|
||||
|
||||
|
||||
declare module "*.settings" {
|
||||
const contents: string;
|
||||
export default contents;
|
||||
}
|
||||
|
||||
|
||||
declare module "copycat/embed" {
|
||||
import { h, Component, render, ComponentChild } from "preact";
|
||||
|
||||
export { h, Component, render };
|
||||
|
||||
export type ComputerAccess = unknown;
|
||||
|
||||
export type MainProps = {
|
||||
hdFont?: boolean | string,
|
||||
persistId?: number,
|
||||
files?: { [filename: string]: string | ArrayBuffer },
|
||||
label?: string,
|
||||
width?: number,
|
||||
height?: number,
|
||||
resolve?: (computer: ComputerAccess) => void,
|
||||
}
|
||||
|
||||
class Computer extends Component<MainProps, unknown> {
|
||||
public render(props: MainProps, state: unknown): ComponentChild;
|
||||
}
|
||||
|
||||
export { Computer };
|
||||
}
|
@ -22,11 +22,6 @@
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"importsNotUsedAsValues": "error",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"paths": {
|
||||
"copycat/embed": [
|
||||
"src/web/copy-cat.d.ts"
|
||||
],
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/web",
|
||||
|
Loading…
Reference in New Issue
Block a user