mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-11-17 15:24:52 +00:00
Merge branch 'mc-1.16.x' into mc-1.18.x
This commit is contained in:
commit
08895cdecc
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,8 +1,5 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: ComputerCraft Discord
|
|
||||||
url: https://discord.computercraft.cc
|
|
||||||
about: Get help on the ComputerCraft Discord.
|
|
||||||
- name: GitHub Discussions
|
- name: GitHub Discussions
|
||||||
url: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
url: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
about: Or ask questions on GitHub Discussions.
|
about: Ask questions on GitHub Discussions.
|
||||||
|
27
.github/workflows/main-ci.yml
vendored
27
.github/workflows/main-ci.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
java-version: 8
|
java-version: 8
|
||||||
|
|
||||||
- name: Cache gradle dependencies
|
- name: Cache Gradle dependencies
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: ~/.gradle/caches
|
path: ~/.gradle/caches
|
||||||
@ -32,7 +32,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
./gradlew assemble || ./gradlew assemble
|
./gradlew assemble || ./gradlew assemble
|
||||||
./gradlew downloadAssets || ./gradlew downloadAssets
|
./gradlew downloadAssets || ./gradlew downloadAssets
|
||||||
xvfb-run ./gradlew build
|
./gradlew build
|
||||||
|
|
||||||
- name: Upload Jar
|
- name: Upload Jar
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
@ -40,31 +40,12 @@ jobs:
|
|||||||
name: CC-Tweaked
|
name: CC-Tweaked
|
||||||
path: build/libs
|
path: build/libs
|
||||||
|
|
||||||
- name: Upload Screnshots
|
- name: Upload coverage
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: Screenshots
|
|
||||||
path: test-files/client/screenshots
|
|
||||||
if-no-files-found: ignore
|
|
||||||
retention-days: 5
|
|
||||||
if: failure()
|
|
||||||
|
|
||||||
- name: Upload Coverage
|
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v2
|
||||||
|
|
||||||
- name: Parse test reports
|
- name: Parse test reports
|
||||||
run: ./tools/parse-reports.py
|
run: ./tools/parse-reports.py
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
|
||||||
- name: Cache pre-commit
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.cache/pre-commit
|
|
||||||
key: ${{ runner.os }}-pre-commit-${{ hashFiles('config/pre-commit/config.yml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pre-commit-
|
|
||||||
|
|
||||||
- name: Run linters
|
- name: Run linters
|
||||||
run: |
|
uses: pre-commit/action@v3.0.0
|
||||||
pip install pre-commit
|
|
||||||
pre-commit run --config config/pre-commit/config.yml --show-diff-on-failure --all --color=always
|
|
||||||
|
6
.github/workflows/make-doc.yml
vendored
6
.github/workflows/make-doc.yml
vendored
@ -26,12 +26,6 @@ jobs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-gradle-
|
${{ runner.os }}-gradle-
|
||||||
|
|
||||||
- name: Setup illuaminate
|
|
||||||
run: |
|
|
||||||
test -d bin || mkdir bin
|
|
||||||
test -f bin/illuaminate || wget -q -Obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
|
|
||||||
chmod +x bin/illuaminate
|
|
||||||
|
|
||||||
- name: Setup node
|
- name: Setup node
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,6 +2,7 @@
|
|||||||
/classes
|
/classes
|
||||||
/logs
|
/logs
|
||||||
/build
|
/build
|
||||||
|
/buildSrc/build
|
||||||
/out
|
/out
|
||||||
/doc/out/
|
/doc/out/
|
||||||
/node_modules
|
/node_modules
|
||||||
|
@ -17,6 +17,6 @@ vscode:
|
|||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Setup pre-commit hool
|
- name: Setup pre-commit hool
|
||||||
init: pre-commit install --config config/pre-commit/config.yml --allow-missing-config
|
init: pre-commit install --allow-missing-config
|
||||||
- name: Install npm packages
|
- name: Install npm packages
|
||||||
init: npm ci
|
init: npm ci
|
||||||
|
@ -41,8 +41,8 @@ repos:
|
|||||||
- id: illuaminate
|
- id: illuaminate
|
||||||
name: Check Lua code
|
name: Check Lua code
|
||||||
files: ".*\\.(lua|java|md)"
|
files: ".*\\.(lua|java|md)"
|
||||||
language: script
|
language: system
|
||||||
entry: config/pre-commit/illuaminate-lint.sh
|
entry: ./gradlew lintLua -i
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
require_serial: true
|
require_serial: true
|
||||||
|
|
@ -39,40 +39,30 @@ are run whenever you submit a PR, it's often useful to run this before committin
|
|||||||
|
|
||||||
- **[Checkstyle]:** Checks Java code to ensure it is consistently formatted. This can be run with `./gradlew build` or
|
- **[Checkstyle]:** Checks Java code to ensure it is consistently formatted. This can be run with `./gradlew build` or
|
||||||
`./gradle check`.
|
`./gradle check`.
|
||||||
- **[illuaminate]:** Checks Lua code for semantic and styleistic issues. See [the usage section][illuaminate-usage] for
|
- **[illuaminate]:** Checks Lua code for semantic and styleistic issues. This can be run with `./gradlew lintLua`.
|
||||||
how to download and run it. You may need to generate the Java documentation stubs (see "Documentation" below) for all
|
|
||||||
lints to pass.
|
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
When writing documentation for [CC: Tweaked's documentation website][docs], it may be useful to build the documentation
|
When writing documentation for [CC: Tweaked's documentation website][docs], it may be useful to build the documentation
|
||||||
and preview it yourself before submitting a PR.
|
and preview it yourself before submitting a PR.
|
||||||
|
|
||||||
Building all documentation is, sadly, a multi-stage process (though this is largely hidden by Gradle). First we need to
|
Our documentation generation pipeline is rather complex, and involves invoking several external tools. Most of this
|
||||||
convert Java doc-comments into Lua ones, we also generate some Javascript to embed. All of this is then finally fed into
|
complexity is hidden by Gradle, but you will need to perform some initial setup:
|
||||||
illuaminate, which spits out our HTML.
|
|
||||||
|
|
||||||
#### Setting up the tooling
|
- Install [Node/npm][node].
|
||||||
For various reasons, getting the environment set up to build documentation can be pretty complex. I'd quite like to
|
- Run `npm ci` to install our Node dependencies.
|
||||||
automate this via Docker and/or nix in the future, but this needs to be done manually for now.
|
|
||||||
|
|
||||||
This tooling is only needed if you need to build the whole website. If you just want to generate the Lua stubs, you can
|
You can now run `./gradlew docWebsite`. This generates documentation from our Lua and Java code, writing the resulting
|
||||||
skp this section.
|
HTML into `./build/docs/site`.
|
||||||
- Install Node/npm and install our Node packages with `npm ci`.
|
|
||||||
- Install [illuaminate][illuaminate-usage] as described above.
|
|
||||||
|
|
||||||
#### Building documentation
|
|
||||||
Gradle should be your entrypoint to building most documentation. There's two tasks which are of interest:
|
|
||||||
|
|
||||||
- `./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/site/`.
|
|
||||||
|
|
||||||
#### Writing documentation
|
#### Writing documentation
|
||||||
illuaminate's documentation system is not currently documented (somewhat ironic), but is _largely_ the same as
|
illuaminate's documentation system is not currently documented (somewhat ironic), but is _largely_ the same as
|
||||||
[ldoc][ldoc]. Documentation comments are written in Markdown,
|
[ldoc][ldoc]. Documentation comments are written in Markdown,
|
||||||
|
|
||||||
Our markdown engine does _not_ support GitHub flavoured markdown, and so does not support all the features one might
|
Our markdown engine does _not_ support GitHub flavoured markdown, and so does not support all the features one might
|
||||||
expect (such as tables). It is very much recommended that you build and preview the docs locally first.
|
expect. It is recommended that you build and preview the docs locally first.
|
||||||
|
|
||||||
|
When iterating on documentation, you can get Gradle to rebuild the website every time a file changes by running
|
||||||
|
`./gradlew docWebsite -t`. This will take a couple of seconds to run, but definitely beats running it manually!
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
Thankfully running tests is much simpler than running the documentation generator! `./gradlew check` will run the
|
Thankfully running tests is much simpler than running the documentation generator! `./gradlew check` will run the
|
||||||
@ -90,11 +80,10 @@ Before we get into writing tests, it's worth mentioning the various test suites
|
|||||||
|
|
||||||
These tests are run by the '"Core" Java' test suite, and so are also run with `./gradlew test`.
|
These tests are run by the '"Core" Java' test suite, and so are also run with `./gradlew test`.
|
||||||
|
|
||||||
- In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server and client,
|
- In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
|
||||||
using [the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
|
the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
|
||||||
|
|
||||||
These are run by `./gradlew testClient` and `./gradlew testServer`. You may want to run the client under `xvfb-run`
|
These tests are run with `./gradlew testServer`.
|
||||||
or similar when running in a headless environment.
|
|
||||||
|
|
||||||
## CraftOS tests
|
## CraftOS tests
|
||||||
CraftOS's tests are written using a test system called "mcfly", heavily inspired by [busted] (and thus RSpec). Groups of
|
CraftOS's tests are written using a test system called "mcfly", heavily inspired by [busted] (and thus RSpec). Groups of
|
||||||
@ -107,9 +96,9 @@ asserts that your variable `foo` is equal to the expected value `"bar"`.
|
|||||||
[community]: README.md#Community "Get in touch with the community."
|
[community]: README.md#Community "Get in touch with the community."
|
||||||
[checkstyle]: https://checkstyle.org/
|
[checkstyle]: https://checkstyle.org/
|
||||||
[illuaminate]: https://github.com/SquidDev/illuaminate/ "Illuaminate on GitHub"
|
[illuaminate]: https://github.com/SquidDev/illuaminate/ "Illuaminate on GitHub"
|
||||||
[illuaminate-usage]: https://github.com/SquidDev/illuaminate/blob/master/README.md#usage "Installing Illuaminate"
|
|
||||||
[weblate]: https://i18n.tweaked.cc/projects/cc-tweaked/minecraft/ "CC: Tweaked weblate instance"
|
[weblate]: https://i18n.tweaked.cc/projects/cc-tweaked/minecraft/ "CC: Tweaked weblate instance"
|
||||||
[docs]: https://tweaked.cc/ "CC: Tweaked documentation"
|
[docs]: https://tweaked.cc/ "CC: Tweaked documentation"
|
||||||
[ldoc]: http://stevedonovan.github.io/ldoc/ "ldoc, a Lua documentation generator."
|
[ldoc]: http://stevedonovan.github.io/ldoc/ "ldoc, a Lua documentation generator."
|
||||||
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg
|
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg
|
||||||
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
|
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
|
||||||
|
[node]: https://nodejs.org/en/ "Node.js"
|
||||||
|
@ -13,9 +13,8 @@ developing the mod, [check out the instructions here](CONTRIBUTING.md#developing
|
|||||||
|
|
||||||
## Community
|
## Community
|
||||||
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
||||||
ComputerCraft we have a [forum](https://forums.computercraft.cc/) and [Discord guild](https://discord.computercraft.cc)!
|
ComputerCraft, do check out our [forum] and [GitHub discussions page][GitHub discussions]! There's also a fairly
|
||||||
There's also a fairly populated, albeit quiet [IRC channel](http://webchat.esper.net/?channels=computercraft), if that's
|
populated, albeit quiet [IRC channel][irc], if that's more your cup of tea.
|
||||||
more your cup of tea.
|
|
||||||
|
|
||||||
We also host fairly comprehensive documentation at [tweaked.cc](https://tweaked.cc/ "The CC: Tweaked website").
|
We also host fairly comprehensive documentation at [tweaked.cc](https://tweaked.cc/ "The CC: Tweaked website").
|
||||||
|
|
||||||
@ -52,3 +51,6 @@ the generated documentation [can be browsed online](https://tweaked.cc/javadoc/)
|
|||||||
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
||||||
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
[ccrestitched]: https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched from CurseForge"
|
[ccrestitched]: https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched from CurseForge"
|
||||||
|
[forum]: https://forums.computercraft.cc/
|
||||||
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
|
[IRC]: http://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
||||||
|
46
build.gradle
46
build.gradle
@ -11,9 +11,12 @@ plugins {
|
|||||||
id "org.spongepowered.mixin" version "0.7.+"
|
id "org.spongepowered.mixin" version "0.7.+"
|
||||||
id "org.parchmentmc.librarian.forgegradle" version "1.+"
|
id "org.parchmentmc.librarian.forgegradle" version "1.+"
|
||||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
id "com.github.johnrengelman.shadow" version "7.1.2"
|
||||||
|
id "cc-tweaked.illuaminate"
|
||||||
}
|
}
|
||||||
|
|
||||||
import org.apache.tools.ant.taskdefs.condition.Os
|
import org.apache.tools.ant.taskdefs.condition.Os
|
||||||
|
import cc.tweaked.gradle.IlluaminateExec
|
||||||
|
import cc.tweaked.gradle.IlluaminateExecToDir
|
||||||
|
|
||||||
version = mod_version
|
version = mod_version
|
||||||
|
|
||||||
@ -169,6 +172,10 @@ dependencies {
|
|||||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.7'
|
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.7'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
illuaminate {
|
||||||
|
version.set("0.1.0-3-g0f40379")
|
||||||
|
}
|
||||||
|
|
||||||
// Compile tasks
|
// Compile tasks
|
||||||
|
|
||||||
javadoc {
|
javadoc {
|
||||||
@ -314,32 +321,36 @@ def rollup = tasks.register("rollup", Exec.class) {
|
|||||||
commandLine mkCommand('"node_modules/.bin/rollup" --config rollup.config.js')
|
commandLine mkCommand('"node_modules/.bin/rollup" --config rollup.config.js')
|
||||||
}
|
}
|
||||||
|
|
||||||
def illuaminateDocs = tasks.register("illuaminateDocs", Exec.class) {
|
def illuaminateDocs = tasks.register("illuaminateDocs", IlluaminateExecToDir.class) {
|
||||||
group = "documentation"
|
group = "documentation"
|
||||||
description = "Generates docs using Illuaminate"
|
description = "Generates docs using Illuaminate"
|
||||||
dependsOn(rollup, luaJavadoc)
|
dependsOn(rollup)
|
||||||
|
|
||||||
inputs.files(fileTree("doc")).withPropertyName("docs")
|
// Config files
|
||||||
inputs.files(fileTree("src/main/resources/data/computercraft/lua/rom")).withPropertyName("lua rom")
|
|
||||||
inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
|
inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
|
||||||
inputs.dir("$buildDir/docs/luaJavadoc")
|
// Sources
|
||||||
|
inputs.files(fileTree("doc")).withPropertyName("docs")
|
||||||
|
inputs.files(fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom")
|
||||||
|
inputs.files(luaJavadoc)
|
||||||
|
// Additional assets
|
||||||
inputs.file("$buildDir/rollup/index.js").withPropertyName("scripts")
|
inputs.file("$buildDir/rollup/index.js").withPropertyName("scripts")
|
||||||
inputs.file("src/web/styles.css").withPropertyName("styles")
|
inputs.file("src/web/styles.css").withPropertyName("styles")
|
||||||
outputs.dir("$buildDir/docs/lua")
|
|
||||||
|
|
||||||
commandLine mkCommand('"bin/illuaminate" doc-gen')
|
// Output directory. Also defined in illuaminate.sexp and transform.tsx
|
||||||
|
output.set(new File(buildDir, "docs/lua"))
|
||||||
|
|
||||||
|
args = ["doc-gen"]
|
||||||
}
|
}
|
||||||
|
|
||||||
def jsxDocs = tasks.register("jsxDocs", Exec) {
|
def jsxDocs = tasks.register("jsxDocs", Exec) {
|
||||||
group = "documentation"
|
group = "documentation"
|
||||||
description = "Post-processes documentation to statically render some dynamic content."
|
description = "Post-processes documentation to statically render some dynamic content."
|
||||||
dependsOn(illuaminateDocs)
|
|
||||||
|
|
||||||
inputs.files(fileTree("src/web")).withPropertyName("sources")
|
inputs.files(fileTree("src/web")).withPropertyName("sources")
|
||||||
inputs.file("src/generated/export/index.json").withPropertyName("export")
|
inputs.file("src/generated/export/index.json").withPropertyName("export")
|
||||||
inputs.file("package-lock.json").withPropertyName("package-lock.json")
|
inputs.file("package-lock.json").withPropertyName("package-lock.json")
|
||||||
inputs.file("tsconfig.json").withPropertyName("Typescript config")
|
inputs.file("tsconfig.json").withPropertyName("Typescript config")
|
||||||
inputs.files(fileTree("$buildDir/docs/lua"))
|
inputs.files(illuaminateDocs)
|
||||||
outputs.dir("$buildDir/docs/site")
|
outputs.dir("$buildDir/docs/site")
|
||||||
|
|
||||||
commandLine mkCommand('"node_modules/.bin/ts-node" -T --esm src/web/transform.tsx')
|
commandLine mkCommand('"node_modules/.bin/ts-node" -T --esm src/web/transform.tsx')
|
||||||
@ -403,6 +414,23 @@ license {
|
|||||||
|
|
||||||
check.dependsOn("licenseCheck")
|
check.dependsOn("licenseCheck")
|
||||||
|
|
||||||
|
def lintLua = tasks.register("lintLua", IlluaminateExec.class) {
|
||||||
|
group = JavaBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Lint Lua (and Lua docs) with illuaminate"
|
||||||
|
|
||||||
|
// Config files
|
||||||
|
inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
|
||||||
|
// Sources
|
||||||
|
inputs.files(fileTree("doc")).withPropertyName("docs")
|
||||||
|
inputs.files(fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom")
|
||||||
|
inputs.files(luaJavadoc)
|
||||||
|
|
||||||
|
args = ["lint"]
|
||||||
|
|
||||||
|
doFirst { if (System.getenv("GITHUB_ACTIONS") != null) println("::add-matcher::.github/matchers/illuaminate.json") }
|
||||||
|
doLast { if (System.getenv("GITHUB_ACTIONS") != null) println("::remove-matcher owner=illuaminate::") }
|
||||||
|
}
|
||||||
|
|
||||||
def testServerClassDumpDir = new File(buildDir, "jacocoClassDump/runTestServer")
|
def testServerClassDumpDir = new File(buildDir, "jacocoClassDump/runTestServer")
|
||||||
|
|
||||||
def testServer = tasks.register("testServer", JavaExec.class) {
|
def testServer = tasks.register("testServer", JavaExec.class) {
|
||||||
|
18
buildSrc/build.gradle.kts
Normal file
18
buildSrc/build.gradle.kts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
plugins {
|
||||||
|
`java-gradle-plugin`
|
||||||
|
`kotlin-dsl`
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
|
||||||
|
gradlePlugin {
|
||||||
|
plugins {
|
||||||
|
register("cc-tweaked.illuaminate") {
|
||||||
|
id = "cc-tweaked.illuaminate"
|
||||||
|
implementationClass = "cc.tweaked.gradle.IlluaminatePlugin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
buildSrc/src/main/kotlin/cc/tweaked/gradle/ExecTasks.kt
Normal file
11
buildSrc/src/main/kotlin/cc/tweaked/gradle/ExecTasks.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.AbstractExecTask
|
||||||
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class ExecToDir : AbstractExecTask<ExecToDir>(ExecToDir::class.java) {
|
||||||
|
@get:OutputDirectory
|
||||||
|
abstract val output: Property<File>
|
||||||
|
}
|
121
buildSrc/src/main/kotlin/cc/tweaked/gradle/Illuaminate.kt
Normal file
121
buildSrc/src/main/kotlin/cc/tweaked/gradle/Illuaminate.kt
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.artifacts.Dependency
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.AbstractExecTask
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class IlluaminateExtension {
|
||||||
|
/** The version of illuaminate to use. */
|
||||||
|
abstract val version: Property<String>
|
||||||
|
|
||||||
|
/** The path to illuaminate. If not given, illuaminate will be downloaded automatically. */
|
||||||
|
abstract val file: Property<File>
|
||||||
|
}
|
||||||
|
|
||||||
|
class IlluaminatePlugin : Plugin<Project> {
|
||||||
|
override fun apply(project: Project) {
|
||||||
|
val extension = project.extensions.create("illuaminate", IlluaminateExtension::class.java)
|
||||||
|
extension.file.convention(setupDependency(project, extension.version))
|
||||||
|
|
||||||
|
project.tasks.register(SetupIlluaminate.NAME, SetupIlluaminate::class.java) {
|
||||||
|
file.set(extension.file.map { it.absolutePath })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set up a repository for illuaminate and download our binary from it. */
|
||||||
|
private fun setupDependency(project: Project, version: Provider<String>): Provider<File> {
|
||||||
|
project.repositories.ivy {
|
||||||
|
name = "Illuaminate"
|
||||||
|
setUrl("https://squiddev.cc/illuaminate/bin/")
|
||||||
|
patternLayout {
|
||||||
|
artifact("[revision]/[artifact]-[ext]")
|
||||||
|
}
|
||||||
|
metadataSources {
|
||||||
|
artifact()
|
||||||
|
}
|
||||||
|
content {
|
||||||
|
includeModule("cc.squiddev", "illuaminate")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return version.map {
|
||||||
|
val dep = illuaminateArtifact(project, it)
|
||||||
|
val configuration = project.configurations.detachedConfiguration(dep)
|
||||||
|
configuration.isTransitive = false
|
||||||
|
configuration.resolve().single()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Define a dependency for illuaminate from a version number and the current operating system. */
|
||||||
|
private fun illuaminateArtifact(project: Project, version: String): Dependency {
|
||||||
|
val osName = System.getProperty("os.name").toLowerCase()
|
||||||
|
val (os, suffix) = when {
|
||||||
|
osName.contains("windows") -> Pair("windows", ".exe")
|
||||||
|
osName.contains("mac os") || osName.contains("darwin") -> Pair("macos", "")
|
||||||
|
osName.contains("linux") -> Pair("linux", "")
|
||||||
|
else -> error("Unsupported OS $osName for illuaminate")
|
||||||
|
}
|
||||||
|
|
||||||
|
val osArch = System.getProperty("os.arch").toLowerCase()
|
||||||
|
val arch = when {
|
||||||
|
osArch == "arm" || osArch.startsWith("aarch") -> error("Unsupported architecture '$osArch' for illuaminate")
|
||||||
|
osArch.contains("64") -> "x86_64"
|
||||||
|
else -> error("Unsupported architecture $osArch for illuaminate")
|
||||||
|
}
|
||||||
|
|
||||||
|
return project.dependencies.create(
|
||||||
|
mapOf(
|
||||||
|
"group" to "cc.squiddev",
|
||||||
|
"name" to "illuaminate",
|
||||||
|
"version" to version,
|
||||||
|
"ext" to "$os-$arch$suffix",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val Task.illuaminatePath: String? // "?" needed to avoid overload ambiguity in setExecutable below.
|
||||||
|
get() = project.extensions.getByType(IlluaminateExtension::class.java).file.get().absolutePath
|
||||||
|
|
||||||
|
/** Prepares illuaminate for being run. This simply requests the dependency and then marks it as executable. */
|
||||||
|
abstract class SetupIlluaminate : DefaultTask() {
|
||||||
|
@get:Input
|
||||||
|
abstract val file: Property<String>
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun setExecutable() {
|
||||||
|
val file = File(this.file.get())
|
||||||
|
if (file.canExecute()) {
|
||||||
|
didWork = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file.setExecutable(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val NAME: String = "setupIlluaminate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class IlluaminateExec : AbstractExecTask<IlluaminateExec>(IlluaminateExec::class.java) {
|
||||||
|
init {
|
||||||
|
dependsOn(SetupIlluaminate.NAME)
|
||||||
|
executable = illuaminatePath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class IlluaminateExecToDir : ExecToDir() {
|
||||||
|
init {
|
||||||
|
dependsOn(SetupIlluaminate.NAME)
|
||||||
|
executable = illuaminatePath
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
test -d bin || mkdir bin
|
|
||||||
test -f bin/illuaminate || curl -s -obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
|
|
||||||
chmod +x bin/illuaminate
|
|
||||||
|
|
||||||
if [ -n ${GITHUB_ACTIONS+x} ]; then
|
|
||||||
# Register a problem matcher (see https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md)
|
|
||||||
# for illuaminate.
|
|
||||||
echo "::add-matcher::.github/matchers/illuaminate.json"
|
|
||||||
trap 'echo "::remove-matcher owner=illuaminate::"' EXIT
|
|
||||||
fi
|
|
||||||
|
|
||||||
./gradlew luaJavadoc
|
|
||||||
bin/illuaminate lint
|
|
@ -185,7 +185,7 @@ end
|
|||||||
|
|
||||||
:::note Confused?
|
:::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
|
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!
|
cover. That said, don't be afraid to ask on [GitHub Discussions] or [IRC] either!
|
||||||
:::
|
:::
|
||||||
|
|
||||||
It's worth noting that the examples of audio processing we've mentioned here are about manipulating the _amplitude_ of
|
It's worth noting that the examples of audio processing we've mentioned here are about manipulating the _amplitude_ of
|
||||||
@ -200,6 +200,5 @@ This is, I'm afraid, left as an exercise to the reader.
|
|||||||
[PCM]: https://en.wikipedia.org/wiki/Pulse-code_modulation "Pulse-code Modulation - 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"
|
[Ring Buffer]: https://en.wikipedia.org/wiki/Circular_buffer "Circular buffer - Wikipedia"
|
||||||
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
|
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
|
||||||
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
[Discord]: https://discord.computercraft.cc "The Minecraft Computer Mods Discord"
|
[IRC]: http://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
||||||
[IRC]: http://webchat.esper.net/?channels=computercraft "IRC webchat on EsperNet"
|
|
||||||
|
@ -37,8 +37,7 @@ little daunting getting started. Thankfully, there's several fantastic tutorials
|
|||||||
Once you're a little more familiar with the mod, the sidebar and links below provide more detailed documentation on the
|
Once you're a little more familiar with the mod, the sidebar and links below provide more detailed documentation on the
|
||||||
various APIs and peripherals provided by the mod.
|
various APIs and peripherals provided by the mod.
|
||||||
|
|
||||||
If you get stuck, do pop in to the [Minecraft Computer Mod Discord guild][discord] or ComputerCraft's
|
If you get stuck, do [ask a question on GitHub][GitHub Discussions] or pop in to the ComputerCraft's [IRC channel][IRC].
|
||||||
[IRC channel][irc].
|
|
||||||
|
|
||||||
## Get Involved
|
## Get Involved
|
||||||
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
||||||
@ -51,5 +50,5 @@ CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please
|
|||||||
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
[ccrestitched]: https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched from CurseForge"
|
[ccrestitched]: https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched from CurseForge"
|
||||||
[lua]: https://www.lua.org/ "Lua's main website"
|
[lua]: https://www.lua.org/ "Lua's main website"
|
||||||
[discord]: https://discord.computercraft.cc "The Minecraft Computer Mods Discord"
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
[irc]: http://webchat.esper.net/?channels=computercraft "IRC webchat on EsperNet"
|
[IRC]: http://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
||||||
|
@ -14,7 +14,7 @@ thread, not the whole program.
|
|||||||
|
|
||||||
:::tip
|
:::tip
|
||||||
Because sleep internally uses timers, it is a function that yields. This means
|
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
|
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.
|
the minimum sleep time is 0.05 seconds, it will slow your program down.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx3G
|
|||||||
kotlin.stdlib.default.dependency=false
|
kotlin.stdlib.default.dependency=false
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
mod_version=1.100.9
|
mod_version=1.100.10
|
||||||
|
|
||||||
# Minecraft properties (update mods.toml when changing)
|
# Minecraft properties (update mods.toml when changing)
|
||||||
mc_version=1.18.2
|
mc_version=1.18.2
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -24,7 +24,7 @@ final class LuaDateTime
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void format( DateTimeFormatterBuilder formatter, String format, ZoneOffset offset ) throws LuaException
|
static void format( DateTimeFormatterBuilder formatter, String format ) throws LuaException
|
||||||
{
|
{
|
||||||
for( int i = 0; i < format.length(); )
|
for( int i = 0; i < format.length(); )
|
||||||
{
|
{
|
||||||
@ -61,7 +61,7 @@ final class LuaDateTime
|
|||||||
formatter.appendText( ChronoField.MONTH_OF_YEAR, TextStyle.FULL );
|
formatter.appendText( ChronoField.MONTH_OF_YEAR, TextStyle.FULL );
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
format( formatter, "%a %b %e %H:%M:%S %Y", offset );
|
format( formatter, "%a %b %e %H:%M:%S %Y" );
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
formatter.appendValueReduced( CENTURY, 2, 2, 0 );
|
formatter.appendValueReduced( CENTURY, 2, 2, 0 );
|
||||||
@ -71,13 +71,13 @@ final class LuaDateTime
|
|||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
case 'x':
|
case 'x':
|
||||||
format( formatter, "%m/%d/%y", offset );
|
format( formatter, "%m/%d/%y" );
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
formatter.padNext( 2 ).appendValue( ChronoField.DAY_OF_MONTH );
|
formatter.padNext( 2 ).appendValue( ChronoField.DAY_OF_MONTH );
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
format( formatter, "%Y-%m-%d", offset );
|
format( formatter, "%Y-%m-%d" );
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
formatter.appendValueReduced( IsoFields.WEEK_BASED_YEAR, 2, 2, 0 );
|
formatter.appendValueReduced( IsoFields.WEEK_BASED_YEAR, 2, 2, 0 );
|
||||||
@ -107,10 +107,10 @@ final class LuaDateTime
|
|||||||
formatter.appendText( ChronoField.AMPM_OF_DAY );
|
formatter.appendText( ChronoField.AMPM_OF_DAY );
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
format( formatter, "%I:%M:%S %p", offset );
|
format( formatter, "%I:%M:%S %p" );
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
format( formatter, "%H:%M", offset );
|
format( formatter, "%H:%M" );
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
formatter.appendValue( ChronoField.SECOND_OF_MINUTE, 2 );
|
formatter.appendValue( ChronoField.SECOND_OF_MINUTE, 2 );
|
||||||
@ -120,7 +120,7 @@ final class LuaDateTime
|
|||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
case 'X':
|
case 'X':
|
||||||
format( formatter, "%H:%M:%S", offset );
|
format( formatter, "%H:%M:%S" );
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
formatter.appendValue( ChronoField.DAY_OF_WEEK );
|
formatter.appendValue( ChronoField.DAY_OF_WEEK );
|
||||||
@ -212,15 +212,13 @@ final class LuaDateTime
|
|||||||
throw new LuaException( "field \"" + field + "\" missing in date table" );
|
throw new LuaException( "field \"" + field + "\" missing in date table" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final TemporalField CENTURY = map( ChronoField.YEAR, ValueRange.of( 0, 6 ), x -> (x / 100) % 100 );
|
private static final TemporalField CENTURY = map( ChronoField.YEAR, ValueRange.of( 0, 99 ), x -> (x / 100) % 100 );
|
||||||
private static final TemporalField ZERO_WEEK = map( WeekFields.SUNDAY_START.dayOfWeek(), ValueRange.of( 0, 6 ), x -> x - 1 );
|
private static final TemporalField ZERO_WEEK = map( WeekFields.SUNDAY_START.dayOfWeek(), ValueRange.of( 0, 6 ), x -> x - 1 );
|
||||||
|
|
||||||
private static TemporalField map( TemporalField field, ValueRange range, LongUnaryOperator convert )
|
private static TemporalField map( TemporalField field, ValueRange range, LongUnaryOperator convert )
|
||||||
{
|
{
|
||||||
return new TemporalField()
|
return new TemporalField()
|
||||||
{
|
{
|
||||||
private final ValueRange range = ValueRange.of( 0, 99 );
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TemporalUnit getBaseUnit()
|
public TemporalUnit getBaseUnit()
|
||||||
{
|
{
|
||||||
|
@ -493,7 +493,7 @@ public class OSAPI implements ILuaAPI
|
|||||||
if( format.equals( "*t" ) ) return LuaDateTime.toTable( date, offset, instant );
|
if( format.equals( "*t" ) ) return LuaDateTime.toTable( date, offset, instant );
|
||||||
|
|
||||||
DateTimeFormatterBuilder formatter = new DateTimeFormatterBuilder();
|
DateTimeFormatterBuilder formatter = new DateTimeFormatterBuilder();
|
||||||
LuaDateTime.format( formatter, format, offset );
|
LuaDateTime.format( formatter, format );
|
||||||
return formatter.toFormatter( Locale.ROOT ).format( date );
|
return formatter.toFormatter( Locale.ROOT ).format( date );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,8 +323,9 @@ public class TurtleBrain implements ITurtleAccess
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Create a new turtle
|
// We use Block.UPDATE_CLIENTS here to ensure that neighbour updates caused in Block.updateNeighbourShapes
|
||||||
if( world.setBlock( pos, newState, 0 ) )
|
// are sent to the client. We want to avoid doing a full block update until the turtle state is copied over.
|
||||||
|
if( world.setBlock( pos, newState, 2 ) )
|
||||||
{
|
{
|
||||||
Block block = world.getBlockState( pos ).getBlock();
|
Block block = world.getBlockState( pos ).getBlock();
|
||||||
if( block == oldBlock.getBlock() )
|
if( block == oldBlock.getBlock() )
|
||||||
|
@ -259,7 +259,7 @@ input should the whole output not fit on the display.
|
|||||||
local rows = {}
|
local rows = {}
|
||||||
for i = 1, 30 do rows[i] = {("Row #%d"):format(i), math.random(1, 400)} end
|
for i = 1, 30 do rows[i] = {("Row #%d"):format(i), math.random(1, 400)} end
|
||||||
|
|
||||||
textutils.tabulate(colors.orange, {"Column", "Value"}, colors.lightBlue, table.unpack(rows))
|
textutils.pagedTabulate(colors.orange, {"Column", "Value"}, colors.lightBlue, table.unpack(rows))
|
||||||
]]
|
]]
|
||||||
function pagedTabulate(...)
|
function pagedTabulate(...)
|
||||||
return tabulateCommon(true, ...)
|
return tabulateCommon(true, ...)
|
||||||
@ -749,9 +749,9 @@ suitable for pretty printing.
|
|||||||
@usage Demonstrates some of the other options
|
@usage Demonstrates some of the other options
|
||||||
|
|
||||||
local tbl = { 1, 2, 3 }
|
local tbl = { 1, 2, 3 }
|
||||||
print(textutils.serialize({ tbl, tbl }, { allow_repetitions = true }))
|
print(textutils.serialise({ tbl, tbl }, { allow_repetitions = true }))
|
||||||
|
|
||||||
print(textutils.serialize(tbl, { compact = true }))
|
print(textutils.serialise(tbl, { compact = true }))
|
||||||
]]
|
]]
|
||||||
function serialize(t, opts)
|
function serialize(t, opts)
|
||||||
local tTracking = {}
|
local tTracking = {}
|
||||||
@ -770,7 +770,7 @@ serialise = serialize -- GB version
|
|||||||
|
|
||||||
--- Converts a serialised string back into a reassembled Lua object.
|
--- Converts a serialised string back into a reassembled Lua object.
|
||||||
--
|
--
|
||||||
-- This is mainly used together with @{textutils.serialize}.
|
-- This is mainly used together with @{textutils.serialise}.
|
||||||
--
|
--
|
||||||
-- @tparam string s The serialised string to deserialise.
|
-- @tparam string s The serialised string to deserialise.
|
||||||
-- @return[1] The deserialised object
|
-- @return[1] The deserialised object
|
||||||
@ -807,10 +807,10 @@ unserialise = unserialize -- GB version
|
|||||||
-- @throws If the object contains a value which cannot be
|
-- @throws If the object contains a value which cannot be
|
||||||
-- serialised. This includes functions and tables which appear multiple
|
-- serialised. This includes functions and tables which appear multiple
|
||||||
-- times.
|
-- times.
|
||||||
-- @usage textutils.serializeJSON({ values = { 1, "2", true } })
|
-- @usage textutils.serialiseJSON({ values = { 1, "2", true } })
|
||||||
-- @since 1.7
|
-- @since 1.7
|
||||||
-- @see textutils.json_null Use to serialize a JSON `null` value.
|
-- @see textutils.json_null Use to serialise a JSON `null` value.
|
||||||
-- @see textutils.empty_json_array Use to serialize a JSON empty array.
|
-- @see textutils.empty_json_array Use to serialise a JSON empty array.
|
||||||
function serializeJSON(t, bNBTStyle)
|
function serializeJSON(t, bNBTStyle)
|
||||||
expect(1, t, "table", "string", "number", "boolean")
|
expect(1, t, "table", "string", "number", "boolean")
|
||||||
expect(2, bNBTStyle, "boolean", "nil")
|
expect(2, bNBTStyle, "boolean", "nil")
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
|
# New features in CC: Tweaked 1.100.10
|
||||||
|
|
||||||
|
* Mention WAV support in speaker help (MCJack123).
|
||||||
|
* Add http programs to the path, even when http is not enabled.
|
||||||
|
|
||||||
|
Several bug fixes:
|
||||||
|
* Fix example in textutils.pagedTabulate docs (IvoLeal72).
|
||||||
|
* Fix help program treating the terminal one line longer than it was.
|
||||||
|
* Send block updates to client when turtle moves (roland-a).
|
||||||
|
* Resolve several monitor issues when running Occulus shaders.
|
||||||
|
|
||||||
# New features in CC: Tweaked 1.100.9
|
# New features in CC: Tweaked 1.100.9
|
||||||
|
|
||||||
* Add documentation for setting up GPS (Lupus590).
|
* Add documentation for setting up GPS (Lupus590).
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
The speaker program plays audio files using speakers attached to this computer.
|
The speaker program plays audio files using speakers attached to this computer.
|
||||||
|
|
||||||
|
It supports audio files in a limited number of formats:
|
||||||
|
* DFPWM: You can convert music to DFPWM with external tools like https://music.madefor.cc.
|
||||||
|
* WAV: WAV files must be 8-bit PCM or DFPWM, with exactly one channel and a sample rate of 48kHz.
|
||||||
|
|
||||||
## Examples:
|
## Examples:
|
||||||
- `speaker play example.dfpwm left` plays the "example.dfpwm" audio file using the speaker on the left of the computer.
|
* `speaker play example.dfpwm left` plays the "example.dfpwm" audio file using the speaker on the left of the computer.
|
||||||
- `speaker stop` stops any currently playing audio.
|
* `speaker stop` stops any currently playing audio.
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
New features in CC: Tweaked 1.100.9
|
New features in CC: Tweaked 1.100.10
|
||||||
|
|
||||||
* Add documentation for setting up GPS (Lupus590).
|
* Mention WAV support in speaker help (MCJack123).
|
||||||
* Add WAV support to the `speaker` program (MCJack123).
|
* Add http programs to the path, even when http is not enabled.
|
||||||
* Expose item groups in `getItemDetail` (itisluiz).
|
|
||||||
* Other fixes to documentation (Erb3, JohnnyIrvin).
|
|
||||||
* Add Norwegian translation (Erb3).
|
|
||||||
|
|
||||||
Several bug fixes:
|
Several bug fixes:
|
||||||
* Fix z-fighting on bold printout borders (toad-dev).
|
* Fix example in textutils.pagedTabulate docs (IvoLeal72).
|
||||||
* Fix `term.blit` failing on certain strings.
|
* Fix help program treating the terminal one line longer than it was.
|
||||||
* Fix `getItemLimit()` using the wrong slot (heap-underflow).
|
* Send block updates to client when turtle moves (roland-a).
|
||||||
* Increase size of monitor depth blocker.
|
* Resolve several monitor issues when running Occulus shaders.
|
||||||
|
|
||||||
Type "help changelog" to see the full version history.
|
Type "help changelog" to see the full version history.
|
||||||
|
@ -146,14 +146,17 @@ end
|
|||||||
|
|
||||||
local contents = file:read("*a")
|
local contents = file:read("*a")
|
||||||
file:close()
|
file:close()
|
||||||
|
-- Trim trailing newlines from the file to avoid displaying a blank line.
|
||||||
|
if contents:sub(-1) == "\n" then contents:sub(1, -2) end
|
||||||
|
|
||||||
local word_wrap = sFile:sub(-3) == ".md" and word_wrap_markdown or word_wrap_basic
|
local word_wrap = sFile:sub(-3) == ".md" and word_wrap_markdown or word_wrap_basic
|
||||||
local width, height = term.getSize()
|
local width, height = term.getSize()
|
||||||
|
local content_height = height - 1 -- Height of the content box.
|
||||||
local lines, fg, bg, sections = word_wrap(contents, width)
|
local lines, fg, bg, sections = word_wrap(contents, width)
|
||||||
local print_height = #lines
|
local print_height = #lines
|
||||||
|
|
||||||
-- If we fit within the screen, just display without pagination.
|
-- If we fit within the screen, just display without pagination.
|
||||||
if print_height <= height then
|
if print_height <= content_height then
|
||||||
local _, y = term.getCursorPos()
|
local _, y = term.getCursorPos()
|
||||||
for i = 1, print_height do
|
for i = 1, print_height do
|
||||||
if y + i - 1 > height then
|
if y + i - 1 > height then
|
||||||
@ -201,7 +204,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
local function draw()
|
local function draw()
|
||||||
for y = 1, height - 1 do
|
for y = 1, content_height do
|
||||||
term.setCursorPos(1, y)
|
term.setCursorPos(1, y)
|
||||||
if y + offset > print_height then
|
if y + offset > print_height then
|
||||||
-- Should only happen if we resize the terminal to a larger one
|
-- Should only happen if we resize the terminal to a larger one
|
||||||
@ -228,14 +231,14 @@ while true do
|
|||||||
if param == keys.up and offset > 0 then
|
if param == keys.up and offset > 0 then
|
||||||
offset = offset - 1
|
offset = offset - 1
|
||||||
draw()
|
draw()
|
||||||
elseif param == keys.down and offset < print_height - height then
|
elseif param == keys.down and offset < print_height - content_height then
|
||||||
offset = offset + 1
|
offset = offset + 1
|
||||||
draw()
|
draw()
|
||||||
elseif param == keys.pageUp and offset > 0 then
|
elseif param == keys.pageUp and offset > 0 then
|
||||||
offset = math.max(offset - height + 2, 0)
|
offset = math.max(offset - content_height + 1, 0)
|
||||||
draw()
|
draw()
|
||||||
elseif param == keys.pageDown and offset < print_height - height then
|
elseif param == keys.pageDown and offset < print_height - content_height then
|
||||||
offset = math.min(offset + height - 2, print_height - height)
|
offset = math.min(offset + content_height - 1, print_height - content_height)
|
||||||
draw()
|
draw()
|
||||||
elseif param == keys.home then
|
elseif param == keys.home then
|
||||||
offset = 0
|
offset = 0
|
||||||
@ -247,7 +250,7 @@ while true do
|
|||||||
offset = sections[current_section + 1].offset
|
offset = sections[current_section + 1].offset
|
||||||
draw()
|
draw()
|
||||||
elseif param == keys["end"] then
|
elseif param == keys["end"] then
|
||||||
offset = print_height - height
|
offset = print_height - content_height
|
||||||
draw()
|
draw()
|
||||||
elseif param == keys.q then
|
elseif param == keys.q then
|
||||||
sleep(0) -- Super janky, but consumes stray "char" events.
|
sleep(0) -- Super janky, but consumes stray "char" events.
|
||||||
@ -257,7 +260,7 @@ while true do
|
|||||||
if param < 0 and offset > 0 then
|
if param < 0 and offset > 0 then
|
||||||
offset = offset - 1
|
offset = offset - 1
|
||||||
draw()
|
draw()
|
||||||
elseif param > 0 and offset < print_height - height then
|
elseif param > 0 and offset <= print_height - content_height then
|
||||||
offset = offset + 1
|
offset = offset + 1
|
||||||
draw()
|
draw()
|
||||||
end
|
end
|
||||||
@ -270,7 +273,8 @@ while true do
|
|||||||
end
|
end
|
||||||
|
|
||||||
width, height = new_width, new_height
|
width, height = new_width, new_height
|
||||||
offset = math.max(math.min(offset, print_height - height), 0)
|
content_height = height - 1
|
||||||
|
offset = math.max(math.min(offset, print_height - content_height), 0)
|
||||||
draw()
|
draw()
|
||||||
draw_menu()
|
draw_menu()
|
||||||
elseif event == "terminate" then
|
elseif event == "terminate" then
|
||||||
|
@ -13,8 +13,8 @@ if #tArgs < 2 then
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not http then
|
if not http then
|
||||||
printError("Pastebin requires the http API")
|
printError("Pastebin requires the http API, but it is not enabled")
|
||||||
printError("Set http.enabled to true in CC: Tweaked's config")
|
printError("Set http.enabled to true in CC: Tweaked's server config")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ end
|
|||||||
local url = table.remove(tArgs, 1)
|
local url = table.remove(tArgs, 1)
|
||||||
|
|
||||||
if not http then
|
if not http then
|
||||||
printError("wget requires the http API")
|
printError("wget requires the http API, but it is not enabled")
|
||||||
printError("Set http.enabled to true in CC: Tweaked's config")
|
printError("Set http.enabled to true in CC: Tweaked's server config")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
local completion = require "cc.shell.completion"
|
local completion = require "cc.shell.completion"
|
||||||
|
|
||||||
-- Setup paths
|
-- Setup paths
|
||||||
local sPath = ".:/rom/programs"
|
local sPath = ".:/rom/programs:/rom/programs/http"
|
||||||
if term.isColor() then
|
if term.isColor() then
|
||||||
sPath = sPath .. ":/rom/programs/advanced"
|
sPath = sPath .. ":/rom/programs/advanced"
|
||||||
end
|
end
|
||||||
@ -19,9 +19,6 @@ end
|
|||||||
if commands then
|
if commands then
|
||||||
sPath = sPath .. ":/rom/programs/command"
|
sPath = sPath .. ":/rom/programs/command"
|
||||||
end
|
end
|
||||||
if http then
|
|
||||||
sPath = sPath .. ":/rom/programs/http"
|
|
||||||
end
|
|
||||||
shell.setPath(sPath)
|
shell.setPath(sPath)
|
||||||
help.setPath("/rom/help")
|
help.setPath("/rom/help")
|
||||||
|
|
||||||
|
@ -1,8 +1,46 @@
|
|||||||
local capture = require "test_helpers".capture_program
|
local capture = require "test_helpers".capture_program
|
||||||
|
local with_window_lines = require "test_helpers".with_window_lines
|
||||||
|
|
||||||
describe("The help program", function()
|
describe("The help program", function()
|
||||||
|
local function stub_help(content)
|
||||||
|
local name = "/help_file.txt"
|
||||||
|
io.open(name, "wb"):write(content):close()
|
||||||
|
stub(help, "lookup", function() return name end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function capture_help(width, height, content)
|
||||||
|
stub_help(content)
|
||||||
|
|
||||||
|
local co = coroutine.create(shell.run)
|
||||||
|
local window = with_window_lines(width, height, function()
|
||||||
|
local ok, err = coroutine.resume(co, "help topic")
|
||||||
|
if not ok then error(err, 0) end
|
||||||
|
end)
|
||||||
|
return coroutine.status(co) == "dead", window
|
||||||
|
end
|
||||||
|
|
||||||
it("errors when there is no such help file", function()
|
it("errors when there is no such help file", function()
|
||||||
expect(capture(stub, "help nothing"))
|
expect(capture(stub, "help nothing"))
|
||||||
:matches { ok = true, error = "No help available\n", output = "" }
|
:matches { ok = true, error = "No help available\n", output = "" }
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("prints a short file directly", function()
|
||||||
|
local dead, output = capture_help(10, 3, "a short\nfile")
|
||||||
|
expect(dead):eq(true)
|
||||||
|
expect(output):same {
|
||||||
|
"a short ",
|
||||||
|
"file ",
|
||||||
|
" ",
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("launches the viewer for a longer file", function()
|
||||||
|
local dead, output = capture_help(10, 3, "a longer\nfile\nwith content")
|
||||||
|
expect(dead):eq(false)
|
||||||
|
expect(output):same {
|
||||||
|
"a longer ",
|
||||||
|
"file ",
|
||||||
|
"Help: topi",
|
||||||
|
}
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -56,7 +56,22 @@ local function with_window(width, height, fn)
|
|||||||
return redirect
|
return redirect
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Run a function redirecting to a new window with the given dimensions,
|
||||||
|
-- returning the content of the window.
|
||||||
|
--
|
||||||
|
-- @tparam number width The window's width
|
||||||
|
-- @tparam number height The window's height
|
||||||
|
-- @tparam function() fn The action to run
|
||||||
|
-- @treturn {string...} The content of the window.
|
||||||
|
local function with_window_lines(width, height, fn)
|
||||||
|
local window = with_window(width, height, fn)
|
||||||
|
local out = {}
|
||||||
|
for i = 1, height do out[i] = window.getLine(i) end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
capture_program = capture_program,
|
capture_program = capture_program,
|
||||||
with_window = with_window,
|
with_window = with_window,
|
||||||
|
with_window_lines = with_window_lines,
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
:root {
|
||||||
|
--nav-width: 250px;
|
||||||
|
}
|
||||||
/* Some misc styles */
|
/* Some misc styles */
|
||||||
|
|
||||||
.big-image {
|
.big-image {
|
||||||
|
Loading…
Reference in New Issue
Block a user