Compare commits
161 Commits
v1.18-1.99
...
v1.19-1.10
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a913232e62 | ||
![]() |
557765d8f0 | ||
![]() |
1e044aed68 | ||
![]() |
5382d34d29 | ||
![]() |
cbbb34cdd4 | ||
![]() |
8f7719a8dc | ||
![]() |
ca58e39707 | ||
![]() |
0aac966239 | ||
![]() |
0e1e8dfa8c | ||
![]() |
a1cbc1d803 | ||
![]() |
0b6dc25607 | ||
![]() |
b91809bfc7 | ||
![]() |
178126725e | ||
![]() |
cd76425877 | ||
![]() |
4411756b06 | ||
![]() |
1fd57a874f | ||
![]() |
3f0704624e | ||
![]() |
3b6cd783cb | ||
![]() |
a07bba4ece | ||
![]() |
ab22726883 | ||
![]() |
2efad38f53 | ||
![]() |
83a1af6526 | ||
![]() |
8b89d88d04 | ||
![]() |
36635662f1 | ||
![]() |
bbc0afa111 | ||
![]() |
34dc915d57 | ||
![]() |
24ed0ca723 | ||
![]() |
5052718428 | ||
![]() |
431e4c9419 | ||
![]() |
2639b84eb2 | ||
![]() |
d631111610 | ||
![]() |
c981c75b7c | ||
![]() |
f05a539443 | ||
![]() |
d8a7ab540a | ||
![]() |
a7536ea4fa | ||
![]() |
d9e75d7c47 | ||
![]() |
78334c4cb1 | ||
![]() |
f5f0c7990a | ||
![]() |
87a1c1a525 | ||
![]() |
be45b718b3 | ||
![]() |
ad2d1d6a05 | ||
![]() |
65a7370db1 | ||
![]() |
03b0244084 | ||
![]() |
6322e72110 | ||
![]() |
7ad6132494 | ||
![]() |
e2189535b8 | ||
![]() |
79467499e6 | ||
![]() |
074793090d | ||
![]() |
cbbab26bf3 | ||
![]() |
9cb7091ce7 | ||
![]() |
e909e11e05 | ||
![]() |
6239dbe9ca | ||
![]() |
49601f0b7c | ||
![]() |
caa412b7d2 | ||
![]() |
9cb7a5bec7 | ||
![]() |
118b89ea41 | ||
![]() |
f2474bbfa2 | ||
![]() |
159f90896e | ||
![]() |
f108ba93af | ||
![]() |
2a4f75ba15 | ||
![]() |
ad228e94a3 | ||
![]() |
42b98bce28 | ||
![]() |
59e3608d2a | ||
![]() |
fccca22d3f | ||
![]() |
4bfdb65989 | ||
![]() |
22e8b9b587 | ||
![]() |
77a00b14ae | ||
![]() |
78aa757549 | ||
![]() |
1196568a7c | ||
![]() |
48c4f397f9 | ||
![]() |
8871f40ced | ||
![]() |
aa62c1f206 | ||
![]() |
fd32b06d6f | ||
![]() |
739d6813c0 | ||
![]() |
daf81b897a | ||
![]() |
e865d96f7b | ||
![]() |
79b1872cab | ||
![]() |
41fa95bce4 | ||
![]() |
2a92794da3 | ||
![]() |
b3e009cca5 | ||
![]() |
ba7598c689 | ||
![]() |
70c5cbafec | ||
![]() |
2c64186965 | ||
![]() |
7731759c77 | ||
![]() |
e6339b2847 | ||
![]() |
31ba17d085 | ||
![]() |
6353e8d930 | ||
![]() |
78cce4981a | ||
![]() |
97c953a9be | ||
![]() |
52df7cb8a4 | ||
![]() |
6735cfd12e | ||
![]() |
bcc7dd6991 | ||
![]() |
f994696161 | ||
![]() |
4a4e8bb4b6 | ||
![]() |
bd36185662 | ||
![]() |
045c4fc88c | ||
![]() |
e0fcc425c6 | ||
![]() |
e01895d719 | ||
![]() |
87b38f4249 | ||
![]() |
60d1d1bb18 | ||
![]() |
cdf8b77ffd | ||
![]() |
e2ce52fe81 | ||
![]() |
9edce36efd | ||
![]() |
e05588c662 | ||
![]() |
9cf70b10ef | ||
![]() |
9ac8f3aeea | ||
![]() |
e191b08eb5 | ||
![]() |
a1221b99e1 | ||
![]() |
85bced6b1d | ||
![]() |
fc4569e0cc | ||
![]() |
e7f08313d9 | ||
![]() |
79366bf2f5 | ||
![]() |
413fa5bcc8 | ||
![]() |
79fc8237b6 | ||
![]() |
9d50d6414c | ||
![]() |
16df86224b | ||
![]() |
a9519f68a1 | ||
![]() |
f1a08a3362 | ||
![]() |
802949d888 | ||
![]() |
2b901f2d5e | ||
![]() |
62f2cd5cb2 | ||
![]() |
e558b31b2b | ||
![]() |
afd82fbf1f | ||
![]() |
901d8d4c3b | ||
![]() |
f794ce42ab | ||
![]() |
f470478a0f | ||
![]() |
aa009df740 | ||
![]() |
0c6c0badde | ||
![]() |
bed2e0b658 | ||
![]() |
0f9ddac83c | ||
![]() |
932b77d7ee | ||
![]() |
5eedea1bbb | ||
![]() |
114261944a | ||
![]() |
4d10639efb | ||
![]() |
aa36b49c50 | ||
![]() |
8a1067940d | ||
![]() |
2562642664 | ||
![]() |
632db1cfa5 | ||
![]() |
aa0d544bba | ||
![]() |
2f6ad00764 | ||
![]() |
05da4dd362 | ||
![]() |
0477b2742c | ||
![]() |
fe3c42ce22 | ||
![]() |
f6fcba7a39 | ||
![]() |
82a7edee12 | ||
![]() |
b048b6666d | ||
![]() |
e16f66e128 | ||
![]() |
1cfad31a0d | ||
![]() |
7c373c6e06 | ||
![]() |
6196aae488 | ||
![]() |
92a0ef2b75 | ||
![]() |
57c5d19f95 | ||
![]() |
1f6e0f287d | ||
![]() |
0e4b7a5a75 | ||
![]() |
47ad7a35dc | ||
![]() |
3eab2a9b57 | ||
![]() |
c4024a4c4c | ||
![]() |
f5fb82cd7d | ||
![]() |
e18ba8a2c2 | ||
![]() |
422bfdb60d | ||
![]() |
1851ed31cd |
3
.gitattributes
vendored
@@ -1,5 +1,5 @@
|
||||
# Ignore changes in generated files
|
||||
src/generated/resources/data/** linguist-generated
|
||||
src/generated/** linguist-generated
|
||||
src/testMod/server-files/structures linguist-generated
|
||||
|
||||
* text=auto
|
||||
@@ -13,3 +13,4 @@ src/testMod/server-files/structures linguist-generated
|
||||
|
||||
*.png binary
|
||||
*.jar binary
|
||||
*.dfpwm binary
|
||||
|
2
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -8,9 +8,9 @@ body:
|
||||
label: Minecraft Version
|
||||
description: What version of Minecraft are you using?
|
||||
options:
|
||||
- 1.15.x
|
||||
- 1.16.x
|
||||
- 1.17.x
|
||||
- 1.18.x
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
|
2
.github/workflows/make-doc.sh
vendored
@@ -12,7 +12,7 @@ chmod 600 "$HOME/.ssh/key"
|
||||
|
||||
# And upload
|
||||
rsync -avc -e "ssh -i $HOME/.ssh/key -o StrictHostKeyChecking=no -p $SSH_PORT" \
|
||||
"$GITHUB_WORKSPACE/build/docs/lua/" \
|
||||
"$GITHUB_WORKSPACE/build/docs/site/" \
|
||||
"$SSH_USER@$SSH_HOST:/$DEST"
|
||||
rsync -avc -e "ssh -i $HOME/.ssh/key -o StrictHostKeyChecking=no -p $SSH_PORT" \
|
||||
"$GITHUB_WORKSPACE/build/docs/javadoc/" \
|
||||
|
@@ -65,7 +65,7 @@ Gradle should be your entrypoint to building most documentation. There's two tas
|
||||
|
||||
- `./gradlew luaJavadoc` - Generate documentation stubs for Java methods.
|
||||
- `./gradlew docWebsite` - Generate the whole website (including Javascript pages). The resulting HTML is stored at
|
||||
`./build/docs/lua/`.
|
||||
`./build/docs/site/`.
|
||||
|
||||
#### Writing documentation
|
||||
illuaminate's documentation system is not currently documented (somewhat ironic), but is _largely_ the same as
|
||||
|
205
build.gradle
@@ -6,6 +6,7 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:5.1.+'
|
||||
classpath "org.spongepowered:mixingradle:0.7.+"
|
||||
classpath 'org.parchmentmc:librarian:1.+'
|
||||
}
|
||||
}
|
||||
@@ -22,6 +23,7 @@ plugins {
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
apply plugin: "org.spongepowered.mixin"
|
||||
apply plugin: 'org.parchmentmc.librarian.forgegradle'
|
||||
|
||||
version = mod_version
|
||||
@@ -46,10 +48,6 @@ tasks.withType(JavaExec).configureEach {
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java {
|
||||
exclude 'dan200/computercraft/shared/integration/jei/**'
|
||||
exclude 'dan200/computercraft/shared/integration/morered/**'
|
||||
}
|
||||
main.resources {
|
||||
srcDir 'src/generated/resources'
|
||||
}
|
||||
@@ -72,6 +70,8 @@ minecraft {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
|
||||
arg "-mixin.config=computercraft.mixins.json"
|
||||
}
|
||||
|
||||
client {
|
||||
@@ -105,9 +105,8 @@ minecraft {
|
||||
}
|
||||
}
|
||||
|
||||
testServer {
|
||||
gameTestServer {
|
||||
workingDirectory project.file('test-files/server')
|
||||
parent runs.server
|
||||
|
||||
mods {
|
||||
cctest {
|
||||
@@ -129,6 +128,11 @@ minecraft {
|
||||
accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
|
||||
}
|
||||
|
||||
mixin {
|
||||
add sourceSets.main, 'computercraft.mixins.refmap.json'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
@@ -152,11 +156,13 @@ dependencies {
|
||||
checkstyle "com.puppycrawl.tools:checkstyle:8.45"
|
||||
|
||||
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
|
||||
annotationProcessor 'org.spongepowered:mixin:0.8.4:processor'
|
||||
|
||||
// compileOnly fg.deobf("mezz.jei:jei-1.17.1:8.0.0.14:api")
|
||||
// runtimeOnly fg.deobf("mezz.jei:jei-1.17.1:8.0.0.14")
|
||||
compileOnly fg.deobf("mezz.jei:jei-1.18.2:9.4.1.116:api")
|
||||
// runtimeOnly fg.deobf("mezz.jei:jei-1.18.2:9.4.1.116")
|
||||
|
||||
shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT'
|
||||
shade 'org.squiddev:Cobalt:0.5.5'
|
||||
shade 'io.netty:netty-codec-http:4.1.76.Final'
|
||||
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0'
|
||||
@@ -170,7 +176,7 @@ dependencies {
|
||||
exclude group: "org.jetbrains", module: "annotations"
|
||||
}
|
||||
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.2'
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.6'
|
||||
}
|
||||
|
||||
// Compile tasks
|
||||
@@ -210,9 +216,13 @@ jar {
|
||||
"Implementation-Version" : "${mod_version}",
|
||||
"Implementation-Vendor" : "SquidDev",
|
||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
,
|
||||
"MixinConfigs" : "computercraft.mixins.json",
|
||||
])
|
||||
}
|
||||
|
||||
duplicatesStrategy(DuplicatesStrategy.WARN)
|
||||
|
||||
from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
|
||||
@@ -230,9 +240,32 @@ processResources {
|
||||
try {
|
||||
hash = ["git", "-C", projectDir, "rev-parse", "HEAD"].execute().text.trim()
|
||||
|
||||
def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
|
||||
["git", "-C", projectDir, "log", "--format=tformat:%an%n%cn"].execute().text.split('\n').each {
|
||||
if (!blacklist.contains(it)) contributors.add(it)
|
||||
def blacklist = ['GitHub', 'Daniel Ratcliffe', 'Weblate']
|
||||
|
||||
// Extract all authors, commiters and co-authors from the git log.
|
||||
def authors = ["git", "-C", projectDir, "log", "--format=tformat:%an <%ae>%n%cn <%ce>%n%(trailers:key=Co-authored-by,valueonly)"]
|
||||
.execute().text.readLines().unique()
|
||||
|
||||
// We now pass this through git's mailmap to de-duplicate some authors.
|
||||
def remapAuthors = ["git", "check-mailmap", "--stdin"].execute()
|
||||
remapAuthors.withWriter { stdin ->
|
||||
if (stdin !instanceof BufferedWriter) stdin = new BufferedWriter(stdin)
|
||||
|
||||
authors.forEach {
|
||||
if (it == "") return
|
||||
if (!it.endsWith(">")) it += ">" // Some commits have broken Co-Authored-By lines!
|
||||
stdin.writeLine(it)
|
||||
}
|
||||
stdin.close()
|
||||
}
|
||||
|
||||
// And finally extract out the actual name.
|
||||
def emailRegex = ~/^([^<]+) <.+>$/
|
||||
remapAuthors.text.readLines().forEach {
|
||||
def matcher = it =~ emailRegex
|
||||
matcher.find()
|
||||
def name = matcher.group(1)
|
||||
if (!blacklist.contains(name)) contributors.add(name)
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace()
|
||||
@@ -282,37 +315,51 @@ task rollup(type: Exec) {
|
||||
commandLine mkCommand('"node_modules/.bin/rollup" --config rollup.config.js')
|
||||
}
|
||||
|
||||
task minifyWeb(type: Exec, dependsOn: rollup) {
|
||||
task illuaminateDocs(type: Exec, dependsOn: [rollup, luaJavadoc]) {
|
||||
group = "build"
|
||||
description = "Bundles JS into rollup"
|
||||
|
||||
inputs.file("$buildDir/rollup/index.js").withPropertyName("sources")
|
||||
inputs.file("package-lock.json").withPropertyName("package-lock.json")
|
||||
outputs.file("$buildDir/rollup/index.min.js").withPropertyName("output")
|
||||
|
||||
commandLine mkCommand('"node_modules/.bin/terser"' + " -o '$buildDir/rollup/index.min.js' '$buildDir/rollup/index.js'")
|
||||
}
|
||||
|
||||
task illuaminateDocs(type: Exec, dependsOn: [minifyWeb, luaJavadoc]) {
|
||||
group = "build"
|
||||
description = "Bundles JS into rollup"
|
||||
description = "Generates docs using Illuaminate"
|
||||
|
||||
inputs.files(fileTree("doc")).withPropertyName("docs")
|
||||
inputs.files(fileTree("src/main/resources/data/computercraft/lua/rom")).withPropertyName("lua rom")
|
||||
inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
|
||||
inputs.dir("$buildDir/docs/luaJavadoc")
|
||||
inputs.file("$buildDir/rollup/index.min.js").withPropertyName("scripts")
|
||||
inputs.file("$buildDir/rollup/index.js").withPropertyName("scripts")
|
||||
inputs.file("src/web/styles.css").withPropertyName("styles")
|
||||
outputs.dir("$buildDir/docs/lua")
|
||||
|
||||
commandLine mkCommand('"bin/illuaminate" doc-gen')
|
||||
}
|
||||
|
||||
task docWebsite(type: Copy, dependsOn: [illuaminateDocs]) {
|
||||
from 'doc'
|
||||
include 'logo.png'
|
||||
include 'images/**'
|
||||
into "${project.docsDir}/lua"
|
||||
task jsxDocs(type: Exec, dependsOn: [illuaminateDocs]) {
|
||||
group = "build"
|
||||
description = "Post-processes documentation to statically render some dynamic content."
|
||||
|
||||
inputs.files(fileTree("src/web")).withPropertyName("sources")
|
||||
inputs.file("src/generated/export/index.json").withPropertyName("export")
|
||||
inputs.file("package-lock.json").withPropertyName("package-lock.json")
|
||||
inputs.file("tsconfig.json").withPropertyName("Typescript config")
|
||||
inputs.files(fileTree("$buildDir/docs/lua"))
|
||||
outputs.dir("$buildDir/docs/site")
|
||||
|
||||
commandLine mkCommand('"node_modules/.bin/ts-node" --esm src/web/transform.tsx')
|
||||
}
|
||||
|
||||
task docWebsite(type: Copy, dependsOn: [jsxDocs]) {
|
||||
from('doc') {
|
||||
include 'logo.png'
|
||||
include 'images/**'
|
||||
}
|
||||
from("$buildDir/rollup") {
|
||||
exclude 'index.js'
|
||||
}
|
||||
from("$buildDir/docs/lua") {
|
||||
exclude '**/*.html'
|
||||
}
|
||||
from("src/generated/export/items") {
|
||||
into("images/items")
|
||||
}
|
||||
|
||||
into "${project.docsDir}/site"
|
||||
}
|
||||
|
||||
// Check tasks
|
||||
@@ -373,69 +420,49 @@ task licenseFormatAPI(type: LicenseFormat)
|
||||
}
|
||||
}
|
||||
|
||||
task setupServer(type: Copy) {
|
||||
group "test server"
|
||||
description "Sets up the environment for the test server."
|
||||
tasks.register("testServer", JavaExec.class).configure {
|
||||
it.group('In-game tests')
|
||||
it.description("Runs tests on a temporary Minecraft instance.")
|
||||
it.dependsOn("prepareRunGameTestServer", "cleanTestServer", 'compileTestModJava')
|
||||
|
||||
from("src/testMod/server-files") {
|
||||
include "eula.txt"
|
||||
include "server.properties"
|
||||
}
|
||||
into "test-files/server"
|
||||
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
||||
// isn't created until the task is configured (which is no good for us).
|
||||
JavaExec exec = tasks.getByName("runGameTestServer")
|
||||
exec.copyTo(it)
|
||||
it.setClasspath(exec.getClasspath())
|
||||
it.mainClass = exec.mainClass
|
||||
it.setArgs(exec.getArgs())
|
||||
|
||||
// Jacoco and modlauncher don't play well together as the classes loaded in-game don't
|
||||
// match up with those written to disk. We get Jacoco to dump all classes to disk, and
|
||||
// use that when generating the report.
|
||||
def coverageOut = new File(buildDir, "jacocoClassDump/testServer")
|
||||
jacoco.applyTo(it)
|
||||
it.jacoco.setIncludes(["dan200.computercraft.*"])
|
||||
it.jacoco.setClassDumpDir(coverageOut)
|
||||
it.outputs.dir(coverageOut)
|
||||
// Older versions of modlauncher don't include a protection domain (and thus no code
|
||||
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
||||
it.jacoco.setIncludeNoLocationClasses(true)
|
||||
}
|
||||
|
||||
["Client", "Server"].forEach { name ->
|
||||
tasks.register("test$name", JavaExec.class).configure {
|
||||
it.group('In-game tests')
|
||||
it.description("Runs tests on a temporary Minecraft instance.")
|
||||
it.dependsOn(setupServer, "prepareRunTest$name", "cleanTest$name", 'compileTestModJava')
|
||||
tasks.register("jacocoTestServerReport", JacocoReport.class).configure {
|
||||
it.group('In-game')
|
||||
it.description("Generate coverage reports for testServer")
|
||||
it.dependsOn("testServer")
|
||||
|
||||
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
||||
// isn't created until the task is configured (which is no good for us).
|
||||
JavaExec exec = tasks.getByName("runTest$name")
|
||||
exec.copyTo(it)
|
||||
it.setClasspath(exec.getClasspath())
|
||||
it.mainClass = exec.mainClass
|
||||
it.setArgs(exec.getArgs())
|
||||
it.executionData(new File(buildDir, "jacoco/testServer.exec"))
|
||||
it.sourceDirectories.from(sourceSets.main.allJava.srcDirs)
|
||||
it.classDirectories.from(new File(buildDir, "jacocoClassDump/testServer"))
|
||||
|
||||
it.systemProperty('forge.logging.console.level', 'info')
|
||||
it.systemProperty('cctest.run', 'true')
|
||||
|
||||
// Jacoco and modlauncher don't play well together as the classes loaded in-game don't
|
||||
// match up with those written to disk. We get Jacoco to dump all classes to disk, and
|
||||
// use that when generating the report.
|
||||
def coverageOut = new File(buildDir, "jacocoClassDump/test$name")
|
||||
jacoco.applyTo(it)
|
||||
it.jacoco.setIncludes(["dan200.computercraft.*"])
|
||||
it.jacoco.setClassDumpDir(coverageOut)
|
||||
it.outputs.dir(coverageOut)
|
||||
// Older versions of modlauncher don't include a protection domain (and thus no code
|
||||
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
||||
it.jacoco.setIncludeNoLocationClasses(true)
|
||||
}
|
||||
|
||||
tasks.register("jacocoTest${name}Report", JacocoReport.class).configure {
|
||||
it.group('In-game')
|
||||
it.description("Generate coverage reports for test$name")
|
||||
it.dependsOn("test$name")
|
||||
|
||||
it.executionData(new File(buildDir, "jacoco/test${name}.exec"))
|
||||
it.sourceDirectories.from(sourceSets.main.allJava.srcDirs)
|
||||
it.classDirectories.from(new File(buildDir, "jacocoClassDump/test$name"))
|
||||
|
||||
it.reports {
|
||||
xml.enabled true
|
||||
html.enabled true
|
||||
}
|
||||
}
|
||||
|
||||
if (name != "Client" || project.findProperty('cc.tweaked.clientTests') == 'true') {
|
||||
// Don't run client tests unless explicitly opted into them. They're a bit of a faff
|
||||
// to run and pretty flakey.
|
||||
check.dependsOn("jacocoTest${name}Report")
|
||||
it.reports {
|
||||
xml.enabled true
|
||||
html.enabled true
|
||||
}
|
||||
}
|
||||
|
||||
check.dependsOn("jacocoTestServerReport")
|
||||
|
||||
|
||||
// Upload tasks
|
||||
|
||||
@@ -479,7 +506,7 @@ task checkRelease {
|
||||
}
|
||||
check.dependsOn checkRelease
|
||||
|
||||
def isStable = false
|
||||
def isStable = true
|
||||
|
||||
curseforge {
|
||||
apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
|
||||
@@ -584,7 +611,7 @@ githubRelease {
|
||||
.takeWhile { it != 'Type "help changelog" to see the full version history.' }
|
||||
.join("\n").trim()
|
||||
}))
|
||||
prerelease isStable
|
||||
prerelease !isStable
|
||||
}
|
||||
|
||||
def uploadTasks = ["publish", "curseforge", "publishModrinth", "githubRelease"]
|
||||
|
@@ -83,7 +83,9 @@
|
||||
<module name="JavadocBlockTagLocation" />
|
||||
<module name="JavadocMethod"/>
|
||||
<module name="JavadocType"/>
|
||||
<module name="JavadocStyle" />
|
||||
<module name="JavadocStyle">
|
||||
<property name="checkHtml" value="false" />
|
||||
</module>
|
||||
<module name="NonEmptyAtclauseDescription" />
|
||||
<module name="SingleLineJavadoc" />
|
||||
<module name="SummaryJavadocCheck"/>
|
||||
|
@@ -51,5 +51,6 @@ exclude: |
|
||||
src/generated|
|
||||
src/test/resources/test-rom/data/json-parsing/|
|
||||
src/testMod/server-files/|
|
||||
config/idea/
|
||||
config/idea/|
|
||||
.*\.dfpwm
|
||||
)
|
||||
|
@@ -2,7 +2,7 @@
|
||||
module: [kind=event] modem_message
|
||||
---
|
||||
|
||||
The @{modem_message} event is fired when a message is received on an open channel on any modem.
|
||||
The @{modem_message} event is fired when a message is received on an open channel on any @{modem}.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
@@ -10,11 +10,15 @@ The @{modem_message} event is fired when a message is received on an open channe
|
||||
3. @{number}: The channel that the message was sent on.
|
||||
4. @{number}: The reply channel set by the sender.
|
||||
5. @{any}: The message as sent by the sender.
|
||||
6. @{number}: The distance between the sender and the receiver, in blocks (decimal).
|
||||
6. @{number}: The distance between the sender and the receiver, in blocks.
|
||||
|
||||
## Example
|
||||
Prints a message when one is sent:
|
||||
Wraps a @{modem} peripheral, opens channel 0 for listening, and prints all received messages.
|
||||
|
||||
```lua
|
||||
local modem = peripheral.find("modem") or error("No modem attached", 0)
|
||||
modem.open(0)
|
||||
|
||||
while true do
|
||||
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
||||
print(("Message received on side %s on channel %d (reply to %d) from %f blocks away with message %s"):format(side, channel, replyChannel, distance, tostring(message)))
|
||||
|
@@ -15,13 +15,11 @@ advanced turtles and pocket computers).
|
||||
Several mouse events (@{mouse_click}, @{mouse_up}, @{mouse_scroll}) contain a "mouse button" code. This takes a
|
||||
numerical value depending on which button on your mouse was last pressed when this event occurred.
|
||||
|
||||
<table class="pretty-table">
|
||||
<!-- Our markdown parser doesn't work on tables!? Guess I'll have to roll my own soonish :/. -->
|
||||
<tr><th>Button code</th><th>Mouse button</th></tr>
|
||||
<tr><td align="right">1</td><td>Left button</td></tr>
|
||||
<tr><td align="right">2</td><td>Middle button</td></tr>
|
||||
<tr><td align="right">3</td><td>Right button</td></tr>
|
||||
</table>
|
||||
| Button Code | Mouse Button |
|
||||
|------------:|---------------|
|
||||
| 1 | Left button |
|
||||
| 2 | Right button |
|
||||
| 3 | Middle button |
|
||||
|
||||
## Example
|
||||
Print the button and the coordinates whenever the mouse is clicked.
|
||||
|
27
doc/events/speaker_audio_empty.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
module: [kind=event] speaker_audio_empty
|
||||
see: speaker.playAudio To play audio using the speaker
|
||||
---
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The name of the speaker which is available to play more audio.
|
||||
|
||||
|
||||
## Example
|
||||
This uses @{io.lines} to read audio data in blocks of 16KiB from "example_song.dfpwm", and then attempts to play it
|
||||
using @{speaker.playAudio}. If the speaker's buffer is full, it waits for an event and tries again.
|
||||
|
||||
```lua {data-peripheral=speaker}
|
||||
local dfpwm = require("cc.audio.dfpwm")
|
||||
local speaker = peripheral.find("speaker")
|
||||
|
||||
local decoder = dfpwm.make_decoder()
|
||||
for chunk in io.lines("data/example.dfpwm", 16 * 1024) do
|
||||
local buffer = decoder(chunk)
|
||||
|
||||
while not speaker.playAudio(buffer) do
|
||||
os.pullEvent("speaker_audio_empty")
|
||||
end
|
||||
end
|
||||
```
|
@@ -2,7 +2,12 @@
|
||||
module: [kind=event] term_resize
|
||||
---
|
||||
|
||||
The @{term_resize} event is fired when the main terminal is resized, mainly when a new tab is opened or closed in @{multishell}.
|
||||
The @{term_resize} event is fired when the main terminal is resized. For instance:
|
||||
- When a the tab bar is shown or hidden in @{multishell}.
|
||||
- When the terminal is redirected to a monitor via the "monitor" program and the monitor is resized.
|
||||
|
||||
When this event fires, some parts of the terminal may have been moved or deleted. Simple terminal programs (those
|
||||
not using @{term.setCursorPos}) can ignore this event, but more complex GUI programs should redraw the entire screen.
|
||||
|
||||
## Example
|
||||
Prints :
|
||||
|
99
doc/guides/local_ips.md
Normal file
@@ -0,0 +1,99 @@
|
||||
---
|
||||
module: [kind=guide] local_ips
|
||||
---
|
||||
|
||||
# Allowing access to local IPs
|
||||
By default, ComputerCraft blocks access to local IP addresses for security. This means you can't normally access any
|
||||
HTTP server running on your computer. However, this may be useful for testing programs without having a remote
|
||||
server. You can unblock these IPs in the ComputerCraft config.
|
||||
|
||||
- [Minecraft 1.13 and later, CC:T 1.87.0 and later](#cc-1.87.0)
|
||||
- [Minecraft 1.13 and later, CC:T 1.86.2 and earlier](#cc-1.86.2)
|
||||
- [Minecraft 1.12.2 and earlier](#mc-1.12)
|
||||
|
||||
## Minecraft 1.13 and later, CC:T 1.87.0 and later {#cc-1.87.0}
|
||||
The configuration file can be located at `serverconfig/computercraft-server.toml` inside the world folder on either
|
||||
single-player or multiplayer. Look for lines that look like this:
|
||||
|
||||
```toml
|
||||
#A list of rules which control behaviour of the "http" API for specific domains or IPs.
|
||||
#Each rule is an item with a 'host' to match against, and a series of properties. The host may be a domain name ("pastebin.com"),
|
||||
#wildcard ("*.pastebin.com") or CIDR notation ("127.0.0.0/8"). If no rules, the domain is blocked.
|
||||
[[http.rules]]
|
||||
host = "$private"
|
||||
action = "deny"
|
||||
```
|
||||
|
||||
On 1.95.0 and later, this will be a single entry with `host = "$private"`. On earlier versions, this will be a number of
|
||||
`[[http.rules]]` with various IP addresses. You will want to remove all of the `[[http.rules]]` entires that have
|
||||
`action = "deny"`. Then save the file and relaunch Minecraft (Server).
|
||||
|
||||
Here's what it should look like after removing:
|
||||
|
||||
```toml
|
||||
#A list of rules which control behaviour of the "http" API for specific domains or IPs.
|
||||
#Each rule is an item with a 'host' to match against, and a series of properties. The host may be a domain name ("pastebin.com"),
|
||||
#wildcard ("*.pastebin.com") or CIDR notation ("127.0.0.0/8"). If no rules, the domain is blocked.
|
||||
[[http.rules]]
|
||||
#The maximum size (in bytes) that a computer can send or receive in one websocket packet.
|
||||
max_websocket_message = 131072
|
||||
host = "*"
|
||||
#The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text.
|
||||
max_upload = 4194304
|
||||
action = "allow"
|
||||
#The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client.
|
||||
max_download = 16777216
|
||||
#The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited.
|
||||
timeout = 30000
|
||||
```
|
||||
|
||||
## Minecraft 1.13 and later, CC:T 1.86.2 and earlier {#cc-1.86.2}
|
||||
The configuration file for singleplayer is at `.minecraft/config/computercraft-common.toml`. Look for lines that look
|
||||
like this:
|
||||
|
||||
```toml
|
||||
#A list of wildcards for domains or IP ranges that cannot be accessed through the "http" API on Computers.
|
||||
#If this is empty then all whitelisted domains will be accessible. Example: "*.github.com" will block access to all subdomains of github.com.
|
||||
#You can use domain names ("pastebin.com"), wilcards ("*.pastebin.com") or CIDR notation ("127.0.0.0/8").
|
||||
blacklist = ["127.0.0.0/8", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fd00::/8"]
|
||||
```
|
||||
|
||||
Remove everything inside the array, leaving the last line as `blacklist = []`. Then save the file and relaunch Minecraft.
|
||||
|
||||
Here's what it should look like after removing:
|
||||
|
||||
```toml
|
||||
#A list of wildcards for domains or IP ranges that cannot be accessed through the "http" API on Computers.
|
||||
#If this is empty then all whitelisted domains will be accessible. Example: "*.github.com" will block access to all subdomains of github.com.
|
||||
#You can use domain names ("pastebin.com"), wilcards ("*.pastebin.com") or CIDR notation ("127.0.0.0/8").
|
||||
blacklist = []
|
||||
```
|
||||
|
||||
## Minecraft 1.12.2 and earlier {#mc-1.12}
|
||||
On singleplayer, the configuration file is located at `.minecraft\config\ComputerCraft.cfg`. On multiplayer, the
|
||||
configuration file is located at `<server folder>\config\ComputerCraft.cfg`. Look for lines that look like this:
|
||||
|
||||
```ini
|
||||
# A list of wildcards for domains or IP ranges that cannot be accessed through the "http" API on Computers.
|
||||
# If this is empty then all explicitly allowed domains will be accessible. Example: "*.github.com" will block access to all subdomains of github.com.
|
||||
# You can use domain names ("pastebin.com"), wildcards ("*.pastebin.com") or CIDR notation ("127.0.0.0/8").
|
||||
S:blocked_domains <
|
||||
127.0.0.0/8
|
||||
10.0.0.0/8
|
||||
172.16.0.0/12
|
||||
192.168.0.0/16
|
||||
fd00::/8
|
||||
>
|
||||
```
|
||||
|
||||
Delete everything between the `<>`, leaving the last line as `S:blocked_domains = <>`. Then save the file and relaunch
|
||||
Minecraft (Server).
|
||||
|
||||
Here's what it should look like after removing:
|
||||
|
||||
```ini
|
||||
# A list of wildcards for domains or IP ranges that cannot be accessed through the "http" API on Computers.
|
||||
# If this is empty then all explicitly allowed domains will be accessible. Example: "*.github.com" will block access to all subdomains of github.com.
|
||||
# You can use domain names ("pastebin.com"), wildcards ("*.pastebin.com") or CIDR notation ("127.0.0.0/8").
|
||||
S:blocked_domains <>
|
||||
```
|
205
doc/guides/speaker_audio.md
Normal file
@@ -0,0 +1,205 @@
|
||||
---
|
||||
module: [kind=guide] speaker_audio
|
||||
see: speaker.playAudio Play PCM audio using a speaker.
|
||||
see: cc.audio.dfpwm Provides utilities for encoding and decoding DFPWM files.
|
||||
---
|
||||
|
||||
# Playing audio with speakers
|
||||
CC: Tweaked's speaker peripheral provides a powerful way to play any audio you like with the @{speaker.playAudio}
|
||||
method. However, for people unfamiliar with digital audio, it's not the most intuitive thing to use. This guide provides
|
||||
an introduction to digital audio, demonstrates how to play music with CC: Tweaked's speakers, and then briefly discusses
|
||||
the more complex topic of audio processing.
|
||||
|
||||
## A short introduction to digital audio
|
||||
When sound is recorded it is captured as an analogue signal, effectively the electrical version of a sound
|
||||
wave. However, this signal is continuous, and so can't be used directly by a computer. Instead, we measure (or *sample*)
|
||||
the amplitude of the wave many times a second and then *quantise* that amplitude, rounding it to the nearest
|
||||
representable value.
|
||||
|
||||
This representation of sound - a long, uniformally sampled list of amplitudes is referred to as [Pulse-code
|
||||
Modulation][PCM] (PCM). PCM can be thought of as the "standard" audio format, as it's incredibly easy to work with. For
|
||||
instance, to mix two pieces of audio together, you can just add samples from the two tracks together and take the average.
|
||||
|
||||
CC: Tweaked's speakers also work with PCM audio. It plays back 48,000 samples a second, where each sample is an integer
|
||||
between -128 and 127. This is more commonly referred to as 48kHz and an 8-bit resolution.
|
||||
|
||||
Let's now look at a quick example. We're going to generate a [Sine Wave] at 220Hz, which sounds like a low monotonous
|
||||
hum. First we wrap our speaker peripheral, and then we fill a table (also referred to as a *buffer*) with 128×1024
|
||||
samples - this is the maximum number of samples a speaker can accept in one go.
|
||||
|
||||
In order to fill this buffer, we need to do a little maths. We want to play 220 sine waves each second, where each sine
|
||||
wave completes a full oscillation in 2π "units". This means one seconds worth of audio is 2×π×220 "units" long. We then
|
||||
need to split this into 48k samples, basically meaning for each sample we move 2×π×220/48k "along" the sine curve.
|
||||
|
||||
```lua {data-peripheral=speaker}
|
||||
local speaker = peripheral.find("speaker")
|
||||
|
||||
local buffer = {}
|
||||
local t, dt = 0, 2 * math.pi * 220 / 48000
|
||||
for i = 1, 128 * 1024 do
|
||||
buffer[i] = math.floor(math.sin(t) * 127)
|
||||
t = (t + dt) % (math.pi * 2)
|
||||
end
|
||||
|
||||
speaker.playAudio(buffer)
|
||||
```
|
||||
|
||||
## Streaming audio
|
||||
You might notice that the above snippet only generates a short bit of audio - 2.7s seconds to be precise. While we could
|
||||
try increasing the number of loop iterations, we'll get an error when we try to play it through the speaker: the sound
|
||||
buffer is too large for it to handle.
|
||||
|
||||
Our 2.7 seconds of audio is stored in a table with over 130 _thousand_ elements. If we wanted to play a full minute of
|
||||
sine waves (and why wouldn't you?), you'd need a table with almost 3 _million_. Suddenly you find these numbers adding
|
||||
up very quickly, and these tables take up more and more memory.
|
||||
|
||||
Instead of building our entire song (well, sine wave) in one go, we can produce it in small batches, each of which get
|
||||
passed off to @{speaker.playAudio} when the time is right. This allows us to build a _stream_ of audio, where we read
|
||||
chunks of audio one at a time (either from a file or a tone generator like above), do some optional processing to each
|
||||
one, and then play them.
|
||||
|
||||
Let's adapt our example from above to do that instead.
|
||||
|
||||
```lua {data-peripheral=speaker}
|
||||
local speaker = peripheral.find("speaker")
|
||||
|
||||
local t, dt = 0, 2 * math.pi * 220 / 48000
|
||||
while true do
|
||||
local buffer = {}
|
||||
for i = 1, 16 * 1024 * 8 do
|
||||
buffer[i] = math.floor(math.sin(t) * 127)
|
||||
t = (t + dt) % (math.pi * 2)
|
||||
end
|
||||
|
||||
while not speaker.playAudio(buffer) do
|
||||
os.pullEvent("speaker_audio_empty")
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
It looks pretty similar to before, aside from we've wrapped the generation and playing code in a while loop, and added a
|
||||
rather odd loop with @{speaker.playAudio} and @{os.pullEvent}.
|
||||
|
||||
Let's talk about this loop, why do we need to keep calling @{speaker.playAudio}? Remember that what we're trying to do
|
||||
here is avoid keeping too much audio in memory at once. However, if we're generating audio quicker than the speakers can
|
||||
play it, we're not helping at all - all this audio is still hanging around waiting to be played!
|
||||
|
||||
In order to avoid this, the speaker rejects any new chunks of audio if its backlog is too large. When this happens,
|
||||
@{speaker.playAudio} returns false. Once enough audio has played, and the backlog has been reduced, a
|
||||
@{speaker_audio_empty} event is queued, and we can try to play our chunk once more.
|
||||
|
||||
## Storing audio
|
||||
PCM is a fantastic way of representing audio when we want to manipulate it, but it's not very efficient when we want to
|
||||
store it to disk. Compare the size of a WAV file (which uses PCM) to an equivalent MP3, it's often 5 times the size.
|
||||
Instead, we store audio in special formats (or *codecs*) and then convert them to PCM when we need to do processing on
|
||||
them.
|
||||
|
||||
Modern audio codecs use some incredibly impressive techniques to compress the audio as much as possible while preserving
|
||||
sound quality. However, due to CC: Tweaked's limited processing power, it's not really possible to use these from your
|
||||
computer. Instead, we need something much simpler.
|
||||
|
||||
DFPWM (Dynamic Filter Pulse Width Modulation) is the de facto standard audio format of the ComputerCraft (and
|
||||
OpenComputers) world. Originally popularised by the addon mod [Computronics], CC:T now has built-in support for it with
|
||||
the @{cc.audio.dfpwm} module. This allows you to read DFPWM files from disk, decode them to PCM, and then play them
|
||||
using the speaker.
|
||||
|
||||
Let's dive in with an example, and we'll explain things afterwards:
|
||||
|
||||
```lua {data-peripheral=speaker}
|
||||
local dfpwm = require("cc.audio.dfpwm")
|
||||
local speaker = peripheral.find("speaker")
|
||||
|
||||
local decoder = dfpwm.make_decoder()
|
||||
for chunk in io.lines("data/example.dfpwm", 16 * 1024) do
|
||||
local buffer = decoder(chunk)
|
||||
|
||||
while not speaker.playAudio(buffer) do
|
||||
os.pullEvent("speaker_audio_empty")
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Once again, we see the @{speaker.playAudio}/@{speaker_audio_empty} loop. However, the rest of the program is a little
|
||||
different.
|
||||
|
||||
First, we require the dfpwm module and call @{cc.audio.dfpwm.make_decoder} to construct a new decoder. This decoder
|
||||
accepts blocks of DFPWM data and converts it to a list of 8-bit amplitudes, which we can then play with our speaker.
|
||||
|
||||
As mentioned above, @{speaker.playAudio} accepts at most 128×1024 samples in one go. DFPMW uses a single bit for each
|
||||
sample, which means we want to process our audio in chunks of 16×1024 bytes (16KiB). In order to do this, we use
|
||||
@{io.lines}, which provides a nice way to loop over chunks of a file. You can of course just use @{fs.open} and
|
||||
@{fs.BinaryReadHandle.read} if you prefer.
|
||||
|
||||
## Processing audio
|
||||
As mentioned near the beginning of this guide, PCM audio is pretty easy to work with as it's just a list of amplitudes.
|
||||
You can mix together samples from different streams by adding their amplitudes, change the rate of playback by removing
|
||||
samples, etc...
|
||||
|
||||
Let's put together a small demonstration here. We're going to add a small delay effect to the song above, so that you
|
||||
hear a faint echo a second and a half later.
|
||||
|
||||
In order to do this, we'll follow a format similar to the previous example, decoding the audio and then playing it.
|
||||
However, we'll also add some new logic between those two steps, which loops over every sample in our chunk of audio, and
|
||||
adds the sample from 1.5 seconds ago to it.
|
||||
|
||||
For this, we'll need to keep track of the last 72k samples - exactly 1.5 seconds worth of audio. We can do this using a
|
||||
[Ring Buffer], which helps makes things a little more efficient.
|
||||
|
||||
```lua {data-peripheral=speaker}
|
||||
local dfpwm = require("cc.audio.dfpwm")
|
||||
local speaker = peripheral.find("speaker")
|
||||
|
||||
-- Speakers play at 48kHz, so 1.5 seconds is 72k samples. We first fill our buffer
|
||||
-- with 0s, as there's nothing to echo at the start of the track!
|
||||
local samples_i, samples_n = 1, 48000 * 1.5
|
||||
local samples = {}
|
||||
for i = 1, samples_n do samples[i] = 0 end
|
||||
|
||||
local decoder = dfpwm.make_decoder()
|
||||
for chunk in io.lines("data/example.dfpwm", 16 * 1024) do
|
||||
local buffer = decoder(chunk)
|
||||
|
||||
for i = 1, #buffer do
|
||||
local original_value = buffer[i]
|
||||
|
||||
-- Replace this sample with its current amplitude plus the amplitude from 1.5 seconds ago.
|
||||
-- We scale both to ensure the resulting value is still between -128 and 127.
|
||||
buffer[i] = original_value * 0.6 + samples[samples_i] * 0.4
|
||||
|
||||
-- Now store the current sample, and move the "head" of our ring buffer forward one place.
|
||||
samples[samples_i] = original_value
|
||||
samples_i = samples_i + 1
|
||||
if samples_i > samples_n then samples_i = 1 end
|
||||
end
|
||||
|
||||
while not speaker.playAudio(buffer) do
|
||||
os.pullEvent("speaker_audio_empty")
|
||||
end
|
||||
|
||||
-- The audio processing above can be quite slow and preparing the first batch of audio
|
||||
-- may timeout the computer. We sleep to avoid this.
|
||||
-- There's definitely better ways of handling this - this is just an example!
|
||||
sleep(0.05)
|
||||
end
|
||||
```
|
||||
|
||||
:::note Confused?
|
||||
Don't worry if you don't understand this example. It's quite advanced, and does use some ideas that this guide doesn't
|
||||
cover. That said, don't be afraid to ask on [Discord] or [IRC] either!
|
||||
:::
|
||||
|
||||
It's worth noting that the examples of audio processing we've mentioned here are about manipulating the _amplitude_ of
|
||||
the wave. If you wanted to modify the _frequency_ (for instance, shifting the pitch), things get rather more complex.
|
||||
For this, you'd need to use the [Fast Fourier transform][FFT] to convert the stream of amplitudes to frequencies,
|
||||
process those, and then convert them back to amplitudes.
|
||||
|
||||
This is, I'm afraid, left as an exercise to the reader.
|
||||
|
||||
[Computronics]: https://github.com/Vexatos/Computronics/ "Computronics on GitHub"
|
||||
[FFT]: https://en.wikipedia.org/wiki/Fast_Fourier_transform "Fast Fourier transform - Wikipedia"
|
||||
[PCM]: https://en.wikipedia.org/wiki/Pulse-code_modulation "Pulse-code Modulation - Wikipedia"
|
||||
[Ring Buffer]: https://en.wikipedia.org/wiki/Circular_buffer "Circular buffer - Wikipedia"
|
||||
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
|
||||
|
||||
[Discord]: https://discord.computercraft.cc "The Minecraft Computer Mods Discord"
|
||||
[IRC]: http://webchat.esper.net/?channels=computercraft "IRC webchat on EsperNet"
|
83
doc/guides/using_require.md
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
module: [kind=guide] using_require
|
||||
---
|
||||
|
||||
# Reusing code with require
|
||||
A library is a collection of useful functions and other definitions which is stored separately to your main program. You
|
||||
might want to create a library because you have some functions which are used in multiple programs, or just to split
|
||||
your program into multiple more modular files.
|
||||
|
||||
Let's say we want to create a small library to make working with the @{term|terminal} a little easier. We'll provide two
|
||||
functions: `reset`, which clears the terminal and sets the cursor to (1, 1), and `write_center`, which prints some text
|
||||
in the middle of the screen.
|
||||
|
||||
Start off by creating a file called `more_term.lua`:
|
||||
|
||||
```lua {data-snippet=more_term}
|
||||
local function reset()
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
end
|
||||
|
||||
local function write_center(text)
|
||||
local x, y = term.getCursorPos()
|
||||
local width, height = term.getSize()
|
||||
term.setCursorPos(math.floor((width - #text) / 2) + 1, y)
|
||||
term.write(text)
|
||||
end
|
||||
|
||||
return { reset = reset, write_center = write_center }
|
||||
```
|
||||
|
||||
Now, what's going on here? We define our two functions as one might expect, and then at the bottom return a table with
|
||||
the two functions. When we require this library, this table is what is returned. With that, we can then call the
|
||||
original functions. Now create a new file, with the following:
|
||||
|
||||
```lua {data-mount=more_term:more_term.lua}
|
||||
local more_term = require("more_term")
|
||||
more_term.reset()
|
||||
more_term.write_center("Hello, world!")
|
||||
```
|
||||
|
||||
When run, this'll clear the screen and print some text in the middle of the first line.
|
||||
|
||||
## require in depth
|
||||
While the previous section is a good introduction to how @{require} operates, there are a couple of remaining points
|
||||
which are worth mentioning for more advanced usage.
|
||||
|
||||
### Libraries can return anything
|
||||
In our above example, we return a table containing the functions we want to expose. However, it's worth pointing out
|
||||
that you can return ''anything'' from your library - a table, a function or even just a string! @{require} treats them
|
||||
all the same, and just returns whatever your library provides.
|
||||
|
||||
### Module resolution and the package path
|
||||
In the above examples, we defined our library in a file, and @{require} read from it. While this is what you'll do most
|
||||
of the time, it is possible to make @{require} look elsewhere for your library, such as downloading from a website or
|
||||
loading from an in-memory library store.
|
||||
|
||||
As a result, the *module name* you pass to @{require} doesn't correspond to a file path. One common mistake is to load
|
||||
code from a sub-directory using `require("folder/library")` or even `require("folder/library.lua")`, neither of which
|
||||
will do quite what you expect.
|
||||
|
||||
When loading libraries (also referred to as *modules*) from files, @{require} searches along the *@{package.path|module
|
||||
path}*. By default, this looks something like:
|
||||
|
||||
* `?.lua`
|
||||
* `?/init.lua`
|
||||
* `/rom/modules/main/?.lua`
|
||||
* etc...
|
||||
|
||||
When you call `require("my_library")`, @{require} replaces the `?` in each element of the path with your module name, and
|
||||
checks if the file exists. In this case, we'd look for `my_library.lua`, `my_library/init.lua`,
|
||||
`/rom/modules/main/my_library.lua` and so on. Note that this works *relative to the current program*, so if your
|
||||
program is actually called `folder/program`, then we'll look for `folder/my_library.lua`, etc...
|
||||
|
||||
One other caveat is loading libraries from sub-directories. For instance, say we have a file
|
||||
`my/fancy/library.lua`. This can be loaded by using `require("my.fancy.library")` - the '.'s are replaced with '/'
|
||||
before we start looking for the library.
|
||||
|
||||
## External links
|
||||
There are several external resources which go into require in a little more detail:
|
||||
|
||||
- The [Lua Module tutorial](http://lua-users.org/wiki/ModulesTutorial) on the Lua wiki.
|
||||
- [Lua's manual section on @{require}](https://www.lua.org/manual/5.1/manual.html#pdf-require).
|
95
doc/reference/feature_compat.md
Normal file
@@ -0,0 +1,95 @@
|
||||
---
|
||||
module: [kind=reference] feature_compat
|
||||
---
|
||||
|
||||
# Lua 5.2/5.3 features in CC: Tweaked
|
||||
CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However, Cobalt and CC:T implement additional features from Lua 5.2 and 5.3 (as well as some deprecated 5.0 features) that are not available in base 5.1. This page lists all of the compatibility for these newer versions.
|
||||
|
||||
## Lua 5.2
|
||||
| Feature | Supported? | Notes |
|
||||
|---------------------------------------------------------------|------------|-------------------------------------------------------------------|
|
||||
| `goto`/labels | ❌ | |
|
||||
| `_ENV` | 🔶 | The `_ENV` global points to `getfenv()`, but it cannot be set. |
|
||||
| `\z` escape | ✔ | |
|
||||
| `\xNN` escape | ✔ | |
|
||||
| Hex literal fractional/exponent parts | ✔ | |
|
||||
| Empty statements | ❌ | |
|
||||
| `__len` metamethod | ✔ | |
|
||||
| `__ipairs` metamethod | ❌ | |
|
||||
| `__pairs` metamethod | ✔ | |
|
||||
| `bit32` library | ✔ | |
|
||||
| `collectgarbage` isrunning, generational, incremental options | ❌ | `collectgarbage` does not exist in CC:T. |
|
||||
| New `load` syntax | ✔ | |
|
||||
| `loadfile` mode parameter | ✔ | Supports both 5.1 and 5.2+ syntax. |
|
||||
| Removed `loadstring` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| Removed `getfenv`, `setfenv` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| `rawlen` function | ✔ | |
|
||||
| Negative index to `select` | ✔ | |
|
||||
| Removed `unpack` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| Arguments to `xpcall` | ❌ | |
|
||||
| Second return value from `coroutine.running` | ❌ | |
|
||||
| Removed `module` | ✔ | |
|
||||
| `package.loaders` -> `package.searchers` | ❌ | |
|
||||
| Second argument to loader functions | ✔ | |
|
||||
| `package.config` | ✔ | |
|
||||
| `package.searchpath` | ✔ | |
|
||||
| Removed `package.seeall` | ✔ | |
|
||||
| `string.dump` on functions with upvalues (blanks them out) | ✔ | |
|
||||
| `string.rep` separator | ❌ | |
|
||||
| `%g` match group | ❌ | |
|
||||
| Removal of `%z` match group | ❌ | |
|
||||
| Removed `table.maxn` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| `table.pack`/`table.unpack` | ✔ | |
|
||||
| `math.log` base argument | ✔ | |
|
||||
| Removed `math.log10` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| `*L` mode to `file:read` | ✔ | |
|
||||
| `os.execute` exit type + return value | ❌ | `os.execute` does not exist in CC:T. |
|
||||
| `os.exit` close argument | ❌ | `os.exit` does not exist in CC:T. |
|
||||
| `istailcall` field in `debug.getinfo` | ❌ | |
|
||||
| `nparams` field in `debug.getinfo` | ✔ | |
|
||||
| `isvararg` field in `debug.getinfo` | ✔ | |
|
||||
| `debug.getlocal` negative indices for varargs | ❌ | |
|
||||
| `debug.getuservalue`/`debug.setuservalue` | ❌ | Userdata are rarely used in CC:T, so this is not necessary. |
|
||||
| `debug.upvalueid` | ✔ | |
|
||||
| `debug.upvaluejoin` | ✔ | |
|
||||
| Tail call hooks | ❌ | |
|
||||
| `=` prefix for chunks | ✔ | |
|
||||
| Yield across C boundary | ✔ | |
|
||||
| Removal of ambiguity error | ❌ | |
|
||||
| Identifiers may no longer use locale-dependent letters | ✔ | |
|
||||
| Ephemeron tables | ❌ | |
|
||||
| Identical functions may be reused | ❌ | |
|
||||
| Generational garbage collector | ❌ | Cobalt uses the built-in Java garbage collector. |
|
||||
|
||||
## Lua 5.3
|
||||
| Feature | Supported? | Notes |
|
||||
|---------------------------------------------------------------------------------------|------------|---------------------------|
|
||||
| Integer subtype | ❌ | |
|
||||
| Bitwise operators/floor division | ❌ | |
|
||||
| `\u{XXX}` escape sequence | ✔ | |
|
||||
| `utf8` library | ✔ | |
|
||||
| removed `__ipairs` metamethod | ✔ | |
|
||||
| `coroutine.isyieldable` | ❌ | |
|
||||
| `string.dump` strip argument | ✔ | |
|
||||
| `string.pack`/`string.unpack`/`string.packsize` | ✔ | |
|
||||
| `table.move` | ❌ | |
|
||||
| `math.atan2` -> `math.atan` | ❌ | |
|
||||
| Removed `math.frexp`, `math.ldexp`, `math.pow`, `math.cosh`, `math.sinh`, `math.tanh` | ❌ | |
|
||||
| `math.maxinteger`/`math.mininteger` | ❌ | |
|
||||
| `math.tointeger` | ❌ | |
|
||||
| `math.type` | ❌ | |
|
||||
| `math.ult` | ❌ | |
|
||||
| Removed `bit32` library | ❌ | |
|
||||
| Remove `*` from `file:read` modes | ✔ | |
|
||||
| Metamethods respected in `table.*`, `ipairs` | 🔶 | Only `__lt` is respected. |
|
||||
|
||||
## Lua 5.0
|
||||
| Feature | Supported? | Notes |
|
||||
|----------------------------------|------------|--------------------------------------------------|
|
||||
| `arg` table | 🔶 | Only set in the shell - not used in functions. |
|
||||
| `string.gfind` | ✔ | Equal to `string.gmatch`. |
|
||||
| `table.getn` | ✔ | Equal to `#tbl`. |
|
||||
| `table.setn` | ❌ | |
|
||||
| `math.mod` | ✔ | Equal to `math.fmod`. |
|
||||
| `table.foreach`/`table.foreachi` | ✔ | |
|
||||
| `gcinfo` | ❌ | Cobalt uses the built-in Java garbage collector. |
|
@@ -1,6 +1,4 @@
|
||||
--- The FS API allows you to manipulate files and the filesystem.
|
||||
--
|
||||
-- @module fs
|
||||
--- @module fs
|
||||
|
||||
--- Returns true if a path is mounted to the parent filesystem.
|
||||
--
|
||||
|
@@ -12,16 +12,19 @@ rounded up to the nearest multiple of 0.05 seconds. If you are using coroutines
|
||||
or the @{parallel|parallel API}, it will only pause execution of the current
|
||||
thread, not the whole program.
|
||||
|
||||
**Note** Because sleep internally uses timers, it is a function that yields.
|
||||
This means that you can use it to prevent "Too long without yielding" errors,
|
||||
however, as the minimum sleep time is 0.05 seconds, it will slow your program
|
||||
down.
|
||||
:::tip
|
||||
Because sleep internally uses timers, it is a function that yields. This means
|
||||
that you can use it to prevent "Too long without yielding" errors, however, as
|
||||
the minimum sleep time is 0.05 seconds, it will slow your program down.
|
||||
:::
|
||||
|
||||
**Warning** Internally, this function queues and waits for a timer event (using
|
||||
:::caution
|
||||
Internally, this function queues and waits for a timer event (using
|
||||
@{os.startTimer}), however it does not listen for any other events. This means
|
||||
that any event that occurs while sleeping will be entirely discarded. If you
|
||||
need to receive events while sleeping, consider using @{os.startTimer|timers},
|
||||
or the @{parallel|parallel API}.
|
||||
:::
|
||||
|
||||
@tparam number time The number of seconds to sleep for, rounded up to the
|
||||
nearest multiple of 0.05.
|
||||
@@ -59,7 +62,7 @@ function print(...) end
|
||||
-- @usage printError("Something went wrong!")
|
||||
function printError(...) end
|
||||
|
||||
--[[- Reads user input from the terminal, automatically handling arrow keys,
|
||||
--[[- Reads user input from the terminal. This automatically handles arrow keys,
|
||||
pasting, character replacement, history scrollback, auto-completion, and
|
||||
default values.
|
||||
|
||||
@@ -107,10 +110,15 @@ the prompt.
|
||||
]]
|
||||
function read(replaceChar, history, completeFn, default) end
|
||||
|
||||
--- The ComputerCraft and Minecraft version of the current computer environment.
|
||||
--- Stores the current ComputerCraft and Minecraft versions.
|
||||
--
|
||||
-- Outside of Minecraft (for instance, in an emulator) @{_HOST} will contain the
|
||||
-- emulator's version instead.
|
||||
--
|
||||
-- For example, `ComputerCraft 1.93.0 (Minecraft 1.15.2)`.
|
||||
-- @usage _HOST
|
||||
-- @usage Print the current computer's environment.
|
||||
--
|
||||
-- print(_HOST)
|
||||
-- @since 1.76
|
||||
_HOST = _HOST
|
||||
|
||||
|
@@ -1,14 +1,13 @@
|
||||
--- The http library allows communicating with web servers, sending and
|
||||
-- receiving data from them.
|
||||
--- Make HTTP requests, sending and receiving data to a remote web server.
|
||||
--
|
||||
-- @module http
|
||||
-- @since 1.1
|
||||
-- @see local_ips To allow accessing servers running on your local network.
|
||||
|
||||
--- Asynchronously make a HTTP request to the given url.
|
||||
--
|
||||
-- This returns immediately, a [`http_success`](#http-success-event) or
|
||||
-- [`http_failure`](#http-failure-event) will be queued once the request has
|
||||
-- completed.
|
||||
-- This returns immediately, a @{http_success} or @{http_failure} will be queued
|
||||
-- once the request has completed.
|
||||
--
|
||||
-- @tparam string url The url to request
|
||||
-- @tparam[opt] string body An optional string containing the body of the
|
||||
@@ -112,9 +111,8 @@ function post(...) end
|
||||
|
||||
--- Asynchronously determine whether a URL can be requested.
|
||||
--
|
||||
-- If this returns `true`, one should also listen for [`http_check`
|
||||
-- events](#http-check-event) which will container further information about
|
||||
-- whether the URL is allowed or not.
|
||||
-- If this returns `true`, one should also listen for @{http_check} which will
|
||||
-- container further information about whether the URL is allowed or not.
|
||||
--
|
||||
-- @tparam string url The URL to check.
|
||||
-- @treturn true When this url is not invalid. This does not imply that it is
|
||||
@@ -128,9 +126,8 @@ function checkURLAsync(url) end
|
||||
|
||||
--- Determine whether a URL can be requested.
|
||||
--
|
||||
-- If this returns `true`, one should also listen for [`http_check`
|
||||
-- events](#http-check-event) which will container further information about
|
||||
-- whether the URL is allowed or not.
|
||||
-- If this returns `true`, one should also listen for @{http_check} which will
|
||||
-- container further information about whether the URL is allowed or not.
|
||||
--
|
||||
-- @tparam string url The URL to check.
|
||||
-- @treturn true When this url is valid and can be requested via @{http.request}.
|
||||
@@ -168,9 +165,8 @@ function websocket(url, headers) end
|
||||
|
||||
--- Asynchronously open a websocket.
|
||||
--
|
||||
-- This returns immediately, a [`websocket_success`](#websocket-success-event)
|
||||
-- or [`websocket_failure`](#websocket-failure-event) will be queued once the
|
||||
-- request has completed.
|
||||
-- This returns immediately, a @{websocket_success} or @{websocket_failure}
|
||||
-- will be queued once the request has completed.
|
||||
--
|
||||
-- @tparam string url The websocket url to connect to. This should have the
|
||||
-- `ws://` or `wss://` protocol.
|
||||
|
@@ -1,10 +1,10 @@
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
|
||||
# Mod properties
|
||||
mod_version=1.99.0
|
||||
mod_version=1.100.6
|
||||
|
||||
# Minecraft properties (update mods.toml when changing)
|
||||
mc_version=1.18
|
||||
mapping_version=2021.09.05
|
||||
forge_version=38.0.0
|
||||
mc_version=1.19
|
||||
mapping_version=2022.03.13
|
||||
forge_version=41.0.16
|
||||
# NO SERIOUSLY, UPDATE mods.toml WHEN CHANGING
|
||||
|
@@ -1,8 +1,7 @@
|
||||
; -*- mode: Lisp;-*-
|
||||
|
||||
(sources
|
||||
/doc/stub/
|
||||
/doc/events/
|
||||
/doc/
|
||||
/build/docs/luaJavadoc/
|
||||
/src/main/resources/*/computercraft/lua/bios.lua
|
||||
/src/main/resources/*/computercraft/lua/rom/
|
||||
@@ -27,7 +26,9 @@
|
||||
(module-kinds
|
||||
(peripheral Peripherals)
|
||||
(generic_peripheral "Generic Peripherals")
|
||||
(event Events))
|
||||
(event Events)
|
||||
(guide Guides)
|
||||
(reference Reference))
|
||||
|
||||
(library-path
|
||||
/doc/stub/
|
||||
|
1805
package-lock.json
generated
11
package.json
@@ -4,15 +4,26 @@
|
||||
"description": "Website additions for tweaked.cc",
|
||||
"author": "SquidDev",
|
||||
"license": "BSD-3-Clause",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"preact": "^10.5.5",
|
||||
"tslib": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^8.2.5",
|
||||
"@rollup/plugin-url": "^6.1.0",
|
||||
"@types/glob": "^7.2.0",
|
||||
"@types/react-dom": "^18.0.5",
|
||||
"glob": "^8.0.3",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"rehype": "^12.0.1",
|
||||
"rehype-highlight": "^5.0.2",
|
||||
"rehype-react": "^7.1.1",
|
||||
"requirejs": "^2.3.6",
|
||||
"rollup": "^2.33.1",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"ts-node": "^10.8.0",
|
||||
"typescript": "^4.0.5"
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import { readFileSync } from "fs";
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import url from '@rollup/plugin-url';
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
|
||||
const input = "src/web";
|
||||
@@ -10,7 +11,7 @@ const requirejs = readFileSync("node_modules/requirejs/require.js");
|
||||
export default {
|
||||
input: [`${input}/index.tsx`],
|
||||
output: {
|
||||
file: "build/rollup/index.js",
|
||||
dir: "build/rollup/",
|
||||
// We bundle requirejs (and config) into the header. It's rather gross
|
||||
// but also works reasonably well.
|
||||
// Also suffix a ?v=${date} onto the end in the event we need to require a specific copy-cat version.
|
||||
@@ -18,7 +19,7 @@ export default {
|
||||
${requirejs}
|
||||
require.config({
|
||||
paths: { copycat: "https://copy-cat.squiddev.cc" },
|
||||
urlArgs: function(id) { return id == "copycat/embed" ? "?v=20211127" : ""; }
|
||||
urlArgs: function(id) { return id == "copycat/embed" ? "?v=20211221" : ""; }
|
||||
});
|
||||
`,
|
||||
format: "amd",
|
||||
@@ -33,12 +34,18 @@ export default {
|
||||
plugins: [
|
||||
typescript(),
|
||||
|
||||
url({
|
||||
include: "**/*.dfpwm",
|
||||
fileName: "[name]-[hash][extname]",
|
||||
publicPath: "/",
|
||||
}),
|
||||
|
||||
{
|
||||
name: "cc-tweaked",
|
||||
async transform(code, file) {
|
||||
// Allow loading files in /mount.
|
||||
const ext = path.extname(file);
|
||||
return ext != '.tsx' && ext != '.ts' && path.dirname(file) === path.resolve(`${input}/mount`)
|
||||
return ext != '.dfpwm' && path.dirname(file) === path.resolve(`${input}/mount`)
|
||||
? `export default ${JSON.stringify(code)};\n`
|
||||
: null;
|
||||
},
|
||||
|
760
src/generated/export/index.json
generated
Normal file
@@ -0,0 +1,760 @@
|
||||
{
|
||||
"itemNames": {
|
||||
"computercraft:cable": "Networking Cable",
|
||||
"computercraft:computer_advanced": "Advanced Computer",
|
||||
"computercraft:computer_command": "Command Computer",
|
||||
"computercraft:computer_normal": "Computer",
|
||||
"computercraft:disk": "Floppy Disk",
|
||||
"computercraft:disk_drive": "Disk Drive",
|
||||
"computercraft:monitor_advanced": "Advanced Monitor",
|
||||
"computercraft:monitor_normal": "Monitor",
|
||||
"computercraft:pocket_computer_advanced": "Advanced Pocket Computer",
|
||||
"computercraft:pocket_computer_normal": "Pocket Computer",
|
||||
"computercraft:printed_book": "Printed Book",
|
||||
"computercraft:printed_page": "Printed Page",
|
||||
"computercraft:printed_pages": "Printed Pages",
|
||||
"computercraft:printer": "Printer",
|
||||
"computercraft:speaker": "Speaker",
|
||||
"computercraft:treasure_disk": "Floppy Disk",
|
||||
"computercraft:turtle_advanced": "Advanced Turtle",
|
||||
"computercraft:turtle_normal": "Turtle",
|
||||
"computercraft:wired_modem": "Wired Modem",
|
||||
"computercraft:wired_modem_full": "Wired Modem",
|
||||
"computercraft:wireless_modem_advanced": "Ender Modem",
|
||||
"computercraft:wireless_modem_normal": "Wireless Modem",
|
||||
"minecraft:black_dye": "Black Dye",
|
||||
"minecraft:blue_dye": "Blue Dye",
|
||||
"minecraft:brown_dye": "Brown Dye",
|
||||
"minecraft:chest": "Chest",
|
||||
"minecraft:command_block": "Command Block",
|
||||
"minecraft:cyan_dye": "Cyan Dye",
|
||||
"minecraft:ender_eye": "Eye of Ender",
|
||||
"minecraft:ender_pearl": "Ender Pearl",
|
||||
"minecraft:glass_pane": "Glass Pane",
|
||||
"minecraft:gold_block": "Block of Gold",
|
||||
"minecraft:gold_ingot": "Gold Ingot",
|
||||
"minecraft:golden_apple": "Golden Apple",
|
||||
"minecraft:gray_dye": "Gray Dye",
|
||||
"minecraft:green_dye": "Green Dye",
|
||||
"minecraft:iron_ingot": "Iron Ingot",
|
||||
"minecraft:leather": "Leather",
|
||||
"minecraft:light_blue_dye": "Light Blue Dye",
|
||||
"minecraft:light_gray_dye": "Light Gray Dye",
|
||||
"minecraft:lime_dye": "Lime Dye",
|
||||
"minecraft:magenta_dye": "Magenta Dye",
|
||||
"minecraft:note_block": "Note Block",
|
||||
"minecraft:orange_dye": "Orange Dye",
|
||||
"minecraft:pink_dye": "Pink Dye",
|
||||
"minecraft:purple_dye": "Purple Dye",
|
||||
"minecraft:red_dye": "Red Dye",
|
||||
"minecraft:redstone": "Redstone Dust",
|
||||
"minecraft:stone": "Stone",
|
||||
"minecraft:string": "String",
|
||||
"minecraft:white_dye": "White Dye",
|
||||
"minecraft:yellow_dye": "Yellow Dye"
|
||||
},
|
||||
"recipes": {
|
||||
"computercraft:cable": {
|
||||
"inputs": [
|
||||
null,
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
null,
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:redstone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
null,
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
null
|
||||
],
|
||||
"output": "computercraft:cable",
|
||||
"count": 6
|
||||
},
|
||||
"computercraft:computer_advanced": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:redstone"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:glass_pane"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:computer_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:computer_advanced_upgrade": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"computercraft:computer_normal"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
null,
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:computer_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:computer_command": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:command_block"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:glass_pane"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:computer_command",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:computer_normal": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:redstone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:glass_pane"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:computer_normal",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:disk_drive": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:redstone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:redstone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:disk_drive",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:monitor_advanced": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:glass_pane"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:monitor_advanced",
|
||||
"count": 4
|
||||
},
|
||||
"computercraft:monitor_normal": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:glass_pane"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:monitor_normal",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:pocket_computer_advanced": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:golden_apple"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:glass_pane"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:pocket_computer_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:pocket_computer_advanced_upgrade": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"computercraft:pocket_computer_normal"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
null,
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:pocket_computer_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:pocket_computer_normal": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:golden_apple"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:glass_pane"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:pocket_computer_normal",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:printed_book": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:leather"
|
||||
],
|
||||
[
|
||||
"computercraft:printed_page"
|
||||
],
|
||||
[
|
||||
"minecraft:string"
|
||||
],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"output": "computercraft:printed_book",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:printed_pages": {
|
||||
"inputs": [
|
||||
[
|
||||
"computercraft:printed_page"
|
||||
],
|
||||
[
|
||||
"computercraft:printed_page"
|
||||
],
|
||||
[
|
||||
"minecraft:string"
|
||||
],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"output": "computercraft:printed_pages",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:printer": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:redstone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:black_dye",
|
||||
"minecraft:blue_dye",
|
||||
"minecraft:brown_dye",
|
||||
"minecraft:cyan_dye",
|
||||
"minecraft:gray_dye",
|
||||
"minecraft:green_dye",
|
||||
"minecraft:light_blue_dye",
|
||||
"minecraft:light_gray_dye",
|
||||
"minecraft:lime_dye",
|
||||
"minecraft:magenta_dye",
|
||||
"minecraft:orange_dye",
|
||||
"minecraft:pink_dye",
|
||||
"minecraft:purple_dye",
|
||||
"minecraft:red_dye",
|
||||
"minecraft:white_dye",
|
||||
"minecraft:yellow_dye"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:printer",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:speaker": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:note_block"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:redstone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:speaker",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:turtle_advanced": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"computercraft:computer_advanced"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:chest"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:turtle_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:turtle_advanced_upgrade": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"computercraft:turtle_normal"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
null,
|
||||
[
|
||||
"minecraft:gold_block"
|
||||
],
|
||||
null
|
||||
],
|
||||
"output": "computercraft:turtle_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:turtle_normal": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:iron_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:iron_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:iron_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:iron_ingot"
|
||||
],
|
||||
[
|
||||
"computercraft:computer_normal"
|
||||
],
|
||||
[
|
||||
"minecraft:iron_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:iron_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:chest"
|
||||
],
|
||||
[
|
||||
"minecraft:iron_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:turtle_normal",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:wired_modem": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:redstone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:wired_modem",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:wired_modem_full_from": {
|
||||
"inputs": [
|
||||
[
|
||||
"computercraft:wired_modem"
|
||||
],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"output": "computercraft:wired_modem_full",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:wired_modem_full_to": {
|
||||
"inputs": [
|
||||
[
|
||||
"computercraft:wired_modem_full"
|
||||
],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"output": "computercraft:wired_modem",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:wireless_modem_advanced": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:ender_eye"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
],
|
||||
[
|
||||
"minecraft:gold_ingot"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:wireless_modem_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:wireless_modem_normal": {
|
||||
"inputs": [
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:ender_pearl"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
],
|
||||
[
|
||||
"minecraft:stone"
|
||||
]
|
||||
],
|
||||
"output": "computercraft:wireless_modem_normal",
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/generated/export/items/computercraft/cable.png
generated
Normal file
After Width: | Height: | Size: 375 B |
BIN
src/generated/export/items/computercraft/computer_advanced.png
generated
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
src/generated/export/items/computercraft/computer_command.png
generated
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
src/generated/export/items/computercraft/computer_normal.png
generated
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/generated/export/items/computercraft/disk.png
generated
Normal file
After Width: | Height: | Size: 189 B |
BIN
src/generated/export/items/computercraft/disk_drive.png
generated
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
src/generated/export/items/computercraft/monitor_advanced.png
generated
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
src/generated/export/items/computercraft/monitor_normal.png
generated
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/generated/export/items/computercraft/pocket_computer_advanced.png
generated
Normal file
After Width: | Height: | Size: 158 B |
BIN
src/generated/export/items/computercraft/pocket_computer_normal.png
generated
Normal file
After Width: | Height: | Size: 158 B |
BIN
src/generated/export/items/computercraft/printed_book.png
generated
Normal file
After Width: | Height: | Size: 287 B |
BIN
src/generated/export/items/computercraft/printed_page.png
generated
Normal file
After Width: | Height: | Size: 208 B |
BIN
src/generated/export/items/computercraft/printed_pages.png
generated
Normal file
After Width: | Height: | Size: 259 B |
BIN
src/generated/export/items/computercraft/printer.png
generated
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
src/generated/export/items/computercraft/speaker.png
generated
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/generated/export/items/computercraft/treasure_disk.png
generated
Normal file
After Width: | Height: | Size: 189 B |
BIN
src/generated/export/items/computercraft/turtle_advanced.png
generated
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/generated/export/items/computercraft/turtle_normal.png
generated
Normal file
After Width: | Height: | Size: 977 B |
BIN
src/generated/export/items/computercraft/wired_modem.png
generated
Normal file
After Width: | Height: | Size: 593 B |
BIN
src/generated/export/items/computercraft/wired_modem_full.png
generated
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/generated/export/items/computercraft/wireless_modem_advanced.png
generated
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/generated/export/items/computercraft/wireless_modem_normal.png
generated
Normal file
After Width: | Height: | Size: 620 B |
BIN
src/generated/export/items/minecraft/black_dye.png
generated
Normal file
After Width: | Height: | Size: 218 B |
BIN
src/generated/export/items/minecraft/blue_dye.png
generated
Normal file
After Width: | Height: | Size: 228 B |
BIN
src/generated/export/items/minecraft/brown_dye.png
generated
Normal file
After Width: | Height: | Size: 218 B |
BIN
src/generated/export/items/minecraft/chest.png
generated
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/generated/export/items/minecraft/command_block.png
generated
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/generated/export/items/minecraft/cyan_dye.png
generated
Normal file
After Width: | Height: | Size: 243 B |
BIN
src/generated/export/items/minecraft/ender_eye.png
generated
Normal file
After Width: | Height: | Size: 278 B |
BIN
src/generated/export/items/minecraft/ender_pearl.png
generated
Normal file
After Width: | Height: | Size: 266 B |
BIN
src/generated/export/items/minecraft/glass_pane.png
generated
Normal file
After Width: | Height: | Size: 186 B |
BIN
src/generated/export/items/minecraft/gold_block.png
generated
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/generated/export/items/minecraft/gold_ingot.png
generated
Normal file
After Width: | Height: | Size: 240 B |
BIN
src/generated/export/items/minecraft/golden_apple.png
generated
Normal file
After Width: | Height: | Size: 257 B |
BIN
src/generated/export/items/minecraft/gray_dye.png
generated
Normal file
After Width: | Height: | Size: 229 B |
BIN
src/generated/export/items/minecraft/green_dye.png
generated
Normal file
After Width: | Height: | Size: 236 B |
BIN
src/generated/export/items/minecraft/iron_ingot.png
generated
Normal file
After Width: | Height: | Size: 240 B |
BIN
src/generated/export/items/minecraft/leather.png
generated
Normal file
After Width: | Height: | Size: 242 B |
BIN
src/generated/export/items/minecraft/light_blue_dye.png
generated
Normal file
After Width: | Height: | Size: 224 B |
BIN
src/generated/export/items/minecraft/light_gray_dye.png
generated
Normal file
After Width: | Height: | Size: 229 B |
BIN
src/generated/export/items/minecraft/lime_dye.png
generated
Normal file
After Width: | Height: | Size: 221 B |
BIN
src/generated/export/items/minecraft/magenta_dye.png
generated
Normal file
After Width: | Height: | Size: 220 B |
BIN
src/generated/export/items/minecraft/note_block.png
generated
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/generated/export/items/minecraft/orange_dye.png
generated
Normal file
After Width: | Height: | Size: 232 B |
BIN
src/generated/export/items/minecraft/pink_dye.png
generated
Normal file
After Width: | Height: | Size: 220 B |
BIN
src/generated/export/items/minecraft/purple_dye.png
generated
Normal file
After Width: | Height: | Size: 220 B |
BIN
src/generated/export/items/minecraft/red_dye.png
generated
Normal file
After Width: | Height: | Size: 233 B |
BIN
src/generated/export/items/minecraft/redstone.png
generated
Normal file
After Width: | Height: | Size: 236 B |
BIN
src/generated/export/items/minecraft/stone.png
generated
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/generated/export/items/minecraft/string.png
generated
Normal file
After Width: | Height: | Size: 193 B |
BIN
src/generated/export/items/minecraft/white_dye.png
generated
Normal file
After Width: | Height: | Size: 245 B |
BIN
src/generated/export/items/minecraft/yellow_dye.png
generated
Normal file
After Width: | Height: | Size: 235 B |
@@ -22,8 +22,7 @@
|
||||
"cable": "true"
|
||||
}
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "wired_modem",
|
||||
@@ -49,8 +48,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -29,8 +29,7 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -29,8 +29,7 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -29,8 +29,7 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -15,8 +15,7 @@
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -15,8 +15,7 @@
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -15,8 +15,7 @@
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -15,8 +15,7 @@
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -15,8 +15,7 @@
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -29,8 +29,7 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -29,8 +29,7 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -15,8 +15,7 @@
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -15,8 +15,7 @@
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -15,8 +15,7 @@
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"functions": []
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft;
|
||||
|
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
||||
import dan200.computercraft.api.detail.IDetailProvider;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
import dan200.computercraft.api.lua.GenericSource;
|
||||
@@ -24,13 +25,13 @@ import dan200.computercraft.shared.BundledRedstone;
|
||||
import dan200.computercraft.shared.MediaProviders;
|
||||
import dan200.computercraft.shared.Peripherals;
|
||||
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.DetailProviders;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
import dan200.computercraft.shared.wired.WiredNode;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -59,10 +60,12 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
|
||||
public static InputStream getResourceFile( String domain, String subPath )
|
||||
{
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ServerLifecycleHooks.getCurrentServer().getResourceManager();
|
||||
var manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
|
||||
var resource = manager.getResource( new ResourceLocation( domain, subPath ) ).orElse( null );
|
||||
if( resource == null ) return null;
|
||||
try
|
||||
{
|
||||
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
|
||||
return resource.open();
|
||||
}
|
||||
catch( IOException ignored )
|
||||
{
|
||||
@@ -156,6 +159,12 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
ApiFactories.register( factory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void registerDetailProvider( @Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider )
|
||||
{
|
||||
DetailProviders.registerProvider( type, provider );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element )
|
||||
|
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api;
|
||||
|
||||
import dan200.computercraft.api.detail.BlockReference;
|
||||
import dan200.computercraft.api.detail.IDetailProvider;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
import dan200.computercraft.api.lua.GenericSource;
|
||||
@@ -20,10 +22,12 @@ import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -111,7 +115,7 @@ public final class ComputerCraftAPI
|
||||
}
|
||||
|
||||
/**
|
||||
* rers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
|
||||
* Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
|
||||
*
|
||||
* @param provider The peripheral provider to register.
|
||||
* @see IPeripheral
|
||||
@@ -196,6 +200,20 @@ public final class ComputerCraftAPI
|
||||
getInstance().registerAPIFactory( factory );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a detail provider to provide additional details for blocks, fluids and items when inspected by methods
|
||||
* such as {@code turtle.getItemDetail()} or {@code turtle.inspect()}.
|
||||
*
|
||||
* @param type The type of object that this provider can provide details for. Should be {@link BlockReference},
|
||||
* {@link FluidStack} or {@link ItemStack}.
|
||||
* @param provider The detail provider to register.
|
||||
* @param <T> The type of object that this provider can provide details for.
|
||||
*/
|
||||
public static <T> void registerDetailProvider( @Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider )
|
||||
{
|
||||
getInstance().registerDetailProvider( type, provider );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new wired node for a given wired element.
|
||||
*
|
||||
@@ -272,6 +290,8 @@ public final class ComputerCraftAPI
|
||||
|
||||
void registerAPIFactory( @Nonnull ILuaAPIFactory factory );
|
||||
|
||||
<T> void registerDetailProvider( @Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider );
|
||||
|
||||
@Nonnull
|
||||
IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element );
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api;
|
||||
@@ -9,7 +9,7 @@ import dan200.computercraft.ComputerCraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
@@ -20,47 +20,47 @@ public class ComputerCraftTags
|
||||
{
|
||||
public static class Items
|
||||
{
|
||||
public static final Tag.Named<Item> COMPUTER = make( "computer" );
|
||||
public static final Tag.Named<Item> TURTLE = make( "turtle" );
|
||||
public static final Tag.Named<Item> WIRED_MODEM = make( "wired_modem" );
|
||||
public static final Tag.Named<Item> MONITOR = make( "monitor" );
|
||||
public static final TagKey<Item> COMPUTER = make( "computer" );
|
||||
public static final TagKey<Item> TURTLE = make( "turtle" );
|
||||
public static final TagKey<Item> WIRED_MODEM = make( "wired_modem" );
|
||||
public static final TagKey<Item> MONITOR = make( "monitor" );
|
||||
|
||||
private static Tag.Named<Item> make( String name )
|
||||
private static TagKey<Item> make( String name )
|
||||
{
|
||||
return ItemTags.bind( new ResourceLocation( ComputerCraft.MOD_ID, name ).toString() );
|
||||
return ItemTags.create( new ResourceLocation( ComputerCraft.MOD_ID, name ) );
|
||||
}
|
||||
}
|
||||
|
||||
public static class Blocks
|
||||
{
|
||||
public static final Tag.Named<Block> COMPUTER = make( "computer" );
|
||||
public static final Tag.Named<Block> TURTLE = make( "turtle" );
|
||||
public static final Tag.Named<Block> WIRED_MODEM = make( "wired_modem" );
|
||||
public static final Tag.Named<Block> MONITOR = make( "monitor" );
|
||||
public static final TagKey<Block> COMPUTER = make( "computer" );
|
||||
public static final TagKey<Block> TURTLE = make( "turtle" );
|
||||
public static final TagKey<Block> WIRED_MODEM = make( "wired_modem" );
|
||||
public static final TagKey<Block> MONITOR = make( "monitor" );
|
||||
|
||||
/**
|
||||
* Blocks which can be broken by any turtle tool.
|
||||
*/
|
||||
public static final Tag.Named<Block> TURTLE_ALWAYS_BREAKABLE = make( "turtle_always_breakable" );
|
||||
public static final TagKey<Block> TURTLE_ALWAYS_BREAKABLE = make( "turtle_always_breakable" );
|
||||
|
||||
/**
|
||||
* Blocks which can be broken by the default shovel tool.
|
||||
*/
|
||||
public static final Tag.Named<Block> TURTLE_SHOVEL_BREAKABLE = make( "turtle_shovel_harvestable" );
|
||||
public static final TagKey<Block> TURTLE_SHOVEL_BREAKABLE = make( "turtle_shovel_harvestable" );
|
||||
|
||||
/**
|
||||
* Blocks which can be broken with the default sword tool.
|
||||
*/
|
||||
public static final Tag.Named<Block> TURTLE_SWORD_BREAKABLE = make( "turtle_sword_harvestable" );
|
||||
public static final TagKey<Block> TURTLE_SWORD_BREAKABLE = make( "turtle_sword_harvestable" );
|
||||
|
||||
/**
|
||||
* Blocks which can be broken with the default hoe tool.
|
||||
*/
|
||||
public static final Tag.Named<Block> TURTLE_HOE_BREAKABLE = make( "turtle_hoe_harvestable" );
|
||||
public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make( "turtle_hoe_harvestable" );
|
||||
|
||||
private static Tag.Named<Block> make( String name )
|
||||
private static TagKey<Block> make( String name )
|
||||
{
|
||||
return BlockTags.bind( new ResourceLocation( ComputerCraft.MOD_ID, name ).toString() );
|
||||
return BlockTags.create( new ResourceLocation( ComputerCraft.MOD_ID, name ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.client;
|
||||
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.detail;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An item detail provider for {@link ItemStack}'s whose {@link Item} has a specific type.
|
||||
*
|
||||
* @param <T> The type the stack's item must have.
|
||||
*/
|
||||
public abstract class BasicItemDetailProvider<T> implements IDetailProvider<ItemStack>
|
||||
{
|
||||
private final Class<T> itemType;
|
||||
private final String namespace;
|
||||
|
||||
/**
|
||||
* Create a new item detail provider. Meta will be inserted into a new sub-map named as per {@code namespace}.
|
||||
*
|
||||
* @param itemType The type the stack's item must have.
|
||||
* @param namespace The namespace to use for this provider.
|
||||
*/
|
||||
public BasicItemDetailProvider( String namespace, @Nonnull Class<T> itemType )
|
||||
{
|
||||
Objects.requireNonNull( itemType );
|
||||
this.itemType = itemType;
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new item detail provider. Meta will be inserted directly into the results.
|
||||
*
|
||||
* @param itemType The type the stack's item must have.
|
||||
*/
|
||||
public BasicItemDetailProvider( @Nonnull Class<T> itemType )
|
||||
{
|
||||
this( null, itemType );
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide additional details for the given {@link Item} and {@link ItemStack}. This method is called by
|
||||
* {@code turtle.getItemDetail()}. New properties should be added to the given {@link Map}, {@code data}.
|
||||
*
|
||||
* This method is always called on the server thread, so it is safe to interact with the world here, but you should
|
||||
* take care to avoid long blocking operations as this will stall the server and other computers.
|
||||
*
|
||||
* @param data The full details to be returned for this item stack. New properties should be added to this map.
|
||||
* @param stack The item stack to provide details for.
|
||||
* @param item The item to provide details for.
|
||||
*/
|
||||
public abstract void provideDetails( @Nonnull Map<? super String, Object> data, @Nonnull ItemStack stack,
|
||||
@Nonnull T item );
|
||||
|
||||
@Override
|
||||
public void provideDetails( @Nonnull Map<? super String, Object> data, @Nonnull ItemStack stack )
|
||||
{
|
||||
Item item = stack.getItem();
|
||||
if( !itemType.isInstance( item ) ) return;
|
||||
|
||||
// If `namespace` is specified, insert into a new data map instead of the existing one.
|
||||
Map<? super String, Object> child = namespace == null ? data : new HashMap<>();
|
||||
|
||||
provideDetails( child, stack, itemType.cast( item ) );
|
||||
|
||||
if( namespace != null )
|
||||
{
|
||||
data.put( namespace, child );
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.detail;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A reference to a block in the world, used by block detail providers.
|
||||
*
|
||||
* @param level The level the block exists in.
|
||||
* @param pos The position of the block.
|
||||
* @param state The block state at this position.
|
||||
* @param blockEntity The block entity at this position, if it exists.
|
||||
*/
|
||||
public record BlockReference(
|
||||
@Nonnull Level level,
|
||||
@Nonnull BlockPos pos,
|
||||
@Nonnull BlockState state,
|
||||
@Nullable BlockEntity blockEntity
|
||||
)
|
||||
{
|
||||
public BlockReference( Level level, BlockPos pos )
|
||||
{
|
||||
this( level, pos, level.getBlockState( pos ), level.getBlockEntity( pos ) );
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.detail;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This interface is used to provide details about a block, fluid, or item.
|
||||
*
|
||||
* @param <T> The type of object that this provider can provide details for.
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerDetailProvider(Class, IDetailProvider)
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IDetailProvider<T>
|
||||
{
|
||||
/**
|
||||
* Provide additional details for the given object. This method is called by functions such as
|
||||
* {@code turtle.getItemDetail()} and {@code turtle.inspect()}. New properties should be added to the given
|
||||
* {@link Map}, {@code data}.
|
||||
*
|
||||
* This method is always called on the server thread, so it is safe to interact with the world here, but you should
|
||||
* take care to avoid long blocking operations as this will stall the server and other computers.
|
||||
*
|
||||
* @param data The full details to be returned. New properties should be added to this map.
|
||||
* @param object The object to provide details for.
|
||||
*/
|
||||
void provideDetails( @Nonnull Map<? super String, Object> data, @Nonnull T object );
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.filesystem;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.filesystem;
|
||||
|