mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-16 14:37:39 +00:00
Compare commits
89 Commits
v1.19.4-1.
...
v1.20.1-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bcb3e9bd53 | ||
![]() |
c30bffbd0f | ||
![]() |
91c41856c5 | ||
![]() |
18c9723308 | ||
![]() |
aee382ed70 | ||
![]() |
6656da5877 | ||
![]() |
09e521727f | ||
![]() |
cab66a2d6e | ||
![]() |
8eabd4f303 | ||
![]() |
e3ced84885 | ||
![]() |
0929ab577d | ||
![]() |
2228733abc | ||
![]() |
e67c94d1bd | ||
![]() |
ae5a661a47 | ||
![]() |
0ff58cdc3e | ||
![]() |
1747c74770 | ||
![]() |
71669cf49c | ||
![]() |
bd327e37eb | ||
![]() |
bdce9a8170 | ||
![]() |
7e5598d084 | ||
![]() |
440fca6535 | ||
![]() |
6635edd35c | ||
![]() |
93ad40efbb | ||
![]() |
27dc8b5b2c | ||
![]() |
3ebdf7ef5e | ||
![]() |
905d4cb091 | ||
![]() |
e7ab05d064 | ||
![]() |
6ec34b42e5 | ||
![]() |
ab785a0906 | ||
![]() |
4541decd40 | ||
![]() |
747a5a53b4 | ||
![]() |
c0643fadca | ||
![]() |
0a31de43c2 | ||
![]() |
96b6947ef2 | ||
![]() |
e7a1065bfc | ||
![]() |
663eecff0c | ||
![]() |
e6125bcf60 | ||
![]() |
0d6c6e7ae7 | ||
![]() |
ae71eb3cae | ||
![]() |
3188197447 | ||
![]() |
6c8b391dab | ||
![]() |
b1248e4901 | ||
![]() |
56d97630e8 | ||
![]() |
e660192f08 | ||
![]() |
4e82bd352d | ||
![]() |
07113c3e9b | ||
![]() |
d562a051c7 | ||
![]() |
6ac09742fc | ||
![]() |
5dd6b9a637 | ||
![]() |
8fb1dd346c | ||
![]() |
cdc8592aa3 | ||
![]() |
0f6ea3deaf | ||
![]() |
13ed422bd5 | ||
![]() |
5b58271b92 | ||
![]() |
4e42394f33 | ||
![]() |
53546b9f57 | ||
![]() |
6dfdeb9321 | ||
![]() |
500406f9eb | ||
![]() |
b3738a7a63 | ||
![]() |
5f8b1dd67f | ||
![]() |
053751b190 | ||
![]() |
52b78f92cd | ||
![]() |
2055052a57 | ||
![]() |
12ee47ff19 | ||
![]() |
25776abf61 | ||
![]() |
f7411b40a2 | ||
![]() |
8c8924f54e | ||
![]() |
c1628d077a | ||
![]() |
5b2fdec6ca | ||
![]() |
5a7259e4c9 | ||
![]() |
92b335f45f | ||
![]() |
b93ea9c62e | ||
![]() |
b9edd7c7f6 | ||
![]() |
84a761ddd5 | ||
![]() |
3371c4651c | ||
![]() |
e6bc1e4e27 | ||
![]() |
ae50f900af | ||
![]() |
48889ceb89 | ||
![]() |
8f1bf4341c | ||
![]() |
9a48b53a83 | ||
![]() |
9519448e43 | ||
![]() |
915b6f9d81 | ||
![]() |
a98f3b2a4c | ||
![]() |
ebaf49508f | ||
![]() |
c45fc94752 | ||
![]() |
fd1f6dda32 | ||
![]() |
5d6389dc50 | ||
![]() |
1ece2aa23b | ||
![]() |
ff1e5f6823 |
@@ -6,7 +6,7 @@
|
|||||||
# See https://pre-commit.com/hooks.html for more hooks
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.0.1
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
@@ -20,14 +20,14 @@ repos:
|
|||||||
exclude: "tsconfig\\.json$"
|
exclude: "tsconfig\\.json$"
|
||||||
|
|
||||||
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
||||||
rev: 2.3.54
|
rev: 2.7.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: editorconfig-checker
|
- id: editorconfig-checker
|
||||||
args: ['-disable-indentation']
|
args: ['-disable-indentation']
|
||||||
exclude: "^(.*\\.(bat)|LICENSE)$"
|
exclude: "^(.*\\.(bat)|LICENSE)$"
|
||||||
|
|
||||||
- repo: https://github.com/fsfe/reuse-tool
|
- repo: https://github.com/fsfe/reuse-tool
|
||||||
rev: v1.1.0
|
rev: v2.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: reuse
|
- id: reuse
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ repos:
|
|||||||
name: Check Java codestyle
|
name: Check Java codestyle
|
||||||
files: ".*\\.java$"
|
files: ".*\\.java$"
|
||||||
language: system
|
language: system
|
||||||
entry: ./gradlew checkstyleMain checkstyleTest
|
entry: ./gradlew checkstyle
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
require_serial: true
|
require_serial: true
|
||||||
- id: illuaminate
|
- id: illuaminate
|
||||||
|
29
.reuse/dep5
29
.reuse/dep5
@@ -10,8 +10,8 @@ Files:
|
|||||||
projects/common/src/testMod/resources/data/cctest/structures/*
|
projects/common/src/testMod/resources/data/cctest/structures/*
|
||||||
projects/fabric/src/generated/*
|
projects/fabric/src/generated/*
|
||||||
projects/forge/src/generated/*
|
projects/forge/src/generated/*
|
||||||
projects/web/src/export/index.json
|
projects/web/src/htmlTransform/export/index.json
|
||||||
projects/web/src/export/items/minecraft/*
|
projects/web/src/htmlTransform/export/items/minecraft/*
|
||||||
Comment: Generated/data files are CC0.
|
Comment: Generated/data files are CC0.
|
||||||
Copyright: The CC: Tweaked Developers
|
Copyright: The CC: Tweaked Developers
|
||||||
License: CC0-1.0
|
License: CC0-1.0
|
||||||
@@ -37,10 +37,10 @@ Files:
|
|||||||
projects/fabric/src/testMod/resources/computercraft-gametest.fabric.mixins.json
|
projects/fabric/src/testMod/resources/computercraft-gametest.fabric.mixins.json
|
||||||
projects/fabric/src/testMod/resources/fabric.mod.json
|
projects/fabric/src/testMod/resources/fabric.mod.json
|
||||||
projects/forge/src/client/resources/computercraft-client.forge.mixins.json
|
projects/forge/src/client/resources/computercraft-client.forge.mixins.json
|
||||||
projects/web/src/mount/.settings
|
projects/web/src/frontend/mount/.settings
|
||||||
projects/web/src/mount/example.nfp
|
projects/web/src/frontend/mount/example.nfp
|
||||||
projects/web/src/mount/example.nft
|
projects/web/src/frontend/mount/example.nft
|
||||||
projects/web/src/mount/expr_template.lua
|
projects/web/src/frontend/mount/expr_template.lua
|
||||||
projects/web/tsconfig.json
|
projects/web/tsconfig.json
|
||||||
Comment: Several assets where it's inconvenient to create a .license file.
|
Comment: Several assets where it's inconvenient to create a .license file.
|
||||||
Copyright: The CC: Tweaked Developers
|
Copyright: The CC: Tweaked Developers
|
||||||
@@ -53,19 +53,32 @@ Files:
|
|||||||
projects/common/src/main/resources/assets/computercraft/textures/*
|
projects/common/src/main/resources/assets/computercraft/textures/*
|
||||||
projects/common/src/main/resources/pack.mcmeta
|
projects/common/src/main/resources/pack.mcmeta
|
||||||
projects/common/src/main/resources/pack.png
|
projects/common/src/main/resources/pack.png
|
||||||
|
projects/core/src/main/resources/assets/computercraft/textures/gui/term_font.png
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/autorun/.ignoreme
|
projects/core/src/main/resources/data/computercraft/lua/rom/autorun/.ignoreme
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/help/*
|
projects/core/src/main/resources/data/computercraft/lua/rom/help/*
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/programs/fun/advanced/levels/*
|
projects/core/src/main/resources/data/computercraft/lua/rom/programs/fun/advanced/levels/*
|
||||||
projects/web/src/export/items/computercraft/*
|
projects/web/src/htmlTransform/export/items/computercraft/*
|
||||||
Comment: Bulk-license original assets as CCPL.
|
Comment: Bulk-license original assets as CCPL.
|
||||||
Copyright: 2011 Daniel Ratcliffe
|
Copyright: 2011 Daniel Ratcliffe
|
||||||
License: LicenseRef-CCPL
|
License: LicenseRef-CCPL
|
||||||
|
|
||||||
|
Files:
|
||||||
|
projects/common/src/main/resources/assets/computercraft/lang/cs_cz.json
|
||||||
|
projects/common/src/main/resources/assets/computercraft/lang/ko_kr.json
|
||||||
|
projects/common/src/main/resources/assets/computercraft/lang/pl_pl.json
|
||||||
|
projects/common/src/main/resources/assets/computercraft/lang/pt_br.json
|
||||||
|
projects/common/src/main/resources/assets/computercraft/lang/ru_ru.json
|
||||||
|
projects/common/src/main/resources/assets/computercraft/lang/uk_ua.json
|
||||||
|
projects/common/src/main/resources/assets/computercraft/lang/zh_cn.json
|
||||||
|
Comment: Community-contributed license files
|
||||||
|
Copyright: 2017 The CC: Tweaked Developers
|
||||||
|
License: LicenseRef-CCPL
|
||||||
|
|
||||||
Files:
|
Files:
|
||||||
projects/common/src/main/resources/assets/computercraft/lang/*
|
projects/common/src/main/resources/assets/computercraft/lang/*
|
||||||
Comment: Community-contributed license files
|
Comment: Community-contributed license files
|
||||||
Copyright: 2017 The CC: Tweaked Developers
|
Copyright: 2017 The CC: Tweaked Developers
|
||||||
License: LicenseRef-CCPL
|
License: MPL-2.0
|
||||||
|
|
||||||
Files:
|
Files:
|
||||||
.github/*
|
.github/*
|
||||||
|
@@ -100,7 +100,6 @@ about how you can build on that until you've covered everything!
|
|||||||
[new-issue]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose "Create a new issue"
|
[new-issue]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose "Create a new issue"
|
||||||
[community]: README.md#community "Get in touch with the community."
|
[community]: README.md#community "Get in touch with the community."
|
||||||
[Adoptium]: https://adoptium.net/temurin/releases?version=17 "Download OpenJDK 17"
|
[Adoptium]: https://adoptium.net/temurin/releases?version=17 "Download OpenJDK 17"
|
||||||
[checkstyle]: https://checkstyle.org/
|
|
||||||
[illuaminate]: https://github.com/SquidDev/illuaminate/ "Illuaminate on GitHub"
|
[illuaminate]: https://github.com/SquidDev/illuaminate/ "Illuaminate on GitHub"
|
||||||
[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"
|
||||||
|
@@ -2,7 +2,11 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
import cc.tweaked.gradle.JUnitExt
|
||||||
|
import net.fabricmc.loom.api.LoomGradleExtensionAPI
|
||||||
|
import net.fabricmc.loom.util.gradle.SourceSetHelper
|
||||||
import org.jetbrains.gradle.ext.compiler
|
import org.jetbrains.gradle.ext.compiler
|
||||||
|
import org.jetbrains.gradle.ext.runConfigurations
|
||||||
import org.jetbrains.gradle.ext.settings
|
import org.jetbrains.gradle.ext.settings
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -38,6 +42,50 @@ githubRelease {
|
|||||||
|
|
||||||
tasks.publish { dependsOn(tasks.githubRelease) }
|
tasks.publish { dependsOn(tasks.githubRelease) }
|
||||||
|
|
||||||
|
idea.project.settings.runConfigurations {
|
||||||
|
register<JUnitExt>("Core Tests") {
|
||||||
|
vmParameters = "-ea"
|
||||||
|
moduleName = "${idea.project.name}.core.test"
|
||||||
|
packageName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("CraftOS Tests") {
|
||||||
|
vmParameters = "-ea"
|
||||||
|
moduleName = "${idea.project.name}.core.test"
|
||||||
|
className = "dan200.computercraft.core.ComputerTestDelegate"
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("CraftOS Tests (Fast)") {
|
||||||
|
vmParameters = "-ea -Dcc.skip_keywords=slow"
|
||||||
|
moduleName = "${idea.project.name}.core.test"
|
||||||
|
className = "dan200.computercraft.core.ComputerTestDelegate"
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("Common Tests") {
|
||||||
|
vmParameters = "-ea"
|
||||||
|
moduleName = "${idea.project.name}.common.test"
|
||||||
|
packageName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("Fabric Tests") {
|
||||||
|
val fabricProject = evaluationDependsOn(":fabric")
|
||||||
|
val classPathGroup = fabricProject.extensions.getByType<LoomGradleExtensionAPI>().mods
|
||||||
|
.joinToString(File.pathSeparator + File.pathSeparator) { modSettings ->
|
||||||
|
SourceSetHelper.getClasspath(modSettings, project).joinToString(File.pathSeparator) { it.absolutePath }
|
||||||
|
}
|
||||||
|
|
||||||
|
vmParameters = "-ea -Dfabric.classPathGroups=$classPathGroup"
|
||||||
|
moduleName = "${idea.project.name}.fabric.test"
|
||||||
|
packageName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("Forge Tests") {
|
||||||
|
vmParameters = "-ea"
|
||||||
|
moduleName = "${idea.project.name}.forge.test"
|
||||||
|
packageName = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
idea.project.settings.compiler.javac {
|
idea.project.settings.compiler.javac {
|
||||||
// We want ErrorProne to be present when compiling via IntelliJ, as it offers some helpful warnings
|
// We want ErrorProne to be present when compiling via IntelliJ, as it offers some helpful warnings
|
||||||
// and errors. Loop through our source sets and find the appropriate flags.
|
// and errors. Loop through our source sets and find the appropriate flags.
|
||||||
|
@@ -50,10 +50,11 @@ dependencies {
|
|||||||
implementation(libs.curseForgeGradle)
|
implementation(libs.curseForgeGradle)
|
||||||
implementation(libs.fabric.loom)
|
implementation(libs.fabric.loom)
|
||||||
implementation(libs.forgeGradle)
|
implementation(libs.forgeGradle)
|
||||||
|
implementation(libs.ideaExt)
|
||||||
implementation(libs.librarian)
|
implementation(libs.librarian)
|
||||||
implementation(libs.minotaur)
|
implementation(libs.minotaur)
|
||||||
implementation(libs.quiltflower)
|
|
||||||
implementation(libs.vanillaGradle)
|
implementation(libs.vanillaGradle)
|
||||||
|
implementation(libs.vineflower)
|
||||||
}
|
}
|
||||||
|
|
||||||
gradlePlugin {
|
gradlePlugin {
|
||||||
|
@@ -12,7 +12,7 @@ import cc.tweaked.gradle.MinecraftConfigurations
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
id("fabric-loom")
|
id("fabric-loom")
|
||||||
id("io.github.juuxel.loom-quiltflower")
|
id("io.github.juuxel.loom-vineflower")
|
||||||
id("cc-tweaked.java-convention")
|
id("cc-tweaked.java-convention")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,13 +59,16 @@ repositories {
|
|||||||
includeGroup("cc.tweaked")
|
includeGroup("cc.tweaked")
|
||||||
includeModule("org.squiddev", "Cobalt")
|
includeModule("org.squiddev", "Cobalt")
|
||||||
// Things we mirror
|
// Things we mirror
|
||||||
|
includeGroup("commoble.morered")
|
||||||
includeGroup("dev.architectury")
|
includeGroup("dev.architectury")
|
||||||
includeGroup("dev.emi")
|
includeGroup("dev.emi")
|
||||||
includeGroup("maven.modrinth")
|
includeGroup("maven.modrinth")
|
||||||
includeGroup("me.shedaniel.cloth")
|
includeGroup("me.shedaniel.cloth")
|
||||||
includeGroup("me.shedaniel")
|
includeGroup("me.shedaniel")
|
||||||
includeGroup("mezz.jei")
|
includeGroup("mezz.jei")
|
||||||
|
includeGroup("org.teavm")
|
||||||
includeModule("com.terraformersmc", "modmenu")
|
includeModule("com.terraformersmc", "modmenu")
|
||||||
|
includeModule("me.lucko", "fabric-permissions-api")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,7 +100,10 @@ sourceSets.all {
|
|||||||
check("FutureReturnValueIgnored", CheckSeverity.OFF) // Too many false positives with Netty
|
check("FutureReturnValueIgnored", CheckSeverity.OFF) // Too many false positives with Netty
|
||||||
|
|
||||||
check("NullAway", CheckSeverity.ERROR)
|
check("NullAway", CheckSeverity.ERROR)
|
||||||
option("NullAway:AnnotatedPackages", listOf("dan200.computercraft", "net.fabricmc.fabric.api").joinToString(","))
|
option(
|
||||||
|
"NullAway:AnnotatedPackages",
|
||||||
|
listOf("dan200.computercraft", "cc.tweaked", "net.fabricmc.fabric.api").joinToString(","),
|
||||||
|
)
|
||||||
option("NullAway:ExcludedFieldAnnotations", listOf("org.spongepowered.asm.mixin.Shadow").joinToString(","))
|
option("NullAway:ExcludedFieldAnnotations", listOf("org.spongepowered.asm.mixin.Shadow").joinToString(","))
|
||||||
option("NullAway:CastToNonNullMethod", "dan200.computercraft.core.util.Nullability.assertNonNull")
|
option("NullAway:CastToNonNullMethod", "dan200.computercraft.core.util.Nullability.assertNonNull")
|
||||||
option("NullAway:CheckOptionalEmptiness")
|
option("NullAway:CheckOptionalEmptiness")
|
||||||
@@ -172,6 +178,12 @@ project.plugins.withType(CCTweakedPlugin::class.java) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.register("checkstyle") {
|
||||||
|
description = "Run Checkstyle on all sources"
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
dependsOn(tasks.withType(Checkstyle::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
spotless {
|
spotless {
|
||||||
encoding = StandardCharsets.UTF_8
|
encoding = StandardCharsets.UTF_8
|
||||||
lineEndings = LineEnding.UNIX
|
lineEndings = LineEnding.UNIX
|
||||||
@@ -189,6 +201,7 @@ spotless {
|
|||||||
|
|
||||||
val ktlintConfig = mapOf(
|
val ktlintConfig = mapOf(
|
||||||
"ktlint_standard_no-wildcard-imports" to "disabled",
|
"ktlint_standard_no-wildcard-imports" to "disabled",
|
||||||
|
"ktlint_standard_class-naming" to "disabled",
|
||||||
"ij_kotlin_allow_trailing_comma" to "true",
|
"ij_kotlin_allow_trailing_comma" to "true",
|
||||||
"ij_kotlin_allow_trailing_comma_on_call_site" to "true",
|
"ij_kotlin_allow_trailing_comma_on_call_site" to "true",
|
||||||
)
|
)
|
||||||
|
@@ -173,7 +173,7 @@ abstract class CCTweakedExtension(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <T> jacoco(task: NamedDomainObjectProvider<T>) where T : Task, T : JavaForkOptions {
|
fun <T> jacoco(task: NamedDomainObjectProvider<T>) where T : Task, T : JavaForkOptions {
|
||||||
val classDump = project.buildDir.resolve("jacocoClassDump/${task.name}")
|
val classDump = project.layout.buildDirectory.dir("jacocoClassDump/${task.name}")
|
||||||
val reportTaskName = "jacoco${task.name.capitalized()}Report"
|
val reportTaskName = "jacoco${task.name.capitalized()}Report"
|
||||||
|
|
||||||
val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
|
val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
|
||||||
@@ -185,7 +185,7 @@ abstract class CCTweakedExtension(
|
|||||||
jacoco.applyTo(this)
|
jacoco.applyTo(this)
|
||||||
extensions.configure(JacocoTaskExtension::class.java) {
|
extensions.configure(JacocoTaskExtension::class.java) {
|
||||||
includes = listOf("dan200.computercraft.*")
|
includes = listOf("dan200.computercraft.*")
|
||||||
classDumpDir = classDump
|
classDumpDir = classDump.get().asFile
|
||||||
|
|
||||||
// Older versions of modlauncher don't include a protection domain (and thus no code
|
// 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.
|
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
||||||
|
@@ -9,6 +9,10 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.api.plugins.JavaPlugin
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||||
|
import org.gradle.plugins.ide.idea.model.IdeaModel
|
||||||
|
import org.jetbrains.gradle.ext.IdeaExtPlugin
|
||||||
|
import org.jetbrains.gradle.ext.runConfigurations
|
||||||
|
import org.jetbrains.gradle.ext.settings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures projects to match a shared configuration.
|
* Configures projects to match a shared configuration.
|
||||||
@@ -21,6 +25,20 @@ class CCTweakedPlugin : Plugin<Project> {
|
|||||||
val sourceSets = project.extensions.getByType(JavaPluginExtension::class.java).sourceSets
|
val sourceSets = project.extensions.getByType(JavaPluginExtension::class.java).sourceSets
|
||||||
cct.sourceDirectories.add(SourceSetReference.internal(sourceSets.getByName("main")))
|
cct.sourceDirectories.add(SourceSetReference.internal(sourceSets.getByName("main")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project.plugins.withType(IdeaExtPlugin::class.java) { extendIdea(project) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend the [IdeaExtPlugin] plugin's `runConfiguration` container to also support [JUnitExt].
|
||||||
|
*/
|
||||||
|
private fun extendIdea(project: Project) {
|
||||||
|
val ideaModel = project.extensions.findByName("idea") as IdeaModel? ?: return
|
||||||
|
val ideaProject = ideaModel.project ?: return
|
||||||
|
|
||||||
|
ideaProject.settings.runConfigurations {
|
||||||
|
registerFactory(JUnitExt::class.java) { name -> project.objects.newInstance(JUnitExt::class.java, name) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.tasks.AbstractExecTask
|
import org.gradle.api.tasks.AbstractExecTask
|
||||||
import org.gradle.api.tasks.OutputDirectory
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
@@ -11,5 +12,5 @@ import java.io.File
|
|||||||
|
|
||||||
abstract class ExecToDir : AbstractExecTask<ExecToDir>(ExecToDir::class.java) {
|
abstract class ExecToDir : AbstractExecTask<ExecToDir>(ExecToDir::class.java) {
|
||||||
@get:OutputDirectory
|
@get:OutputDirectory
|
||||||
abstract val output: Property<File>
|
abstract val output: DirectoryProperty
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||||
|
import org.gradle.api.file.FileSystemLocation
|
||||||
|
import org.gradle.api.file.FileSystemLocationProperty
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.JavaExec
|
import org.gradle.api.tasks.JavaExec
|
||||||
@@ -124,3 +126,6 @@ class CloseScope : AutoCloseable {
|
|||||||
|
|
||||||
/** Proxy method to avoid overload ambiguity. */
|
/** Proxy method to avoid overload ambiguity. */
|
||||||
fun <T> Property<T>.setProvider(provider: Provider<out T>) = set(provider)
|
fun <T> Property<T>.setProvider(provider: Provider<out T>) = set(provider)
|
||||||
|
|
||||||
|
/** Short-cut method to get the absolute path of a [FileSystemLocation] provider. */
|
||||||
|
fun Provider<out FileSystemLocation>.getAbsolutePath(): String = get().asFile.absolutePath
|
||||||
|
23
buildSrc/src/main/kotlin/cc/tweaked/gradle/IdeaExt.kt
Normal file
23
buildSrc/src/main/kotlin/cc/tweaked/gradle/IdeaExt.kt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.jetbrains.gradle.ext.JUnit
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A version of [JUnit] with a functional [className].
|
||||||
|
*
|
||||||
|
* See [#92](https://github.com/JetBrains/gradle-idea-ext-plugin/issues/92).
|
||||||
|
*/
|
||||||
|
open class JUnitExt @Inject constructor(nameParam: String) : JUnit(nameParam) {
|
||||||
|
override fun toMap(): MutableMap<String, *> {
|
||||||
|
val map = HashMap(super.toMap())
|
||||||
|
// Should be "class" instead of "className".
|
||||||
|
// See https://github.com/JetBrains/intellij-community/blob/9ba394021dc73a3926f13d6d6cdf434f9ee7046d/plugins/junit/src/com/intellij/execution/junit/JUnitRunConfigurationImporter.kt#L39
|
||||||
|
map["class"] = className
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
}
|
@@ -58,7 +58,7 @@ abstract class ClientJavaExec : JavaExec() {
|
|||||||
if (!clientDebug) systemProperty("cctest.client", "")
|
if (!clientDebug) systemProperty("cctest.client", "")
|
||||||
if (renderdoc) environment("LD_PRELOAD", "/usr/lib/librenderdoc.so")
|
if (renderdoc) environment("LD_PRELOAD", "/usr/lib/librenderdoc.so")
|
||||||
systemProperty("cctest.gametest-report", testResults.get().asFile.absoluteFile)
|
systemProperty("cctest.gametest-report", testResults.get().asFile.absoluteFile)
|
||||||
workingDir(project.buildDir.resolve("gametest").resolve(name))
|
workingDir(project.layout.buildDirectory.dir("gametest/$name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@@ -112,7 +112,9 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
<module name="LambdaParameterName" />
|
<module name="LambdaParameterName" />
|
||||||
<module name="LocalFinalVariableName" />
|
<module name="LocalFinalVariableName" />
|
||||||
<module name="LocalVariableName" />
|
<module name="LocalVariableName" />
|
||||||
<module name="MemberName" />
|
<module name="MemberName">
|
||||||
|
<property name="format" value="^\$?[a-z][a-zA-Z0-9]*$" />
|
||||||
|
</module>
|
||||||
<module name="MethodName">
|
<module name="MethodName">
|
||||||
<property name="format" value="^(computercraft\$)?[a-z][a-zA-Z0-9]*$" />
|
<property name="format" value="^(computercraft\$)?[a-z][a-zA-Z0-9]*$" />
|
||||||
</module>
|
</module>
|
||||||
@@ -122,7 +124,7 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
</module>
|
</module>
|
||||||
<module name="ParameterName" />
|
<module name="ParameterName" />
|
||||||
<module name="StaticVariableName">
|
<module name="StaticVariableName">
|
||||||
<property name="format" value="^[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z_]+)?$" />
|
<property name="format" value="^[a-z][a-zA-Z0-9]*$" />
|
||||||
</module>
|
</module>
|
||||||
<module name="TypeName" />
|
<module name="TypeName" />
|
||||||
|
|
||||||
|
@@ -16,4 +16,10 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
|
|
||||||
<!-- The commands API is documented in Lua. -->
|
<!-- The commands API is documented in Lua. -->
|
||||||
<suppress checks="SummaryJavadocCheck" files=".*[\\/]CommandAPI.java" />
|
<suppress checks="SummaryJavadocCheck" files=".*[\\/]CommandAPI.java" />
|
||||||
|
|
||||||
|
<!-- Allow putting files in other packages if they look like our TeaVM stubs. -->
|
||||||
|
<suppress checks="PackageName" files=".*[\\/]T[A-Za-z]+.java" />
|
||||||
|
|
||||||
|
<!-- Allow underscores in our test classes. -->
|
||||||
|
<suppress checks="MethodName" files=".*Contract.java" />
|
||||||
</suppressions>
|
</suppressions>
|
||||||
|
@@ -9,11 +9,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{alarm} event is fired when an alarm started with @{os.setAlarm} completes.
|
The [`alarm`] event is fired when an alarm started with [`os.setAlarm`] completes.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The ID of the alarm that finished.
|
2. [`number`]: The ID of the alarm that finished.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Starts a timer and then waits for it to complete.
|
Starts a timer and then waits for it to complete.
|
||||||
|
@@ -6,18 +6,18 @@ see: key To listen to any key press.
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{char} event is fired when a character is typed on the keyboard.
|
The [`char`] event is fired when a character is typed on the keyboard.
|
||||||
|
|
||||||
The @{char} event is different to a key press. Sometimes multiple key presses may result in one character being
|
The [`char`] event is different to a key press. Sometimes multiple key presses may result in one character being
|
||||||
typed (for instance, on some European keyboards). Similarly, some keys (e.g. <kbd>Ctrl</kbd>) do not have any
|
typed (for instance, on some European keyboards). Similarly, some keys (e.g. <kbd>Ctrl</kbd>) do not have any
|
||||||
corresponding character. The @{key} should be used if you want to listen to key presses themselves.
|
corresponding character. The [`key`] should be used if you want to listen to key presses themselves.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The string representing the character that was pressed.
|
2. [`string`]: The string representing the character that was pressed.
|
||||||
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
@@ -8,11 +8,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{computer_command} event is fired when the `/computercraft queue` command is run for the current computer.
|
The [`computer_command`] event is fired when the `/computercraft queue` command is run for the current computer.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}<abbr title="Variable number of arguments">…</abbr>: The arguments passed to the command.
|
2. [`string`]<abbr title="Variable number of arguments">…</abbr>: The arguments passed to the command.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints the contents of messages sent:
|
Prints the contents of messages sent:
|
||||||
|
@@ -9,11 +9,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{disk} event is fired when a disk is inserted into an adjacent or networked disk drive.
|
The [`disk`] event is fired when a disk is inserted into an adjacent or networked disk drive.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The side of the disk drive that had a disk inserted.
|
2. [`string`]: The side of the disk drive that had a disk inserted.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when a disk is inserted:
|
Prints a message when a disk is inserted:
|
||||||
|
@@ -9,11 +9,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{disk_eject} event is fired when a disk is removed from an adjacent or networked disk drive.
|
The [`disk_eject`] event is fired when a disk is removed from an adjacent or networked disk drive.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The side of the disk drive that had a disk removed.
|
2. [`string`]: The side of the disk drive that had a disk removed.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when a disk is removed:
|
Prints a message when a disk is removed:
|
||||||
|
@@ -9,15 +9,15 @@ SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{file_transfer} event is queued when a user drags-and-drops a file on an open computer.
|
The [`file_transfer`] event is queued when a user drags-and-drops a file on an open computer.
|
||||||
|
|
||||||
This event contains a single argument of type @{TransferredFiles}, which can be used to @{TransferredFiles.getFiles|get
|
This event contains a single argument of type [`TransferredFiles`], which can be used to [get the files to be
|
||||||
the files to be transferred}. Each file returned is a @{fs.BinaryReadHandle|binary file handle} with an additional
|
transferred][`TransferredFiles.getFiles`]. Each file returned is a [binary file handle][`fs.BinaryReadHandle`] with an
|
||||||
@{TransferredFile.getName|getName} method.
|
additional [getName][`TransferredFile.getName`] method.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name
|
1. [`string`]: The event name
|
||||||
2. @{TransferredFiles}: The list of transferred files.
|
2. [`TransferredFiles`]: The list of transferred files.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Waits for a user to drop files on top of the computer, then prints the list of files and the size of each file.
|
Waits for a user to drop files on top of the computer, then prints the list of files and the size of each file.
|
||||||
@@ -29,7 +29,7 @@ for _, file in ipairs(files.getFiles()) do
|
|||||||
local size = file.seek("end")
|
local size = file.seek("end")
|
||||||
file.seek("set", 0)
|
file.seek("set", 0)
|
||||||
|
|
||||||
print(file.getName() .. " " .. file.getSize())
|
print(file.getName() .. " " .. size)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -9,12 +9,12 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{http_check} event is fired when a URL check finishes.
|
The [`http_check`] event is fired when a URL check finishes.
|
||||||
|
|
||||||
This event is normally handled inside @{http.checkURL}, but it can still be seen when using @{http.checkURLAsync}.
|
This event is normally handled inside [`http.checkURL`], but it can still be seen when using [`http.checkURLAsync`].
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The URL requested to be checked.
|
2. [`string`]: The URL requested to be checked.
|
||||||
3. @{boolean}: Whether the check succeeded.
|
3. [`boolean`]: Whether the check succeeded.
|
||||||
4. <span class="type">@{string}|@{nil}</span>: If the check failed, a reason explaining why the check failed.
|
4. <span class="type">[`string`]|[`nil`]</span>: If the check failed, a reason explaining why the check failed.
|
||||||
|
@@ -9,15 +9,15 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{http_failure} event is fired when an HTTP request fails.
|
The [`http_failure`] event is fired when an HTTP request fails.
|
||||||
|
|
||||||
This event is normally handled inside @{http.get} and @{http.post}, but it can still be seen when using @{http.request}.
|
This event is normally handled inside [`http.get`] and [`http.post`], but it can still be seen when using [`http.request`].
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The URL of the site requested.
|
2. [`string`]: The URL of the site requested.
|
||||||
3. @{string}: An error describing the failure.
|
3. [`string`]: An error describing the failure.
|
||||||
4. <span class="type">@{http.Response}|@{nil}</span>: A response handle if the connection succeeded, but the server's
|
4. <span class="type">[`http.Response`]|[`nil`]</span>: A response handle if the connection succeeded, but the server's
|
||||||
response indicated failure.
|
response indicated failure.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
@@ -9,14 +9,14 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{http_success} event is fired when an HTTP request returns successfully.
|
The [`http_success`] event is fired when an HTTP request returns successfully.
|
||||||
|
|
||||||
This event is normally handled inside @{http.get} and @{http.post}, but it can still be seen when using @{http.request}.
|
This event is normally handled inside [`http.get`] and [`http.post`], but it can still be seen when using [`http.request`].
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The URL of the site requested.
|
2. [`string`]: The URL of the site requested.
|
||||||
3. @{http.Response}: The successful HTTP response.
|
3. [`http.Response`]: The successful HTTP response.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints the content of a website (this may fail if the request fails):
|
Prints the content of a website (this may fail if the request fails):
|
||||||
|
@@ -5,21 +5,21 @@ module: [kind=event] key
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired when any key is pressed while the terminal is focused.
|
This event is fired when any key is pressed while the terminal is focused.
|
||||||
|
|
||||||
This event returns a numerical "key code" (for instance, <kbd>F1</kbd> is 290). This value may vary between versions and
|
This event returns a numerical "key code" (for instance, <kbd>F1</kbd> is 290). This value may vary between versions and
|
||||||
so it is recommended to use the constants in the @{keys} API rather than hard coding numeric values.
|
so it is recommended to use the constants in the [`keys`] API rather than hard coding numeric values.
|
||||||
|
|
||||||
If the button pressed represented a printable character, then the @{key} event will be followed immediately by a @{char}
|
If the button pressed represented a printable character, then the [`key`] event will be followed immediately by a [`char`]
|
||||||
event. If you are consuming text input, use a @{char} event instead!
|
event. If you are consuming text input, use a [`char`] event instead!
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The numerical key value of the key pressed.
|
2. [`number`]: The numerical key value of the key pressed.
|
||||||
3. @{boolean}: Whether the key event was generated while holding the key (@{true}), rather than pressing it the first time (@{false}).
|
3. [`boolean`]: Whether the key event was generated while holding the key ([`true`]), rather than pressing it the first time ([`false`]).
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints each key when the user presses it, and if the key is being held.
|
Prints each key when the user presses it, and if the key is being held.
|
||||||
|
@@ -6,20 +6,20 @@ see: keys For a lookup table of the given keys.
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
Fired whenever a key is released (or the terminal is closed while a key was being pressed).
|
Fired whenever a key is released (or the terminal is closed while a key was being pressed).
|
||||||
|
|
||||||
This event returns a numerical "key code" (for instance, <kbd>F1</kbd> is 290). This value may vary between versions and
|
This event returns a numerical "key code" (for instance, <kbd>F1</kbd> is 290). This value may vary between versions and
|
||||||
so it is recommended to use the constants in the @{keys} API rather than hard coding numeric values.
|
so it is recommended to use the constants in the [`keys`] API rather than hard coding numeric values.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The numerical key value of the key pressed.
|
2. [`number`]: The numerical key value of the key pressed.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints each key released on the keyboard whenever a @{key_up} event is fired.
|
Prints each key released on the keyboard whenever a [`key_up`] event is fired.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
while true do
|
while true do
|
||||||
|
@@ -8,18 +8,18 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
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
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The side of the modem that received the message.
|
2. [`string`]: The side of the modem that received the message.
|
||||||
3. @{number}: The channel that the message was sent on.
|
3. [`number`]: The channel that the message was sent on.
|
||||||
4. @{number}: The reply channel set by the sender.
|
4. [`number`]: The reply channel set by the sender.
|
||||||
5. @{any}: The message as sent by the sender.
|
5. [`any`]: The message as sent by the sender.
|
||||||
6. <span class="type">@{number}|@{nil}</span>: The distance between the sender and the receiver in blocks, or @{nil} if the message was sent between dimensions.
|
6. <span class="type">[`number`]|[`nil`]</span>: The distance between the sender and the receiver in blocks, or [`nil`] if the message was sent between dimensions.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Wraps a @{modem} peripheral, opens channel 0 for listening, and prints all received messages.
|
Wraps a [`modem`] peripheral, opens channel 0 for listening, and prints all received messages.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local modem = peripheral.find("modem") or error("No modem attached", 0)
|
local modem = peripheral.find("modem") or error("No modem attached", 0)
|
||||||
|
@@ -8,11 +8,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{monitor_resize} event is fired when an adjacent or networked monitor's size is changed.
|
The [`monitor_resize`] event is fired when an adjacent or networked monitor's size is changed.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The side or network ID of the monitor that was resized.
|
2. [`string`]: The side or network ID of the monitor that was resized.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when a monitor is resized:
|
Prints a message when a monitor is resized:
|
||||||
|
@@ -8,13 +8,13 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{monitor_touch} event is fired when an adjacent or networked Advanced Monitor is right-clicked.
|
The [`monitor_touch`] event is fired when an adjacent or networked Advanced Monitor is right-clicked.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The side or network ID of the monitor that was touched.
|
2. [`string`]: The side or network ID of the monitor that was touched.
|
||||||
3. @{number}: The X coordinate of the touch, in characters.
|
3. [`number`]: The X coordinate of the touch, in characters.
|
||||||
4. @{number}: The Y coordinate of the touch, in characters.
|
4. [`number`]: The Y coordinate of the touch, in characters.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when a monitor is touched:
|
Prints a message when a monitor is touched:
|
||||||
|
@@ -5,20 +5,20 @@ module: [kind=event] mouse_click
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired when the terminal is clicked with a mouse. This event is only fired on advanced computers (including
|
This event is fired when the terminal is clicked with a mouse. This event is only fired on advanced computers (including
|
||||||
advanced turtles and pocket computers).
|
advanced turtles and pocket computers).
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The mouse button that was clicked.
|
2. [`number`]: The mouse button that was clicked.
|
||||||
3. @{number}: The X-coordinate of the click.
|
3. [`number`]: The X-coordinate of the click.
|
||||||
4. @{number}: The Y-coordinate of the click.
|
4. [`number`]: The Y-coordinate of the click.
|
||||||
|
|
||||||
## Mouse buttons
|
## Mouse buttons
|
||||||
Several mouse events (@{mouse_click}, @{mouse_up}, @{mouse_scroll}) contain a "mouse button" code. This takes a
|
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.
|
numerical value depending on which button on your mouse was last pressed when this event occurred.
|
||||||
|
|
||||||
| Button Code | Mouse Button |
|
| Button Code | Mouse Button |
|
||||||
|
@@ -6,16 +6,16 @@ see: mouse_click For when a mouse button is initially pressed.
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired every time the mouse is moved while a mouse button is being held.
|
This event is fired every time the mouse is moved while a mouse button is being held.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The [mouse button](mouse_click.html#Mouse_buttons) that is being pressed.
|
2. [`number`]: The [mouse button](mouse_click.html#Mouse_buttons) that is being pressed.
|
||||||
3. @{number}: The X-coordinate of the mouse.
|
3. [`number`]: The X-coordinate of the mouse.
|
||||||
4. @{number}: The Y-coordinate of the mouse.
|
4. [`number`]: The Y-coordinate of the mouse.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Print the button and the coordinates whenever the mouse is dragged.
|
Print the button and the coordinates whenever the mouse is dragged.
|
||||||
|
@@ -5,16 +5,16 @@ module: [kind=event] mouse_scroll
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired when a mouse wheel is scrolled in the terminal.
|
This event is fired when a mouse wheel is scrolled in the terminal.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The direction of the scroll. (-1 = up, 1 = down)
|
2. [`number`]: The direction of the scroll. (-1 = up, 1 = down)
|
||||||
3. @{number}: The X-coordinate of the mouse when scrolling.
|
3. [`number`]: The X-coordinate of the mouse when scrolling.
|
||||||
4. @{number}: The Y-coordinate of the mouse when scrolling.
|
4. [`number`]: The Y-coordinate of the mouse when scrolling.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints the direction of each scroll, and the position of the mouse at the time.
|
Prints the direction of each scroll, and the position of the mouse at the time.
|
||||||
|
@@ -5,16 +5,16 @@ module: [kind=event] mouse_up
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired when a mouse button is released or a held mouse leaves the computer's terminal.
|
This event is fired when a mouse button is released or a held mouse leaves the computer's terminal.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The [mouse button](mouse_click.html#Mouse_buttons) that was released.
|
2. [`number`]: The [mouse button](mouse_click.html#Mouse_buttons) that was released.
|
||||||
3. @{number}: The X-coordinate of the mouse.
|
3. [`number`]: The X-coordinate of the mouse.
|
||||||
4. @{number}: The Y-coordinate of the mouse.
|
4. [`number`]: The Y-coordinate of the mouse.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints the coordinates and button number whenever the mouse is released.
|
Prints the coordinates and button number whenever the mouse is released.
|
||||||
|
@@ -8,11 +8,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{paste} event is fired when text is pasted into the computer through Ctrl-V (or ⌘V on Mac).
|
The [`paste`] event is fired when text is pasted into the computer through Ctrl-V (or ⌘V on Mac).
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string} The text that was pasted.
|
2. [`string`] The text that was pasted.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints pasted text:
|
Prints pasted text:
|
||||||
|
@@ -9,11 +9,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{peripheral} event is fired when a peripheral is attached on a side or to a modem.
|
The [`peripheral`] event is fired when a peripheral is attached on a side or to a modem.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The side the peripheral was attached to.
|
2. [`string`]: The side the peripheral was attached to.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when a peripheral is attached:
|
Prints a message when a peripheral is attached:
|
||||||
|
@@ -9,11 +9,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{peripheral_detach} event is fired when a peripheral is detached from a side or from a modem.
|
The [`peripheral_detach`] event is fired when a peripheral is detached from a side or from a modem.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The side the peripheral was detached from.
|
2. [`string`]: The side the peripheral was detached from.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when a peripheral is detached:
|
Prints a message when a peripheral is detached:
|
||||||
|
@@ -10,17 +10,17 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{rednet_message} event is fired when a message is sent over Rednet.
|
The [`rednet_message`] event is fired when a message is sent over Rednet.
|
||||||
|
|
||||||
This event is usually handled by @{rednet.receive}, but it can also be pulled manually.
|
This event is usually handled by [`rednet.receive`], but it can also be pulled manually.
|
||||||
|
|
||||||
@{rednet_message} events are sent by @{rednet.run} in the top-level coroutine in response to @{modem_message} events. A @{rednet_message} event is always preceded by a @{modem_message} event. They are generated inside CraftOS rather than being sent by the ComputerCraft machine.
|
[`rednet_message`] events are sent by [`rednet.run`] in the top-level coroutine in response to [`modem_message`] events. A [`rednet_message`] event is always preceded by a [`modem_message`] event. They are generated inside CraftOS rather than being sent by the ComputerCraft machine.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The ID of the sending computer.
|
2. [`number`]: The ID of the sending computer.
|
||||||
3. @{any}: The message sent.
|
3. [`any`]: The message sent.
|
||||||
4. <span class="type">@{string}|@{nil}</span>: The protocol of the message, if provided.
|
4. <span class="type">[`string`]|[`nil`]</span>: The protocol of the message, if provided.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when one is sent:
|
Prints a message when one is sent:
|
||||||
|
@@ -8,10 +8,10 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{event!redstone} event is fired whenever any redstone inputs on the computer change.
|
The [`event!redstone`] event is fired whenever any redstone inputs on the computer change.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when a redstone input changes:
|
Prints a message when a redstone input changes:
|
||||||
|
@@ -10,13 +10,13 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The name of the speaker which is available to play more audio.
|
2. [`string`]: The name of the speaker which is available to play more audio.
|
||||||
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
This uses @{io.lines} to read audio data in blocks of 16KiB from "example_song.dfpwm", and then attempts to play it
|
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.
|
using [`speaker.playAudio`]. If the speaker's buffer is full, it waits for an event and tries again.
|
||||||
|
|
||||||
```lua {data-peripheral=speaker}
|
```lua {data-peripheral=speaker}
|
||||||
local dfpwm = require("cc.audio.dfpwm")
|
local dfpwm = require("cc.audio.dfpwm")
|
||||||
|
@@ -9,13 +9,13 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{task_complete} event is fired when an asynchronous task completes. This is usually handled inside the function call that queued the task; however, functions such as @{commands.execAsync} return immediately so the user can wait for completion.
|
The [`task_complete`] event is fired when an asynchronous task completes. This is usually handled inside the function call that queued the task; however, functions such as [`commands.execAsync`] return immediately so the user can wait for completion.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The ID of the task that completed.
|
2. [`number`]: The ID of the task that completed.
|
||||||
3. @{boolean}: Whether the command succeeded.
|
3. [`boolean`]: Whether the command succeeded.
|
||||||
4. @{string}: If the command failed, an error message explaining the failure. (This is not present if the command succeeded.)
|
4. [`string`]: If the command failed, an error message explaining the failure. (This is not present if the command succeeded.)
|
||||||
5. <abbr title="Variable number of arguments">…</abbr>: Any parameters returned from the command.
|
5. <abbr title="Variable number of arguments">…</abbr>: Any parameters returned from the command.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
@@ -8,15 +8,15 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{term_resize} event is fired when the main terminal is resized. For instance:
|
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 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 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
|
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.
|
not using [`term.setCursorPos`]) can ignore this event, but more complex GUI programs should redraw the entire screen.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Print a message each time the terminal is resized.
|
Print a message each time the terminal is resized.
|
||||||
|
@@ -8,14 +8,14 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{terminate} event is fired when <kbd>Ctrl-T</kbd> is held down.
|
The [`terminate`] event is fired when <kbd>Ctrl-T</kbd> is held down.
|
||||||
|
|
||||||
This event is normally handled by @{os.pullEvent}, and will not be returned. However, @{os.pullEventRaw} will return this event when fired.
|
This event is normally handled by [`os.pullEvent`], and will not be returned. However, [`os.pullEventRaw`] will return this event when fired.
|
||||||
|
|
||||||
@{terminate} will be sent even when a filter is provided to @{os.pullEventRaw}. When using @{os.pullEventRaw} with a filter, make sure to check that the event is not @{terminate}.
|
[`terminate`] will be sent even when a filter is provided to [`os.pullEventRaw`]. When using [`os.pullEventRaw`] with a filter, make sure to check that the event is not [`terminate`].
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when Ctrl-T is held:
|
Prints a message when Ctrl-T is held:
|
||||||
|
@@ -9,11 +9,11 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{timer} event is fired when a timer started with @{os.startTimer} completes.
|
The [`timer`] event is fired when a timer started with [`os.startTimer`] completes.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{number}: The ID of the timer that finished.
|
2. [`number`]: The ID of the timer that finished.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Start and wait for a timer to finish.
|
Start and wait for a timer to finish.
|
||||||
|
@@ -8,10 +8,10 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{turtle_inventory} event is fired when a turtle's inventory is changed.
|
The [`turtle_inventory`] event is fired when a turtle's inventory is changed.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when the inventory is changed:
|
Prints a message when the inventory is changed:
|
||||||
|
@@ -8,16 +8,16 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{websocket_closed} event is fired when an open WebSocket connection is closed.
|
The [`websocket_closed`] event is fired when an open WebSocket connection is closed.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The URL of the WebSocket that was closed.
|
2. [`string`]: The URL of the WebSocket that was closed.
|
||||||
3. <span class="type">@{string}|@{nil}</span>: The [server-provided reason][close_reason]
|
3. <span class="type">[`string`]|[`nil`]</span>: The [server-provided reason][close_reason]
|
||||||
the websocket was closed. This will be @{nil} if the connection was closed
|
the websocket was closed. This will be [`nil`] if the connection was closed
|
||||||
abnormally.
|
abnormally.
|
||||||
4. <span class="type">@{number}|@{nil}</span>: The [connection close code][close_code],
|
4. <span class="type">[`number`]|[`nil`]</span>: The [connection close code][close_code],
|
||||||
indicating why the socket was closed. This will be @{nil} if the connection
|
indicating why the socket was closed. This will be [`nil`] if the connection
|
||||||
was closed abnormally.
|
was closed abnormally.
|
||||||
|
|
||||||
[close_reason]: https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.6 "The WebSocket Connection Close Reason, RFC 6455"
|
[close_reason]: https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.6 "The WebSocket Connection Close Reason, RFC 6455"
|
||||||
|
@@ -9,14 +9,14 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{websocket_failure} event is fired when a WebSocket connection request fails.
|
The [`websocket_failure`] event is fired when a WebSocket connection request fails.
|
||||||
|
|
||||||
This event is normally handled inside @{http.websocket}, but it can still be seen when using @{http.websocketAsync}.
|
This event is normally handled inside [`http.websocket`], but it can still be seen when using [`http.websocketAsync`].
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The URL of the site requested.
|
2. [`string`]: The URL of the site requested.
|
||||||
3. @{string}: An error describing the failure.
|
3. [`string`]: An error describing the failure.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints an error why the website cannot be contacted:
|
Prints an error why the website cannot be contacted:
|
||||||
|
@@ -8,15 +8,15 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{websocket_message} event is fired when a message is received on an open WebSocket connection.
|
The [`websocket_message`] event is fired when a message is received on an open WebSocket connection.
|
||||||
|
|
||||||
This event is normally handled by @{http.Websocket.receive}, but it can also be pulled manually.
|
This event is normally handled by [`http.Websocket.receive`], but it can also be pulled manually.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The URL of the WebSocket.
|
2. [`string`]: The URL of the WebSocket.
|
||||||
3. @{string}: The contents of the message.
|
3. [`string`]: The contents of the message.
|
||||||
4. @{boolean}: Whether this is a binary message.
|
4. [`boolean`]: Whether this is a binary message.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message sent by a WebSocket:
|
Prints a message sent by a WebSocket:
|
||||||
|
@@ -9,14 +9,14 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The @{websocket_success} event is fired when a WebSocket connection request returns successfully.
|
The [`websocket_success`] event is fired when a WebSocket connection request returns successfully.
|
||||||
|
|
||||||
This event is normally handled inside @{http.websocket}, but it can still be seen when using @{http.websocketAsync}.
|
This event is normally handled inside [`http.websocket`], but it can still be seen when using [`http.websocketAsync`].
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. @{string}: The event name.
|
1. [`string`]: The event name.
|
||||||
2. @{string}: The URL of the site.
|
2. [`string`]: The URL of the site.
|
||||||
3. @{http.Websocket}: The handle for the WebSocket.
|
3. [`http.Websocket`]: The handle for the WebSocket.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints the content of a website (this may fail if the request fails):
|
Prints the content of a website (this may fail if the request fails):
|
||||||
|
@@ -9,7 +9,7 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
# Setting up GPS
|
# Setting up GPS
|
||||||
The @{gps} API allows computers and turtles to find their current position using wireless modems.
|
The [`gps`] API allows computers and turtles to find their current position using wireless modems.
|
||||||
|
|
||||||
In order to use GPS, you'll need to set up multiple *GPS hosts*. These are computers running the special `gps host`
|
In order to use GPS, you'll need to set up multiple *GPS hosts*. These are computers running the special `gps host`
|
||||||
program, which tell other computers the host's position. Several hosts running together are known as a *GPS
|
program, which tell other computers the host's position. Several hosts running together are known as a *GPS
|
||||||
@@ -19,22 +19,21 @@ In order to give the best results, a GPS constellation needs at least four compu
|
|||||||
constellation is redundant, but it does not cause problems.
|
constellation is redundant, but it does not cause problems.
|
||||||
|
|
||||||
## Building a GPS constellation
|
## Building a GPS constellation
|
||||||
{.big-image}
|
<img alt="An example GPS constellation." src="/images/gps-constellation-example.png" class="big-image" />
|
||||||
|
|
||||||
We are going to build our GPS constellation as shown in the image above. You will need 4 computers and either 4 wireless
|
We are going to build our GPS constellation as shown in the image above. You will need 4 computers and either 4 wireless
|
||||||
modems or 4 ender modems. Try not to mix ender and wireless modems together as you might get some odd behavior when your
|
modems or 4 ender modems. Try not to mix ender and wireless modems together as you might get some odd behavior when your
|
||||||
requesting computers are out of range.
|
requesting computers are out of range.
|
||||||
|
|
||||||
:::tip Ender modems vs wireless modems
|
> [Ender modems vs wireless modems][!TIP]
|
||||||
Ender modems have a very large range, which makes them very useful for setting up GPS hosts. If you do this then you
|
> Ender modems have a very large range, which makes them very useful for setting up GPS hosts. If you do this then you
|
||||||
will likely only need one GPS constellation for the whole dimension (such as the Overworld or Nether).
|
> will likely only need one GPS constellation for the whole dimension (such as the Overworld or Nether).
|
||||||
|
>
|
||||||
If you do use wireless modems then you may find that you need multiple GPS constellations to cover your needs.
|
> If you do use wireless modems then you may find that you need multiple GPS constellations to cover your needs.
|
||||||
|
>
|
||||||
A computer needs a wireless or ender modem and to be in range of a GPS constellation that is in the same dimension as it
|
> A computer needs a wireless or ender modem and to be in range of a GPS constellation that is in the same dimension as
|
||||||
to use the GPS API. The reason for this is that ComputerCraft mimics real-life GPS by making use of the distance
|
> it to use the GPS API. The reason for this is that ComputerCraft mimics real-life GPS by making use of the distance
|
||||||
parameter of @{modem_message|modem messages} and some maths.
|
> parameter of [modem messages][`modem_message`] and some maths.
|
||||||
:::
|
|
||||||
|
|
||||||
Locate where you want to place your GPS constellation. You will need an area at least 6 blocks high, 6 blocks wide, and
|
Locate where you want to place your GPS constellation. You will need an area at least 6 blocks high, 6 blocks wide, and
|
||||||
6 blocks deep (6x6x6). If you are using wireless modems then you may want to build your constellation as high as you can
|
6 blocks deep (6x6x6). If you are using wireless modems then you may want to build your constellation as high as you can
|
||||||
@@ -79,18 +78,16 @@ To hide Minecraft's debug screen, press <kbd>F3</kbd> again.
|
|||||||
Create similar startup files for the other computers in your constellation, making sure to input the each computer's own
|
Create similar startup files for the other computers in your constellation, making sure to input the each computer's own
|
||||||
coordinates.
|
coordinates.
|
||||||
|
|
||||||
:::caution Modem messages come from the computer's position, not the modem's
|
> [Modem messages come from the computer's position, not the modem's][!WARNING]
|
||||||
Wireless modems transmit from the block that they are attached to *not* the block space that they occupy, the
|
> Wireless modems transmit from the block that they are attached to *not* the block space that they occupy, the
|
||||||
coordinates that you input into your GPS host should be the position of the computer and not the position of the modem.
|
> coordinates that you input into your GPS host should be the position of the computer and not the position of the modem.
|
||||||
:::
|
|
||||||
|
|
||||||
Congratulations, your constellation is now fully set up! You can test it by placing another computer close by, placing a
|
Congratulations, your constellation is now fully set up! You can test it by placing another computer close by, placing a
|
||||||
wireless modem on it, and running the `gps locate` program (or calling the @{gps.locate} function).
|
wireless modem on it, and running the `gps locate` program (or calling the [`gps.locate`] function).
|
||||||
|
|
||||||
:::info Why use Minecraft's coordinates?
|
> [Why use Minecraft's coordinates?][!INFO]
|
||||||
CC doesn't care if you use Minecraft's coordinate system, so long as all of the GPS hosts with overlapping ranges use
|
> CC doesn't care if you use Minecraft's coordinate system, so long as all of the GPS hosts with overlapping ranges use
|
||||||
the same reference point (requesting computers will get confused if hosts have different reference points). However,
|
> the same reference point (requesting computers will get confused if hosts have different reference points). However,
|
||||||
using MC's coordinate system does provide a nice standard to adopt server-wide. It also is consistent with how command
|
> using MC's coordinate system does provide a nice standard to adopt server-wide. It also is consistent with how command
|
||||||
computers get their location, they use MC's command system to get their block which returns that in MC's coordinate
|
> computers get their location, they use MC's command system to get their block which returns that in MC's coordinate
|
||||||
system.
|
> system.
|
||||||
:::
|
|
||||||
|
@@ -11,7 +11,7 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
# Playing audio with speakers
|
# Playing audio with speakers
|
||||||
CC: Tweaked's speaker peripheral provides a powerful way to play any audio you like with the @{speaker.playAudio}
|
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
|
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
|
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.
|
the more complex topic of audio processing.
|
||||||
@@ -60,7 +60,7 @@ sine waves (and why wouldn't you?), you'd need a table with almost 3 _million_.
|
|||||||
up very quickly, and these tables take up more and more memory.
|
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
|
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
|
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
|
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.
|
one, and then play them.
|
||||||
|
|
||||||
@@ -84,15 +84,15 @@ end
|
|||||||
```
|
```
|
||||||
|
|
||||||
It looks pretty similar to before, aside from we've wrapped the generation and playing code in a while loop, and added a
|
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}.
|
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
|
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
|
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!
|
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,
|
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.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.
|
[`speaker_audio_empty`] event is queued, and we can try to play our chunk once more.
|
||||||
|
|
||||||
## Storing audio
|
## 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
|
PCM is a fantastic way of representing audio when we want to manipulate it, but it's not very efficient when we want to
|
||||||
@@ -106,7 +106,7 @@ computer. Instead, we need something much simpler.
|
|||||||
|
|
||||||
DFPWM (Dynamic Filter Pulse Width Modulation) is the de facto standard audio format of the ComputerCraft (and
|
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
|
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
|
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.
|
using the speaker.
|
||||||
|
|
||||||
Let's dive in with an example, and we'll explain things afterwards:
|
Let's dive in with an example, and we'll explain things afterwards:
|
||||||
@@ -125,16 +125,16 @@ for chunk in io.lines("data/example.dfpwm", 16 * 1024) do
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Once again, we see the @{speaker.playAudio}/@{speaker_audio_empty} loop. However, the rest of the program is a little
|
Once again, we see the [`speaker.playAudio`]/[`speaker_audio_empty`] loop. However, the rest of the program is a little
|
||||||
different.
|
different.
|
||||||
|
|
||||||
First, we require the dfpwm module and call @{cc.audio.dfpwm.make_decoder} to construct a new decoder. This decoder
|
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.
|
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
|
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
|
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
|
[`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.
|
[`fs.BinaryReadHandle.read`] if you prefer.
|
||||||
|
|
||||||
## Processing audio
|
## 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.
|
As mentioned near the beginning of this guide, PCM audio is pretty easy to work with as it's just a list of amplitudes.
|
||||||
@@ -189,10 +189,9 @@ for chunk in io.lines("data/example.dfpwm", 16 * 1024) do
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note Confused?
|
> [Confused?][!NOTE]
|
||||||
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 [GitHub Discussions] 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
|
||||||
the wave. If you wanted to modify the _frequency_ (for instance, shifting the pitch), things get rather more complex.
|
the wave. If you wanted to modify the _frequency_ (for instance, shifting the pitch), things get rather more complex.
|
||||||
|
@@ -13,7 +13,7 @@ A library is a collection of useful functions and other definitions which is sto
|
|||||||
might want to create a library because you have some functions which are used in multiple programs, or just to split
|
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.
|
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
|
Let's say we want to create a small library to make working with the [terminal][`term`] 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
|
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.
|
in the middle of the screen.
|
||||||
|
|
||||||
@@ -48,32 +48,32 @@ more_term.write_center("Hello, world!")
|
|||||||
When run, this'll clear the screen and print some text in the middle of the first line.
|
When run, this'll clear the screen and print some text in the middle of the first line.
|
||||||
|
|
||||||
## require in depth
|
## require in depth
|
||||||
While the previous section is a good introduction to how @{require} operates, there are a couple of remaining points
|
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.
|
which are worth mentioning for more advanced usage.
|
||||||
|
|
||||||
### Libraries can return anything
|
### 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
|
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
|
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.
|
all the same, and just returns whatever your library provides.
|
||||||
|
|
||||||
### Module resolution and the package path
|
### 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
|
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
|
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.
|
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
|
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
|
code from a sub-directory using `require("folder/library")` or even `require("folder/library.lua")`, neither of which
|
||||||
will do quite what you expect.
|
will do quite what you expect.
|
||||||
|
|
||||||
When loading libraries (also referred to as *modules*) from files, @{require} searches along the *@{package.path|module
|
When loading libraries (also referred to as *modules*) from files, [`require`] searches along the [*module
|
||||||
path}*. By default, this looks something like:
|
path*][`package.path`]. By default, this looks something like:
|
||||||
|
|
||||||
* `?.lua`
|
* `?.lua`
|
||||||
* `?/init.lua`
|
* `?/init.lua`
|
||||||
* `/rom/modules/main/?.lua`
|
* `/rom/modules/main/?.lua`
|
||||||
* etc...
|
* etc...
|
||||||
|
|
||||||
When you call `require("my_library")`, @{require} replaces the `?` in each element of the path with your module name, and
|
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`,
|
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
|
`/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...
|
program is actually called `folder/program`, then we'll look for `folder/my_library.lua`, etc...
|
||||||
@@ -86,4 +86,4 @@ before we start looking for the library.
|
|||||||
There are several external resources which go into require in a little more detail:
|
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.
|
- 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).
|
- [Lua's manual section on `require`](https://www.lua.org/manual/5.1/manual.html#pdf-require).
|
||||||
|
@@ -15,13 +15,13 @@ CC: Tweaked can be installed from [CurseForge] or [Modrinth]. It runs on both [M
|
|||||||
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
|
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
|
||||||
writing code and automating your Minecraft world.
|
writing code and automating your Minecraft world.
|
||||||
|
|
||||||
{.big-image}
|
<img alt="A ComputerCraft terminal open and ready to be programmed." src="images/basic-terminal.png" class="big-image" />
|
||||||
|
|
||||||
While computers are incredibly powerful, they're rather limited by their inability to move about. *Turtles* are the
|
While computers are incredibly powerful, they're rather limited by their inability to move about. *Turtles* are the
|
||||||
solution here. They can move about the world, placing and breaking blocks, swinging a sword to protect you from zombies,
|
solution here. They can move about the world, placing and breaking blocks, swinging a sword to protect you from zombies,
|
||||||
or whatever else you program them to!
|
or whatever else you program them to!
|
||||||
|
|
||||||
{.big-image}
|
<img alt="A turtle tunneling in Minecraft." src="images/turtle.png" class="big-image" />
|
||||||
|
|
||||||
Not all problems can be solved with a pickaxe though, and so CC: Tweaked also provides a bunch of additional peripherals
|
Not all problems can be solved with a pickaxe though, and so CC: Tweaked also provides a bunch of additional peripherals
|
||||||
for your computers. You can play a tune with speakers, display text or images on a monitor, connect all your
|
for your computers. You can play a tune with speakers, display text or images on a monitor, connect all your
|
||||||
@@ -30,7 +30,7 @@ computers together with modems, and much more.
|
|||||||
Computers can now also interact with inventories such as chests, allowing you to build complex inventory and item
|
Computers can now also interact with inventories such as chests, allowing you to build complex inventory and item
|
||||||
management systems.
|
management systems.
|
||||||
|
|
||||||
{.big-image}
|
<img alt="A chest's contents being read by a computer and displayed on a monitor." src="images/peripherals.png" class="big-image" />
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
While ComputerCraft is lovely for both experienced programmers and for people who have never coded before, it can be a
|
While ComputerCraft is lovely for both experienced programmers and for people who have never coded before, it can be a
|
||||||
|
67
doc/reference/breaking_changes.md
Normal file
67
doc/reference/breaking_changes.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
module: [kind=reference] breaking_changes
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2019 The CC: Tweaked Developers
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MPL-2.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Incompatibilities between versions
|
||||||
|
|
||||||
|
CC: Tweaked tries to remain as compatible between versions as possible, meaning most programs written for older version
|
||||||
|
of the mod should run fine on later versions.
|
||||||
|
|
||||||
|
> [External peripherals][!WARNING]
|
||||||
|
>
|
||||||
|
> While CC: Tweaked is relatively stable across versions, this may not be true for other mods which add their own
|
||||||
|
> peripherals. Older programs which interact with external blocks may not work on newer versions of the game.
|
||||||
|
|
||||||
|
However, some changes to the underlying game, or CC: Tweaked's own internals may break some programs. This page serves
|
||||||
|
as documentation for breaking changes and "gotchas" one should look out for between versions.
|
||||||
|
|
||||||
|
## Minecraft 1.13 {#mc-1.13}
|
||||||
|
- The "key code" for [`key`] and [`key_up`] events has changed, due to Minecraft updating to LWJGL 3. Make sure you're
|
||||||
|
using the constants provided by the [`keys`] API, rather than hard-coding numerical values.
|
||||||
|
|
||||||
|
Related to this change, the numpad enter key now has a different key code to the enter key. You may need to adjust
|
||||||
|
your programs to handle both. (Note, the `keys.numpadEnter` constant was defined in pre-1.13 versions of CC, but the
|
||||||
|
`keys.enter` constant was queued when the key was pressed)
|
||||||
|
|
||||||
|
- Minecraft 1.13 removed the concept of item damage and block metadata (see ["The Flattening"][flattening]). As a
|
||||||
|
result `turtle.inspect` no longer provides block metadata, and `turtle.getItemDetail` no longer provides damage.
|
||||||
|
|
||||||
|
- Block states (`turtle.inspect().state`) should provide all the same information as block metadata, but in a much
|
||||||
|
more understandable format.
|
||||||
|
|
||||||
|
- Item and block names now represent a unique item type. For instance, wool is split into 16 separate items
|
||||||
|
(`minecraft:white_wool`, etc...) rather than a single `minecraft:wool` with each meta/damage value specifying the
|
||||||
|
colour.
|
||||||
|
|
||||||
|
- Custom ROMs are now provided using data packs rather than resource packs. This should mostly be a matter of renaming
|
||||||
|
the "assets" folder to "data", and placing it in "datapacks", but there are a couple of other gotchas to look out
|
||||||
|
for:
|
||||||
|
|
||||||
|
- Data packs [impose some restrictions on file names][legal_data_pack]. As a result, your programs and directories
|
||||||
|
must all be lower case.
|
||||||
|
- Due to how data packs are read by CC: Tweaked, you may need to use the `/reload` command to see changes to your
|
||||||
|
pack show up on the computer.
|
||||||
|
|
||||||
|
See [the example datapack][datapack-example] for how to get started.
|
||||||
|
|
||||||
|
- Turtles can now be waterlogged and move "through" water sources rather than breaking them.
|
||||||
|
|
||||||
|
## CC: Tweaked 1.88.0 {#cc-1.88}
|
||||||
|
- Unlabelled computers and turtles now keep their ID when broken, meaning that unlabelled computers/items do not stack.
|
||||||
|
|
||||||
|
## ComputerCraft 1.80pr1 {#cc-1.80}
|
||||||
|
- Programs run via `shell.run` are now started in their own isolated environment. This means globals set by programs
|
||||||
|
will not be accessible outside of this program.
|
||||||
|
|
||||||
|
- Programs containing `/` are looked up in the current directory and are no longer looked up on the path. For instance,
|
||||||
|
you can no longer type `turtle/excavate` to run `/rom/programs/turtle/excavate.lua`.
|
||||||
|
|
||||||
|
[flattening]: https://minecraft.wiki.com/w/Java_Edition_1.13/Flattening
|
||||||
|
[legal_data_pack]: https://minecraft.gamepedia.com/Tutorials/Creating_a_data_pack#Legal_characters
|
||||||
|
[datapack-example]: https://github.com/cc-tweaked/datapack-example "An example datapack for CC: Tweaked"
|
@@ -13,22 +13,20 @@ include standard Lua functions.
|
|||||||
|
|
||||||
As it waits for a fixed amount of world ticks, `time` will automatically be
|
As it waits for a fixed amount of world ticks, `time` will automatically be
|
||||||
rounded up to the nearest multiple of 0.05 seconds. If you are using coroutines
|
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
|
or the [parallel API][`parallel`], it will only pause execution of the current
|
||||||
thread, not the whole program.
|
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.
|
||||||
:::
|
|
||||||
|
|
||||||
:::caution
|
> [!WARNING]
|
||||||
Internally, this function queues and waits for a timer event (using
|
> Internally, this function queues and waits for a timer event (using
|
||||||
@{os.startTimer}), however it does not listen for any other events. This means
|
> [`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
|
> that any event that occurs while sleeping will be entirely discarded. If you
|
||||||
need to receive events while sleeping, consider using @{os.startTimer|timers},
|
> need to receive events while sleeping, consider using [timers][`os.startTimer`],
|
||||||
or the @{parallel|parallel API}.
|
> or the [parallel API][`parallel`].
|
||||||
:::
|
|
||||||
|
|
||||||
@tparam number time The number of seconds to sleep for, rounded up to the
|
@tparam number time The number of seconds to sleep for, rounded up to the
|
||||||
nearest multiple of 0.05.
|
nearest multiple of 0.05.
|
||||||
@@ -116,7 +114,7 @@ function read(replaceChar, history, completeFn, default) end
|
|||||||
|
|
||||||
--- Stores the current ComputerCraft and Minecraft versions.
|
--- Stores the current ComputerCraft and Minecraft versions.
|
||||||
--
|
--
|
||||||
-- Outside of Minecraft (for instance, in an emulator) @{_HOST} will contain the
|
-- Outside of Minecraft (for instance, in an emulator) [`_HOST`] will contain the
|
||||||
-- emulator's version instead.
|
-- emulator's version instead.
|
||||||
--
|
--
|
||||||
-- For example, `ComputerCraft 1.93.0 (Minecraft 1.15.2)`.
|
-- For example, `ComputerCraft 1.93.0 (Minecraft 1.15.2)`.
|
||||||
|
@@ -15,27 +15,27 @@ variables and functions exported by it will by available through the use of
|
|||||||
@deprecated When possible it's best to avoid using this function. It pollutes
|
@deprecated When possible it's best to avoid using this function. It pollutes
|
||||||
the global table and can mask errors.
|
the global table and can mask errors.
|
||||||
|
|
||||||
@{require} should be used to load libraries instead.
|
[`require`] should be used to load libraries instead.
|
||||||
]]
|
]]
|
||||||
function loadAPI(path) end
|
function loadAPI(path) end
|
||||||
|
|
||||||
--- Unloads an API which was loaded by @{os.loadAPI}.
|
--- Unloads an API which was loaded by [`os.loadAPI`].
|
||||||
--
|
--
|
||||||
-- This effectively removes the specified table from `_G`.
|
-- This effectively removes the specified table from `_G`.
|
||||||
--
|
--
|
||||||
-- @tparam string name The name of the API to unload.
|
-- @tparam string name The name of the API to unload.
|
||||||
-- @since 1.2
|
-- @since 1.2
|
||||||
-- @deprecated See @{os.loadAPI} for why.
|
-- @deprecated See [`os.loadAPI`] for why.
|
||||||
function unloadAPI(name) end
|
function unloadAPI(name) end
|
||||||
|
|
||||||
--[[- Pause execution of the current thread and waits for any events matching
|
--[[- Pause execution of the current thread and waits for any events matching
|
||||||
`filter`.
|
`filter`.
|
||||||
|
|
||||||
This function @{coroutine.yield|yields} the current process and waits for it
|
This function [yields][`coroutine.yield`] the current process and waits for it
|
||||||
to be resumed with a vararg list where the first element matches `filter`.
|
to be resumed with a vararg list where the first element matches `filter`.
|
||||||
If no `filter` is supplied, this will match all events.
|
If no `filter` is supplied, this will match all events.
|
||||||
|
|
||||||
Unlike @{os.pullEventRaw}, it will stop the application upon a "terminate"
|
Unlike [`os.pullEventRaw`], it will stop the application upon a "terminate"
|
||||||
event, printing the error "Terminated".
|
event, printing the error "Terminated".
|
||||||
|
|
||||||
@tparam[opt] string filter Event to filter for.
|
@tparam[opt] string filter Event to filter for.
|
||||||
@@ -69,7 +69,7 @@ function pullEvent(filter) end
|
|||||||
--[[- Pause execution of the current thread and waits for events, including the
|
--[[- Pause execution of the current thread and waits for events, including the
|
||||||
`terminate` event.
|
`terminate` event.
|
||||||
|
|
||||||
This behaves almost the same as @{os.pullEvent}, except it allows you to handle
|
This behaves almost the same as [`os.pullEvent`], except it allows you to handle
|
||||||
the `terminate` event yourself - the program will not stop execution when
|
the `terminate` event yourself - the program will not stop execution when
|
||||||
<kbd>Ctrl+T</kbd> is pressed.
|
<kbd>Ctrl+T</kbd> is pressed.
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ the `terminate` event yourself - the program will not stop execution when
|
|||||||
]]
|
]]
|
||||||
function pullEventRaw(filter) end
|
function pullEventRaw(filter) end
|
||||||
|
|
||||||
--- Pauses execution for the specified number of seconds, alias of @{_G.sleep}.
|
--- Pauses execution for the specified number of seconds, alias of [`_G.sleep`].
|
||||||
--
|
--
|
||||||
-- @tparam number time The number of seconds to sleep for, rounded up to the
|
-- @tparam number time The number of seconds to sleep for, rounded up to the
|
||||||
-- nearest multiple of 0.05.
|
-- nearest multiple of 0.05.
|
||||||
@@ -109,12 +109,12 @@ arguments.
|
|||||||
|
|
||||||
This function does not resolve program names like the shell does. This means
|
This function does not resolve program names like the shell does. This means
|
||||||
that, for example, `os.run("edit")` will not work. As well as this, it does not
|
that, for example, `os.run("edit")` will not work. As well as this, it does not
|
||||||
provide access to the @{shell} API in the environment. For this behaviour, use
|
provide access to the [`shell`] API in the environment. For this behaviour, use
|
||||||
@{shell.run} instead.
|
[`shell.run`] instead.
|
||||||
|
|
||||||
If the program cannot be found, or failed to run, it will print the error and
|
If the program cannot be found, or failed to run, it will print the error and
|
||||||
return `false`. If you want to handle this more gracefully, use an alternative
|
return `false`. If you want to handle this more gracefully, use an alternative
|
||||||
such as @{loadfile}.
|
such as [`loadfile`].
|
||||||
|
|
||||||
@tparam table env The environment to run the program with.
|
@tparam table env The environment to run the program with.
|
||||||
@tparam string path The exact path of the program to run.
|
@tparam string path The exact path of the program to run.
|
||||||
|
@@ -10,7 +10,7 @@ kotlin.jvm.target.validation.mode=error
|
|||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
isUnstable=false
|
isUnstable=false
|
||||||
modVersion=1.107.0
|
modVersion=1.108.4
|
||||||
|
|
||||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
||||||
mcVersion=1.19.4
|
mcVersion=1.20.1
|
||||||
|
@@ -7,20 +7,21 @@
|
|||||||
# Minecraft
|
# Minecraft
|
||||||
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
||||||
# Remember to update corresponding versions in fabric.mod.json/mods.toml
|
# Remember to update corresponding versions in fabric.mod.json/mods.toml
|
||||||
fabric-api = "0.86.1+1.19.4"
|
fabric-api = "0.86.1+1.20.1"
|
||||||
fabric-loader = "0.14.21"
|
fabric-loader = "0.14.21"
|
||||||
forge = "45.0.42"
|
forge = "47.1.0"
|
||||||
forgeSpi = "6.0.0"
|
forgeSpi = "6.0.0"
|
||||||
mixin = "0.8.5"
|
mixin = "0.8.5"
|
||||||
parchment = "2023.06.26"
|
parchment = "2023.08.20"
|
||||||
parchmentMc = "1.19.4"
|
parchmentMc = "1.20.1"
|
||||||
|
|
||||||
# Normal dependencies
|
# Normal dependencies
|
||||||
asm = "9.3"
|
asm = "9.5"
|
||||||
autoService = "1.0.1"
|
autoService = "1.1.1"
|
||||||
checkerFramework = "3.32.0"
|
checkerFramework = "3.32.0"
|
||||||
cobalt = "0.7.1"
|
cobalt = "0.7.3"
|
||||||
cobalt-next = "0.7.2" # Not a real version, used to constrain the version we accept.
|
cobalt-next = "0.7.4" # Not a real version, used to constrain the version we accept.
|
||||||
|
commonsCli = "1.3.1"
|
||||||
fastutil = "8.5.9"
|
fastutil = "8.5.9"
|
||||||
guava = "31.1-jre"
|
guava = "31.1-jre"
|
||||||
jetbrainsAnnotations = "24.0.1"
|
jetbrainsAnnotations = "24.0.1"
|
||||||
@@ -29,51 +30,56 @@ jzlib = "1.1.3"
|
|||||||
kotlin = "1.8.10"
|
kotlin = "1.8.10"
|
||||||
kotlin-coroutines = "1.6.4"
|
kotlin-coroutines = "1.6.4"
|
||||||
netty = "4.1.82.Final"
|
netty = "4.1.82.Final"
|
||||||
nightConfig = "3.6.5"
|
nightConfig = "3.6.7"
|
||||||
slf4j = "1.7.36"
|
slf4j = "2.0.1"
|
||||||
|
|
||||||
# Minecraft mods
|
# Minecraft mods
|
||||||
emi = "1.0.8+1.19.4"
|
emi = "1.0.8+1.20.1"
|
||||||
iris = "1.5.2+1.19.4"
|
fabricPermissions = "0.3.20230723"
|
||||||
jei = "13.1.0.11"
|
iris = "1.6.4+1.20"
|
||||||
modmenu = "6.1.0-rc.1"
|
jei = "15.2.0.22"
|
||||||
|
modmenu = "7.1.0"
|
||||||
|
moreRed = "4.0.0.4"
|
||||||
oculus = "1.2.5"
|
oculus = "1.2.5"
|
||||||
rei = "10.0.578"
|
rei = "12.0.626"
|
||||||
rubidium = "0.6.1"
|
rubidium = "0.6.1"
|
||||||
sodium = "mc1.19.4-0.4.10"
|
sodium = "mc1.20-0.4.10"
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
byteBuddy = "1.14.2"
|
|
||||||
hamcrest = "2.2"
|
hamcrest = "2.2"
|
||||||
jqwik = "1.7.2"
|
jqwik = "1.7.4"
|
||||||
junit = "5.9.2"
|
junit = "5.10.0"
|
||||||
|
|
||||||
# Build tools
|
# Build tools
|
||||||
cctJavadoc = "1.7.0"
|
cctJavadoc = "1.8.0"
|
||||||
checkstyle = "10.3.4"
|
checkstyle = "10.12.3"
|
||||||
curseForgeGradle = "1.0.14"
|
curseForgeGradle = "1.0.14"
|
||||||
errorProne-core = "2.18.0"
|
errorProne-core = "2.21.1"
|
||||||
errorProne-plugin = "3.0.1"
|
errorProne-plugin = "3.1.0"
|
||||||
fabric-loom = "1.3.7"
|
fabric-loom = "1.3.7"
|
||||||
forgeGradle = "6.0.8"
|
forgeGradle = "6.0.8"
|
||||||
githubRelease = "2.2.12"
|
githubRelease = "2.4.1"
|
||||||
ideaExt = "1.1.6"
|
ideaExt = "1.1.7"
|
||||||
illuaminate = "0.1.0-28-ga7efd71"
|
illuaminate = "0.1.0-44-g9ee0055"
|
||||||
librarian = "1.+"
|
librarian = "1.+"
|
||||||
|
lwjgl = "3.3.1"
|
||||||
minotaur = "2.+"
|
minotaur = "2.+"
|
||||||
mixinGradle = "0.7.+"
|
mixinGradle = "0.7.+"
|
||||||
nullAway = "0.9.9"
|
nullAway = "0.9.9"
|
||||||
quiltflower = "1.10.0"
|
spotless = "6.21.0"
|
||||||
spotless = "6.17.0"
|
|
||||||
taskTree = "2.1.1"
|
taskTree = "2.1.1"
|
||||||
|
teavm = "0.9.0-SQUID.1"
|
||||||
vanillaGradle = "0.2.1-SNAPSHOT"
|
vanillaGradle = "0.2.1-SNAPSHOT"
|
||||||
|
vineflower = "1.11.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
# Normal dependencies
|
# Normal dependencies
|
||||||
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
|
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
|
||||||
|
asm-commons = { module = "org.ow2.asm:asm-commons", version.ref = "asm" }
|
||||||
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
|
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
|
||||||
checkerFramework = { module = "org.checkerframework:checker-qual", version.ref = "checkerFramework" }
|
checkerFramework = { module = "org.checkerframework:checker-qual", version.ref = "checkerFramework" }
|
||||||
cobalt = { module = "org.squiddev:Cobalt", version.ref = "cobalt" }
|
cobalt = { module = "org.squiddev:Cobalt", version.ref = "cobalt" }
|
||||||
|
commonsCli = { module = "commons-cli:commons-cli", version.ref = "commonsCli" }
|
||||||
fastutil = { module = "it.unimi.dsi:fastutil", version.ref = "fastutil" }
|
fastutil = { module = "it.unimi.dsi:fastutil", version.ref = "fastutil" }
|
||||||
forgeSpi = { module = "net.minecraftforge:forgespi", version.ref = "forgeSpi" }
|
forgeSpi = { module = "net.minecraftforge:forgespi", version.ref = "forgeSpi" }
|
||||||
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
||||||
@@ -93,13 +99,16 @@ slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
|||||||
# Minecraft mods
|
# Minecraft mods
|
||||||
fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" }
|
fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" }
|
||||||
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" }
|
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" }
|
||||||
|
fabric-junit = { module = "net.fabricmc:fabric-loader-junit", version.ref = "fabric-loader" }
|
||||||
|
fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" }
|
||||||
emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" }
|
emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" }
|
||||||
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
|
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
|
||||||
jei-api = { module = "mezz.jei:jei-1.19.4-common-api", version.ref = "jei" }
|
jei-api = { module = "mezz.jei:jei-1.20.1-common-api", version.ref = "jei" }
|
||||||
jei-fabric = { module = "mezz.jei:jei-1.19.4-fabric", version.ref = "jei" }
|
jei-fabric = { module = "mezz.jei:jei-1.20.1-fabric", version.ref = "jei" }
|
||||||
jei-forge = { module = "mezz.jei:jei-1.19.4-forge", version.ref = "jei" }
|
jei-forge = { module = "mezz.jei:jei-1.20.1-forge", version.ref = "jei" }
|
||||||
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
|
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
|
||||||
modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" }
|
modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" }
|
||||||
|
moreRed = { module = "commoble.morered:morered-1.20.1", version.ref = "moreRed" }
|
||||||
oculus = { module = "maven.modrinth:oculus", version.ref = "oculus" }
|
oculus = { module = "maven.modrinth:oculus", version.ref = "oculus" }
|
||||||
rei-api = { module = "me.shedaniel:RoughlyEnoughItems-api", version.ref = "rei" }
|
rei-api = { module = "me.shedaniel:RoughlyEnoughItems-api", version.ref = "rei" }
|
||||||
rei-builtin = { module = "me.shedaniel:RoughlyEnoughItems-default-plugin", version.ref = "rei" }
|
rei-builtin = { module = "me.shedaniel:RoughlyEnoughItems-default-plugin", version.ref = "rei" }
|
||||||
@@ -108,8 +117,6 @@ rubidium = { module = "maven.modrinth:rubidium", version.ref = "rubidium" }
|
|||||||
sodium = { module = "maven.modrinth:sodium", version.ref = "sodium" }
|
sodium = { module = "maven.modrinth:sodium", version.ref = "sodium" }
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
byteBuddyAgent = { module = "net.bytebuddy:byte-buddy-agent", version.ref = "byteBuddy" }
|
|
||||||
byteBuddy = { module = "net.bytebuddy:byte-buddy", version.ref = "byteBuddy" }
|
|
||||||
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
|
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
|
||||||
jqwik-api = { module = "net.jqwik:jqwik-api", version.ref = "jqwik" }
|
jqwik-api = { module = "net.jqwik:jqwik-api", version.ref = "jqwik" }
|
||||||
jqwik-engine = { module = "net.jqwik:jqwik-engine", version.ref = "jqwik" }
|
jqwik-engine = { module = "net.jqwik:jqwik-engine", version.ref = "jqwik" }
|
||||||
@@ -118,6 +125,12 @@ junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", vers
|
|||||||
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
||||||
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
|
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
|
||||||
|
|
||||||
|
# LWJGL
|
||||||
|
lwjgl-bom = { module = "org.lwjgl:lwjgl-bom", version.ref = "lwjgl" }
|
||||||
|
lwjgl-core = { module = "org.lwjgl:lwjgl" }
|
||||||
|
lwjgl-opengl = { module = "org.lwjgl:lwjgl-opengl" }
|
||||||
|
lwjgl-glfw = { module = "org.lwjgl:lwjgl-glfw" }
|
||||||
|
|
||||||
# Build tools
|
# Build tools
|
||||||
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
|
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
|
||||||
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
|
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
|
||||||
@@ -129,34 +142,47 @@ errorProne-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", versi
|
|||||||
errorProne-testHelpers = { module = "com.google.errorprone:error_prone_test_helpers", version.ref = "errorProne-core" }
|
errorProne-testHelpers = { module = "com.google.errorprone:error_prone_test_helpers", version.ref = "errorProne-core" }
|
||||||
fabric-loom = { module = "net.fabricmc:fabric-loom", version.ref = "fabric-loom" }
|
fabric-loom = { module = "net.fabricmc:fabric-loom", version.ref = "fabric-loom" }
|
||||||
forgeGradle = { module = "net.minecraftforge.gradle:ForgeGradle", version.ref = "forgeGradle" }
|
forgeGradle = { module = "net.minecraftforge.gradle:ForgeGradle", version.ref = "forgeGradle" }
|
||||||
|
ideaExt = { module = "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext", version.ref = "ideaExt" }
|
||||||
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
librarian = { module = "org.parchmentmc:librarian", version.ref = "librarian" }
|
librarian = { module = "org.parchmentmc:librarian", version.ref = "librarian" }
|
||||||
minotaur = { module = "com.modrinth.minotaur:Minotaur", version.ref = "minotaur" }
|
minotaur = { module = "com.modrinth.minotaur:Minotaur", version.ref = "minotaur" }
|
||||||
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
|
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
|
||||||
quiltflower = { module = "io.github.juuxel:loom-quiltflower", version.ref = "quiltflower" }
|
|
||||||
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
||||||
|
teavm-classlib = { module = "org.teavm:teavm-classlib", version.ref = "teavm" }
|
||||||
|
teavm-jso = { module = "org.teavm:teavm-jso", version.ref = "teavm" }
|
||||||
|
teavm-jso-apis = { module = "org.teavm:teavm-jso-apis", version.ref = "teavm" }
|
||||||
|
teavm-jso-impl = { module = "org.teavm:teavm-jso-impl", version.ref = "teavm" }
|
||||||
|
teavm-metaprogramming-api = { module = "org.teavm:teavm-metaprogramming-api", version.ref = "teavm" }
|
||||||
|
teavm-metaprogramming-impl = { module = "org.teavm:teavm-metaprogramming-impl", version.ref = "teavm" }
|
||||||
|
teavm-platform = { module = "org.teavm:teavm-platform", version.ref = "teavm" }
|
||||||
|
teavm-tooling = { module = "org.teavm:teavm-tooling", version.ref = "teavm" }
|
||||||
vanillaGradle = { module = "org.spongepowered:vanillagradle", version.ref = "vanillaGradle" }
|
vanillaGradle = { module = "org.spongepowered:vanillagradle", version.ref = "vanillaGradle" }
|
||||||
|
vineflower = { module = "io.github.juuxel:loom-vineflower", version.ref = "vineflower" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" }
|
forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" }
|
||||||
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
|
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
|
||||||
ideaExt = { id = "org.jetbrains.gradle.plugin.idea-ext", version.ref = "ideaExt" }
|
|
||||||
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
librarian = { id = "org.parchmentmc.librarian.forgegradle", version.ref = "librarian" }
|
librarian = { id = "org.parchmentmc.librarian.forgegradle", version.ref = "librarian" }
|
||||||
mixinGradle = { id = "org.spongepowered.mixin", version.ref = "mixinGradle" }
|
mixinGradle = { id = "org.spongepowered.mixin", version.ref = "mixinGradle" }
|
||||||
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
|
annotations = ["jsr305", "checkerFramework", "jetbrainsAnnotations"]
|
||||||
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
||||||
|
|
||||||
# Minecraft
|
# Minecraft
|
||||||
externalMods-common = ["jei-api", "nightConfig-core", "nightConfig-toml"]
|
externalMods-common = ["jei-api", "nightConfig-core", "nightConfig-toml"]
|
||||||
externalMods-forge-compile = ["oculus", "jei-api"]
|
externalMods-forge-compile = ["moreRed", "oculus", "jei-api"]
|
||||||
externalMods-forge-runtime = ["jei-forge"]
|
externalMods-forge-runtime = ["jei-forge"]
|
||||||
externalMods-fabric = ["nightConfig-core", "nightConfig-toml"]
|
externalMods-fabric = ["nightConfig-core", "nightConfig-toml"]
|
||||||
externalMods-fabric-compile = ["iris", "jei-api", "rei-api", "rei-builtin"]
|
externalMods-fabric-compile = ["fabricPermissions", "iris", "jei-api", "rei-api", "rei-builtin"]
|
||||||
externalMods-fabric-runtime = ["jei-fabric", "modmenu"]
|
externalMods-fabric-runtime = ["jei-fabric", "modmenu"]
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]
|
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]
|
||||||
testRuntime = ["junit-jupiter-engine", "jqwik-engine"]
|
testRuntime = ["junit-jupiter-engine", "jqwik-engine"]
|
||||||
|
|
||||||
|
# Build tools
|
||||||
|
teavm-api = [ "teavm-jso", "teavm-jso-apis", "teavm-platform", "teavm-classlib", "teavm-metaprogramming-api" ]
|
||||||
|
teavm-tooling = [ "teavm-tooling", "teavm-metaprogramming-impl", "teavm-jso-impl" ]
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
; SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
; SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
;
|
;
|
||||||
; SPDX-License-Identifier: LicenseRef-CCPL
|
; SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
(sources
|
(sources
|
||||||
/doc/
|
/doc/
|
||||||
@@ -10,8 +10,7 @@
|
|||||||
/projects/core/src/main/resources/data/computercraft/lua/bios.lua
|
/projects/core/src/main/resources/data/computercraft/lua/bios.lua
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/
|
/projects/core/src/main/resources/data/computercraft/lua/rom/
|
||||||
/projects/core/src/test/resources/test-rom
|
/projects/core/src/test/resources/test-rom
|
||||||
/projects/web/src/mount)
|
/projects/web/src/frontend/mount)
|
||||||
|
|
||||||
|
|
||||||
(doc
|
(doc
|
||||||
; Also defined in projects/web/build.gradle.kts
|
; Also defined in projects/web/build.gradle.kts
|
||||||
@@ -24,7 +23,7 @@
|
|||||||
(url https://tweaked.cc/)
|
(url https://tweaked.cc/)
|
||||||
(source-link https://github.com/cc-tweaked/CC-Tweaked/blob/${commit}/${path}#L${line})
|
(source-link https://github.com/cc-tweaked/CC-Tweaked/blob/${commit}/${path}#L${line})
|
||||||
|
|
||||||
(styles /projects/web/src/styles.css)
|
(styles /projects/web/build/rollup/index.css)
|
||||||
(scripts /projects/web/build/rollup/index.js)
|
(scripts /projects/web/build/rollup/index.js)
|
||||||
(head doc/head.html))
|
(head doc/head.html))
|
||||||
|
|
||||||
@@ -50,6 +49,8 @@
|
|||||||
(at /
|
(at /
|
||||||
(linters
|
(linters
|
||||||
syntax:string-index
|
syntax:string-index
|
||||||
|
doc:docusaurus-admonition
|
||||||
|
doc:ldoc-reference
|
||||||
|
|
||||||
;; It'd be nice to avoid this, but right now there's a lot of instances of
|
;; It'd be nice to avoid this, but right now there's a lot of instances of
|
||||||
;; it.
|
;; it.
|
||||||
@@ -76,29 +77,24 @@
|
|||||||
(globals
|
(globals
|
||||||
:max
|
:max
|
||||||
_CC_DEFAULT_SETTINGS
|
_CC_DEFAULT_SETTINGS
|
||||||
_CC_DISABLE_LUA51_FEATURES
|
|
||||||
_HOST
|
_HOST
|
||||||
;; Ideally we'd pick these up from bios.lua, but illuaminate currently
|
;; Ideally we'd pick these up from bios.lua, but illuaminate currently
|
||||||
;; isn't smart enough.
|
;; isn't smart enough.
|
||||||
sleep write printError read rs)))
|
sleep write printError read rs)))
|
||||||
|
|
||||||
;; We disable the unused global linter in bios.lua and the APIs. In the future
|
;; We disable the unused global linter in bios.lua, APIs and our documentation
|
||||||
;; hopefully we'll get illuaminate to handle this.
|
;; stubs docs. In the future hopefully we'll get illuaminate to handle this.
|
||||||
(at
|
(at
|
||||||
(/projects/core/src/main/resources/data/computercraft/lua/bios.lua
|
(/doc/stub/
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/)
|
/projects/core/src/main/resources/data/computercraft/lua/bios.lua
|
||||||
(linters -var:unused-global)
|
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/
|
||||||
(lint (allow-toplevel-global true)))
|
/projects/forge/build/docs/luaJavadoc/)
|
||||||
|
|
||||||
;; Silence some variable warnings in documentation stubs.
|
|
||||||
(at (/doc/stub/ /projects/forge/build/docs/luaJavadoc/)
|
|
||||||
(linters -var:unused-global)
|
(linters -var:unused-global)
|
||||||
(lint (allow-toplevel-global true)))
|
(lint (allow-toplevel-global true)))
|
||||||
|
|
||||||
;; Suppress warnings for currently undocumented modules.
|
;; Suppress warnings for currently undocumented modules.
|
||||||
(at
|
(at
|
||||||
(; Lua APIs
|
(; Lua APIs
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/io.lua
|
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/window.lua)
|
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/window.lua)
|
||||||
|
|
||||||
(linters -doc:undocumented -doc:undocumented-arg -doc:undocumented-return))
|
(linters -doc:undocumented -doc:undocumented-arg -doc:undocumented-return))
|
||||||
@@ -118,4 +114,4 @@
|
|||||||
:max sleep write
|
:max sleep write
|
||||||
cct_test describe expect howlci fail it pending stub before_each)))
|
cct_test describe expect howlci fail it pending stub before_each)))
|
||||||
|
|
||||||
(at /projects/web/src/mount/expr_template.lua (lint (globals :max __expr__)))
|
(at /projects/web/src/frontend/mount/expr_template.lua (lint (globals :max __expr__)))
|
||||||
|
3351
package-lock.json
generated
3351
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@@ -6,24 +6,24 @@
|
|||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@squid-dev/cc-web-term": "^2.0.0",
|
||||||
"preact": "^10.5.5",
|
"preact": "^10.5.5",
|
||||||
|
"setimmediate": "^1.0.5",
|
||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-terser": "^0.4.0",
|
"@rollup/plugin-node-resolve": "^15.2.1",
|
||||||
"@rollup/plugin-typescript": "^11.0.0",
|
"@rollup/plugin-typescript": "^11.0.0",
|
||||||
"@rollup/plugin-url": "^8.0.1",
|
"@rollup/plugin-url": "^8.0.1",
|
||||||
"@types/glob": "^8.1.0",
|
"@swc/core": "^1.3.92",
|
||||||
"@types/react-dom": "^18.0.5",
|
"@types/node": "^20.8.3",
|
||||||
"glob": "^9.3.0",
|
"lightningcss": "^1.22.0",
|
||||||
"react-dom": "^18.1.0",
|
"preact-render-to-string": "^6.2.1",
|
||||||
"react": "^18.1.0",
|
"rehype": "^13.0.0",
|
||||||
"rehype-highlight": "^6.0.0",
|
"rehype-highlight": "^7.0.0",
|
||||||
"rehype-react": "^7.1.1",
|
"rehype-react": "^8.0.0",
|
||||||
"rehype": "^12.0.1",
|
"rollup": "^4.0.0",
|
||||||
"requirejs": "^2.3.6",
|
"tsx": "^3.12.10",
|
||||||
"rollup": "^3.19.1",
|
"typescript": "^5.2.2"
|
||||||
"ts-node": "^10.8.0",
|
|
||||||
"typescript": "^4.0.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -62,6 +62,9 @@ mentioning:
|
|||||||
- `lints`: This defines an [ErrorProne] plugin which adds a couple of compile-time checks to our code. This is what
|
- `lints`: This defines an [ErrorProne] plugin which adds a couple of compile-time checks to our code. This is what
|
||||||
enforces that no client-specific code is used inside the `main` source set (and a couple of other things!).
|
enforces that no client-specific code is used inside the `main` source set (and a couple of other things!).
|
||||||
|
|
||||||
|
- `standalone`: This contains a standalone UI for computers, allowing debugging and development of CraftOS without
|
||||||
|
launching Minecraft.
|
||||||
|
|
||||||
- `web`: This contains the additional tooling for building [the documentation website][tweaked.cc], such as support for
|
- `web`: This contains the additional tooling for building [the documentation website][tweaked.cc], such as support for
|
||||||
rendering recipes
|
rendering recipes
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ import org.joml.Matrix4f;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
class TurtleUpgradeModellers {
|
final class TurtleUpgradeModellers {
|
||||||
private static final Transformation leftTransform = getMatrixFor(-0.4065f);
|
private static final Transformation leftTransform = getMatrixFor(-0.4065f);
|
||||||
private static final Transformation rightTransform = getMatrixFor(0.4065f);
|
private static final Transformation rightTransform = getMatrixFor(0.4065f);
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ class TurtleUpgradeModellers {
|
|||||||
|
|
||||||
static final TurtleUpgradeModeller<ITurtleUpgrade> UPGRADE_ITEM = new UpgradeItemModeller();
|
static final TurtleUpgradeModeller<ITurtleUpgrade> UPGRADE_ITEM = new UpgradeItemModeller();
|
||||||
|
|
||||||
private static class UpgradeItemModeller implements TurtleUpgradeModeller<ITurtleUpgrade> {
|
private static final class UpgradeItemModeller implements TurtleUpgradeModeller<ITurtleUpgrade> {
|
||||||
@Override
|
@Override
|
||||||
public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
||||||
return getModel(turtle == null ? upgrade.getCraftingItem() : upgrade.getUpgradeItem(turtle.getUpgradeNBTData(side)), side);
|
return getModel(turtle == null ? upgrade.getCraftingItem() : upgrade.getUpgradeItem(turtle.getUpgradeNBTData(side)), side);
|
||||||
|
@@ -46,6 +46,14 @@ public class ComputerCraftTags {
|
|||||||
public static final TagKey<Block> WIRED_MODEM = make("wired_modem");
|
public static final TagKey<Block> WIRED_MODEM = make("wired_modem");
|
||||||
public static final TagKey<Block> MONITOR = make("monitor");
|
public static final TagKey<Block> MONITOR = make("monitor");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which should be ignored by a {@code peripheral_hub} peripheral.
|
||||||
|
* <p>
|
||||||
|
* This should include blocks which themselves expose a peripheral hub (such as {@linkplain #WIRED_MODEM wired
|
||||||
|
* modems}).
|
||||||
|
*/
|
||||||
|
public static final TagKey<Block> PERIPHERAL_HUB_IGNORE = make("peripheral_hub_ignore");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocks which can be broken by any turtle tool.
|
* Blocks which can be broken by any turtle tool.
|
||||||
*/
|
*/
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.pocket;
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||||
@@ -30,14 +29,6 @@ import java.util.function.Function;
|
|||||||
* @see PocketUpgradeDataProvider
|
* @see PocketUpgradeDataProvider
|
||||||
*/
|
*/
|
||||||
public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends UpgradeSerialiser<T> {
|
public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends UpgradeSerialiser<T> {
|
||||||
/**
|
|
||||||
* The ID for the associated registry.
|
|
||||||
*
|
|
||||||
* @deprecated Use {@link #registryId()} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
ResourceKey<Registry<PocketUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade_serialiser"));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID for the associated registry.
|
* The ID for the associated registry.
|
||||||
*
|
*
|
||||||
|
@@ -16,7 +16,6 @@ import net.minecraft.nbt.CompoundTag;
|
|||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -71,29 +70,6 @@ public interface ITurtleAccess {
|
|||||||
*/
|
*/
|
||||||
boolean teleportTo(Level world, BlockPos pos);
|
boolean teleportTo(Level world, BlockPos pos);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a vector containing the floating point co-ordinates at which the turtle is rendered.
|
|
||||||
* This will shift when the turtle is moving.
|
|
||||||
*
|
|
||||||
* @param f The subframe fraction.
|
|
||||||
* @return A vector containing the floating point co-ordinates at which the turtle resides.
|
|
||||||
* @see #getVisualYaw(float)
|
|
||||||
* @deprecated Will be removed in 1.20.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
Vec3 getVisualPosition(float f);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the yaw the turtle is facing when it is rendered.
|
|
||||||
*
|
|
||||||
* @param f The subframe fraction.
|
|
||||||
* @return The yaw the turtle is facing.
|
|
||||||
* @see #getVisualPosition(float)
|
|
||||||
* @deprecated Will be removed in 1.20.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
float getVisualYaw(float f);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the world direction the turtle is currently facing.
|
* Returns the world direction the turtle is currently facing.
|
||||||
*
|
*
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.turtle;
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||||
@@ -65,14 +64,6 @@ import java.util.function.Function;
|
|||||||
* @see dan200.computercraft.api.client.turtle.TurtleUpgradeModeller
|
* @see dan200.computercraft.api.client.turtle.TurtleUpgradeModeller
|
||||||
*/
|
*/
|
||||||
public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends UpgradeSerialiser<T> {
|
public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends UpgradeSerialiser<T> {
|
||||||
/**
|
|
||||||
* The ID for the associated registry.
|
|
||||||
*
|
|
||||||
* @deprecated Use {@link #registryId()} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade_serialiser"));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID for the associated registry.
|
* The ID for the associated registry.
|
||||||
*
|
*
|
||||||
|
@@ -19,8 +19,6 @@ import net.minecraft.data.PackOutput;
|
|||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -36,8 +34,6 @@ import java.util.function.Function;
|
|||||||
* @param <R> The upgrade serialiser to register for.
|
* @param <R> The upgrade serialiser to register for.
|
||||||
*/
|
*/
|
||||||
public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends UpgradeSerialiser<? extends T>> implements DataProvider {
|
public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends UpgradeSerialiser<? extends T>> implements DataProvider {
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
|
||||||
|
|
||||||
private final PackOutput output;
|
private final PackOutput output;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String folder;
|
private final String folder;
|
||||||
|
@@ -7,9 +7,9 @@ import cc.tweaked.gradle.clientClasses
|
|||||||
import cc.tweaked.gradle.commonClasses
|
import cc.tweaked.gradle.commonClasses
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("cc-tweaked.publishing")
|
|
||||||
id("cc-tweaked.vanilla")
|
id("cc-tweaked.vanilla")
|
||||||
id("cc-tweaked.gametest")
|
id("cc-tweaked.gametest")
|
||||||
|
id("cc-tweaked.publishing")
|
||||||
}
|
}
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
@@ -39,4 +39,6 @@ dependencies {
|
|||||||
testModImplementation(testFixtures(project(":core")))
|
testModImplementation(testFixtures(project(":core")))
|
||||||
testModImplementation(testFixtures(project(":common")))
|
testModImplementation(testFixtures(project(":common")))
|
||||||
testModImplementation(libs.bundles.kotlin)
|
testModImplementation(libs.bundles.kotlin)
|
||||||
|
|
||||||
|
testFixturesImplementation(testFixtures(project(":core")))
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
|||||||
import dan200.computercraft.shared.computer.inventory.ViewComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.ViewComputerMenu;
|
||||||
import dan200.computercraft.shared.media.items.DiskItem;
|
import dan200.computercraft.shared.media.items.DiskItem;
|
||||||
import dan200.computercraft.shared.media.items.TreasureDiskItem;
|
import dan200.computercraft.shared.media.items.TreasureDiskItem;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.color.item.ItemColor;
|
import net.minecraft.client.color.item.ItemColor;
|
||||||
import net.minecraft.client.gui.screens.MenuScreens;
|
import net.minecraft.client.gui.screens.MenuScreens;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
@@ -30,6 +31,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
|
|||||||
import net.minecraft.client.renderer.item.ClampedItemPropertyFunction;
|
import net.minecraft.client.renderer.item.ClampedItemPropertyFunction;
|
||||||
import net.minecraft.client.renderer.item.ItemProperties;
|
import net.minecraft.client.renderer.item.ItemProperties;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
||||||
import net.minecraft.server.packs.resources.ResourceProvider;
|
import net.minecraft.server.packs.resources.ResourceProvider;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
@@ -107,6 +109,10 @@ public final class ClientRegistry {
|
|||||||
for (var item : items) ItemProperties.register(item.get(), id, getter);
|
for (var item : items) ItemProperties.register(item.get(), id, getter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void registerReloadListeners(Consumer<PreparableReloadListener> register, Minecraft minecraft) {
|
||||||
|
register.accept(GuiSprites.initialise(minecraft.getTextureManager()));
|
||||||
|
}
|
||||||
|
|
||||||
private static final String[] EXTRA_MODELS = new String[]{
|
private static final String[] EXTRA_MODELS = new String[]{
|
||||||
"block/turtle_colour",
|
"block/turtle_colour",
|
||||||
"block/turtle_elf_overlay",
|
"block/turtle_elf_overlay",
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||||
import dan200.computercraft.client.gui.widgets.DynamicImageButton;
|
import dan200.computercraft.client.gui.widgets.DynamicImageButton;
|
||||||
import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
||||||
@@ -19,6 +18,7 @@ import dan200.computercraft.shared.config.Config;
|
|||||||
import dan200.computercraft.shared.network.server.UploadFileMessage;
|
import dan200.computercraft.shared.network.server.UploadFileMessage;
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
@@ -33,7 +33,6 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@@ -124,10 +123,10 @@ public abstract class AbstractComputerScreen<T extends AbstractComputerMenu> ext
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground(stack);
|
renderBackground(graphics);
|
||||||
super.render(stack, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(stack, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -147,7 +146,7 @@ public abstract class AbstractComputerScreen<T extends AbstractComputerMenu> ext
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderLabels(PoseStack transform, int mouseX, int mouseY) {
|
protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
|
||||||
// Skip rendering labels.
|
// Skip rendering labels.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +218,7 @@ public abstract class AbstractComputerScreen<T extends AbstractComputerMenu> ext
|
|||||||
|
|
||||||
private void alert(Component title, Component message) {
|
private void alert(Component title, Component message) {
|
||||||
OptionScreen.show(minecraft, title, message,
|
OptionScreen.show(minecraft, title, message,
|
||||||
Collections.singletonList(OptionScreen.newButton(OK, b -> minecraft.setScreen(this))),
|
List.of(OptionScreen.newButton(OK, b -> minecraft.setScreen(this))),
|
||||||
() -> minecraft.setScreen(this)
|
() -> minecraft.setScreen(this)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -4,16 +4,17 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||||
import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
||||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||||
|
import dan200.computercraft.client.render.RenderTypes;
|
||||||
|
import dan200.computercraft.client.render.SpriteRenderer;
|
||||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
|
||||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
||||||
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A GUI for computers which renders the terminal (and border), but with no UI elements.
|
* A GUI for computers which renders the terminal (and border), but with no UI elements.
|
||||||
@@ -36,13 +37,17 @@ public final class ComputerScreen<T extends AbstractComputerMenu> extends Abstra
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderBg(PoseStack stack, float partialTicks, int mouseX, int mouseY) {
|
public void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
||||||
// Draw a border around the terminal
|
// Draw a border around the terminal
|
||||||
var terminal = getTerminal();
|
var terminal = getTerminal();
|
||||||
|
var spriteRenderer = SpriteRenderer.createForGui(graphics, RenderTypes.GUI_SPRITES);
|
||||||
|
var computerTextures = GuiSprites.getComputerTextures(family);
|
||||||
|
|
||||||
ComputerBorderRenderer.render(
|
ComputerBorderRenderer.render(
|
||||||
stack.last().pose(), ComputerBorderRenderer.getTexture(family), terminal.getX(), terminal.getY(),
|
spriteRenderer, computerTextures,
|
||||||
FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight()
|
terminal.getX(), terminal.getY(), terminal.getWidth(), terminal.getHeight(), false
|
||||||
);
|
);
|
||||||
ComputerSidebar.renderBackground(stack, leftPos, topPos + sidebarYOffset);
|
ComputerSidebar.renderBackground(spriteRenderer, computerTextures, leftPos, topPos + sidebarYOffset);
|
||||||
|
graphics.flush(); // Flush to ensure background textures are drawn before foreground.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveMenu;
|
import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveMenu;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@@ -23,16 +22,14 @@ public class DiskDriveScreen extends AbstractContainerScreen<DiskDriveMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderBg(PoseStack transform, float partialTicks, int mouseX, int mouseY) {
|
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
||||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight);
|
||||||
RenderSystem.setShaderTexture(0, BACKGROUND);
|
|
||||||
blit(transform, leftPos, topPos, 0, 0, imageWidth, imageHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(PoseStack transform, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground(transform);
|
renderBackground(graphics);
|
||||||
super.render(transform, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(transform, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,127 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||||
|
import dan200.computercraft.data.client.ClientDataProviders;
|
||||||
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureManager;
|
||||||
|
import net.minecraft.client.resources.TextureAtlasHolder;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sprite sheet for all GUI texutres in the mod.
|
||||||
|
*/
|
||||||
|
public final class GuiSprites extends TextureAtlasHolder {
|
||||||
|
public static final ResourceLocation SPRITE_SHEET = new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui");
|
||||||
|
public static final ResourceLocation TEXTURE = SPRITE_SHEET.withPath(x -> "textures/atlas/" + x + ".png");
|
||||||
|
|
||||||
|
public static final ButtonTextures TURNED_OFF = button("turned_off");
|
||||||
|
public static final ButtonTextures TURNED_ON = button("turned_on");
|
||||||
|
public static final ButtonTextures TERMINATE = button("terminate");
|
||||||
|
|
||||||
|
public static final ComputerTextures COMPUTER_NORMAL = computer("normal", true, true);
|
||||||
|
public static final ComputerTextures COMPUTER_ADVANCED = computer("advanced", true, true);
|
||||||
|
public static final ComputerTextures COMPUTER_COMMAND = computer("command", false, true);
|
||||||
|
public static final ComputerTextures COMPUTER_COLOUR = computer("colour", true, false);
|
||||||
|
|
||||||
|
private static ButtonTextures button(String name) {
|
||||||
|
return new ButtonTextures(
|
||||||
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name),
|
||||||
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name + "_hover")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ComputerTextures computer(String name, boolean pocket, boolean sidebar) {
|
||||||
|
return new ComputerTextures(
|
||||||
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/border_" + name),
|
||||||
|
pocket ? new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/pocket_bottom_" + name) : null,
|
||||||
|
sidebar ? new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/sidebar_" + name) : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @Nullable GuiSprites instance;
|
||||||
|
|
||||||
|
private GuiSprites(TextureManager textureManager) {
|
||||||
|
super(textureManager, TEXTURE, SPRITE_SHEET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the singleton {@link GuiSprites} instance.
|
||||||
|
*
|
||||||
|
* @param textureManager The current texture manager.
|
||||||
|
* @return The singleton {@link GuiSprites} instance, to register as resource reload listener.
|
||||||
|
*/
|
||||||
|
public static GuiSprites initialise(TextureManager textureManager) {
|
||||||
|
if (instance != null) throw new IllegalStateException("GuiSprites has already been initialised");
|
||||||
|
return instance = new GuiSprites(textureManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup a texture on the atlas.
|
||||||
|
*
|
||||||
|
* @param texture The texture to find.
|
||||||
|
* @return The sprite on the atlas.
|
||||||
|
*/
|
||||||
|
public static TextureAtlasSprite get(ResourceLocation texture) {
|
||||||
|
if (instance == null) throw new IllegalStateException("GuiSprites has not been initialised");
|
||||||
|
return instance.getSprite(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the appropriate textures to use for a particular computer family.
|
||||||
|
*
|
||||||
|
* @param family The computer family.
|
||||||
|
* @return The family-specific textures.
|
||||||
|
*/
|
||||||
|
public static ComputerTextures getComputerTextures(ComputerFamily family) {
|
||||||
|
return switch (family) {
|
||||||
|
case NORMAL -> COMPUTER_NORMAL;
|
||||||
|
case ADVANCED -> COMPUTER_ADVANCED;
|
||||||
|
case COMMAND -> COMPUTER_COMMAND;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of sprites for a button, with both a normal and "active" state.
|
||||||
|
*
|
||||||
|
* @param normal The normal texture for the button.
|
||||||
|
* @param active The texture for the button when it is active (hovered or focused).
|
||||||
|
*/
|
||||||
|
public record ButtonTextures(ResourceLocation normal, ResourceLocation active) {
|
||||||
|
public TextureAtlasSprite get(boolean active) {
|
||||||
|
return GuiSprites.get(active ? this.active : normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<ResourceLocation> textures() {
|
||||||
|
return Stream.of(normal, active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the set of sprites for a computer family.
|
||||||
|
*
|
||||||
|
* @param border The texture for the computer's border.
|
||||||
|
* @param pocketBottom The texture for the bottom of a pocket computer.
|
||||||
|
* @param sidebar The texture for the computer sidebar.
|
||||||
|
* @see ComputerBorderRenderer
|
||||||
|
* @see ClientDataProviders
|
||||||
|
*/
|
||||||
|
public record ComputerTextures(
|
||||||
|
ResourceLocation border,
|
||||||
|
@Nullable ResourceLocation pocketBottom,
|
||||||
|
@Nullable ResourceLocation sidebar
|
||||||
|
) {
|
||||||
|
public Stream<ResourceLocation> textures() {
|
||||||
|
return Stream.of(border, pocketBottom, sidebar).filter(Objects::nonNull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -4,10 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiComponent;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.components.toasts.Toast;
|
import net.minecraft.client.gui.components.toasts.Toast;
|
||||||
import net.minecraft.client.gui.components.toasts.ToastComponent;
|
import net.minecraft.client.gui.components.toasts.ToastComponent;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
@@ -73,55 +71,52 @@ public class ItemToast implements Toast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Visibility render(PoseStack transform, ToastComponent component, long time) {
|
public Visibility render(GuiGraphics graphics, ToastComponent component, long time) {
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
|
|
||||||
firstDisplay = time;
|
firstDisplay = time;
|
||||||
isNew = false;
|
isNew = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderSystem.setShaderTexture(0, TEXTURE);
|
|
||||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
|
||||||
|
|
||||||
if (width == 160 && message.size() <= 1) {
|
if (width == 160 && message.size() <= 1) {
|
||||||
GuiComponent.blit(transform, 0, 0, 0, 64, width, height());
|
graphics.blit(TEXTURE, 0, 0, 0, 64, width, height());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
var height = height();
|
var height = height();
|
||||||
|
|
||||||
var bottom = Math.min(4, height - 28);
|
var bottom = Math.min(4, height - 28);
|
||||||
renderBackgroundRow(transform, component, width, 0, 0, 28);
|
renderBackgroundRow(graphics, width, 0, 0, 28);
|
||||||
|
|
||||||
for (var i = 28; i < height - bottom; i += 10) {
|
for (var i = 28; i < height - bottom; i += 10) {
|
||||||
renderBackgroundRow(transform, component, width, 16, i, Math.min(16, height - i - bottom));
|
renderBackgroundRow(graphics, width, 16, i, Math.min(16, height - i - bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBackgroundRow(transform, component, width, 32 - bottom, height - bottom, bottom);
|
renderBackgroundRow(graphics, width, 32 - bottom, height - bottom, bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
var textX = MARGIN;
|
var textX = MARGIN;
|
||||||
if (!stack.isEmpty()) {
|
if (!stack.isEmpty()) {
|
||||||
textX += MARGIN + IMAGE_SIZE;
|
textX += MARGIN + IMAGE_SIZE;
|
||||||
component.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(transform, stack, MARGIN, MARGIN + height() / 2 - IMAGE_SIZE);
|
graphics.renderFakeItem(stack, MARGIN, MARGIN + height() / 2 - IMAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
component.getMinecraft().font.draw(transform, title, textX, MARGIN, 0xff500050);
|
graphics.drawString(component.getMinecraft().font, title, textX, MARGIN, 0xff500050, false);
|
||||||
for (var i = 0; i < message.size(); ++i) {
|
for (var i = 0; i < message.size(); ++i) {
|
||||||
component.getMinecraft().font.draw(transform, message.get(i), textX, (float) (LINE_SPACING + (i + 1) * LINE_SPACING), 0xff000000);
|
graphics.drawString(component.getMinecraft().font, message.get(i), textX, LINE_SPACING + (i + 1) * LINE_SPACING, 0xff000000, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return time - firstDisplay < DISPLAY_TIME ? Visibility.SHOW : Visibility.HIDE;
|
return time - firstDisplay < DISPLAY_TIME ? Visibility.SHOW : Visibility.HIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderBackgroundRow(PoseStack transform, ToastComponent component, int x, int u, int y, int height) {
|
private static void renderBackgroundRow(GuiGraphics graphics, int x, int u, int y, int height) {
|
||||||
var leftOffset = 5;
|
var leftOffset = 5;
|
||||||
var rightOffset = Math.min(60, x - leftOffset);
|
var rightOffset = Math.min(60, x - leftOffset);
|
||||||
|
|
||||||
GuiComponent.blit(transform, 0, y, 0, 32 + u, leftOffset, height);
|
graphics.blit(TEXTURE, 0, y, 0, 32 + u, leftOffset, height);
|
||||||
for (var k = leftOffset; k < x - rightOffset; k += 64) {
|
for (var k = leftOffset; k < x - rightOffset; k += 64) {
|
||||||
GuiComponent.blit(transform, k, y, 32, 32 + u, Math.min(64, x - k - rightOffset), height);
|
graphics.blit(TEXTURE, k, y, 32, 32 + u, Math.min(64, x - k - rightOffset), height);
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiComponent.blit(transform, x - rightOffset, y, 160 - rightOffset, 32 + u, rightOffset, height);
|
graphics.blit(TEXTURE, x - rightOffset, y, 160 - rightOffset, 32 + u, rightOffset, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: LicenseRef-CCPL
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||||
import net.minecraft.client.KeyMapping;
|
import net.minecraft.client.KeyMapping;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.client.gui.screens.inventory.MenuAccess;
|
import net.minecraft.client.gui.screens.inventory.MenuAccess;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
@@ -42,7 +42,6 @@ public class NoTermComputerScreen<T extends AbstractComputerMenu> extends Screen
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
passEvents = true; // Pass mouse vents through to the game's mouse handler.
|
|
||||||
// First ensure we're still grabbing the mouse, so the user can look around. Then reset bits of state that
|
// First ensure we're still grabbing the mouse, so the user can look around. Then reset bits of state that
|
||||||
// grabbing unsets.
|
// grabbing unsets.
|
||||||
minecraft.mouseHandler.grabMouse();
|
minecraft.mouseHandler.grabMouse();
|
||||||
@@ -91,15 +90,15 @@ public class NoTermComputerScreen<T extends AbstractComputerMenu> extends Screen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(PoseStack transform, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
super.render(transform, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
|
|
||||||
var font = minecraft.font;
|
var font = minecraft.font;
|
||||||
var lines = font.split(Component.translatable("gui.computercraft.pocket_computer_overlay"), (int) (width * 0.8));
|
var lines = font.split(Component.translatable("gui.computercraft.pocket_computer_overlay"), (int) (width * 0.8));
|
||||||
var y = 10.0f;
|
var y = 10;
|
||||||
for (var line : lines) {
|
for (var line : lines) {
|
||||||
font.drawShadow(transform, line, (float) ((width / 2) - (minecraft.font.width(line) / 2)), y, 0xFFFFFF);
|
graphics.drawString(font, line, (width / 2) - (minecraft.font.width(line) / 2), y, 0xFFFFFF, true);
|
||||||
y += 9.0f;
|
y += 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.components.AbstractWidget;
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
import net.minecraft.client.gui.components.MultiLineLabel;
|
import net.minecraft.client.gui.components.MultiLineLabel;
|
||||||
@@ -86,20 +85,19 @@ public final class OptionScreen extends Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(PoseStack transform, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground(transform);
|
renderBackground(graphics);
|
||||||
|
|
||||||
// Render the actual texture.
|
// Render the actual texture.
|
||||||
RenderSystem.setShaderTexture(0, BACKGROUND);
|
graphics.blit(BACKGROUND, x, y, 0, 0, innerWidth, PADDING);
|
||||||
blit(transform, x, y, 0, 0, innerWidth, PADDING);
|
graphics.blit(BACKGROUND,
|
||||||
blit(transform,
|
|
||||||
x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
|
x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
|
||||||
innerWidth, PADDING
|
innerWidth, PADDING
|
||||||
);
|
);
|
||||||
blit(transform, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING);
|
graphics.blit(BACKGROUND, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING);
|
||||||
|
|
||||||
assertNonNull(messageRenderer).renderLeftAlignedNoShadow(transform, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040);
|
assertNonNull(messageRenderer).renderLeftAlignedNoShadow(graphics, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040);
|
||||||
super.render(transform, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import dan200.computercraft.shared.peripheral.printer.PrinterMenu;
|
import dan200.computercraft.shared.peripheral.printer.PrinterMenu;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@@ -23,18 +22,16 @@ public class PrinterScreen extends AbstractContainerScreen<PrinterMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderBg(PoseStack transform, float partialTicks, int mouseX, int mouseY) {
|
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
||||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight);
|
||||||
RenderSystem.setShaderTexture(0, BACKGROUND);
|
|
||||||
blit(transform, leftPos, topPos, 0, 0, imageWidth, imageHeight);
|
|
||||||
|
|
||||||
if (getMenu().isPrinting()) blit(transform, leftPos + 34, topPos + 21, 176, 0, 25, 45);
|
if (getMenu().isPrinting()) graphics.blit(BACKGROUND, leftPos + 34, topPos + 21, 176, 0, 25, 45);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground(stack);
|
renderBackground(graphics);
|
||||||
super.render(stack, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(stack, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,12 +4,11 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import com.mojang.blaze3d.vertex.Tesselator;
|
import com.mojang.blaze3d.vertex.Tesselator;
|
||||||
import dan200.computercraft.core.terminal.TextBuffer;
|
import dan200.computercraft.core.terminal.TextBuffer;
|
||||||
import dan200.computercraft.shared.common.HeldItemMenu;
|
import dan200.computercraft.shared.common.HeldItemMenu;
|
||||||
import dan200.computercraft.shared.media.items.PrintoutItem;
|
import dan200.computercraft.shared.media.items.PrintoutItem;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
@@ -83,30 +82,27 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderBg(PoseStack transform, float partialTicks, int mouseX, int mouseY) {
|
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
||||||
// Draw the printout
|
// Draw the printout
|
||||||
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
RenderSystem.enableDepthTest();
|
|
||||||
|
|
||||||
var renderer = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
var renderer = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
||||||
drawBorder(transform, renderer, leftPos, topPos, 0, page, pages, book, FULL_BRIGHT_LIGHTMAP);
|
drawBorder(graphics.pose(), renderer, leftPos, topPos, 0, page, pages, book, FULL_BRIGHT_LIGHTMAP);
|
||||||
drawText(transform, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutItem.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours);
|
drawText(graphics.pose(), renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutItem.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours);
|
||||||
renderer.endBatch();
|
renderer.endBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
// We must take the background further back in order to not overlap with our printed pages.
|
// We must take the background further back in order to not overlap with our printed pages.
|
||||||
stack.pushPose();
|
graphics.pose().pushPose();
|
||||||
stack.translate(0, 0, -1);
|
graphics.pose().translate(0, 0, -1);
|
||||||
renderBackground(stack);
|
renderBackground(graphics);
|
||||||
stack.popPose();
|
graphics.pose().popPose();
|
||||||
|
|
||||||
super.render(stack, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderLabels(PoseStack transform, int mouseX, int mouseY) {
|
protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
|
||||||
// Skip rendering labels.
|
// Skip rendering labels.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,15 +4,15 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||||
import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
||||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
import dan200.computercraft.client.render.RenderTypes;
|
||||||
|
import dan200.computercraft.client.render.SpriteRenderer;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||||
import dan200.computercraft.shared.turtle.inventory.TurtleMenu;
|
import dan200.computercraft.shared.turtle.inventory.TurtleMenu;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
@@ -44,23 +44,25 @@ public class TurtleScreen extends AbstractComputerScreen<TurtleMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderBg(PoseStack transform, float partialTicks, int mouseX, int mouseY) {
|
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
||||||
var advanced = family == ComputerFamily.ADVANCED;
|
var advanced = family == ComputerFamily.ADVANCED;
|
||||||
RenderSystem.setShaderTexture(0, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL);
|
var texture = advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL;
|
||||||
blit(transform, leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, 0, TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE);
|
graphics.blit(texture, leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, 0, TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE);
|
||||||
|
|
||||||
// Render selected slot
|
// Render selected slot
|
||||||
var slot = getMenu().getSelectedSlot();
|
var slot = getMenu().getSelectedSlot();
|
||||||
if (slot >= 0) {
|
if (slot >= 0) {
|
||||||
var slotX = slot % 4;
|
var slotX = slot % 4;
|
||||||
var slotY = slot / 4;
|
var slotY = slot / 4;
|
||||||
blit(transform,
|
graphics.blit(texture,
|
||||||
leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, 0,
|
leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, 0,
|
||||||
0, 217, 24, 24, FULL_TEX_SIZE, FULL_TEX_SIZE
|
0, 217, 24, 24, FULL_TEX_SIZE, FULL_TEX_SIZE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderSystem.setShaderTexture(0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL);
|
// Render sidebar
|
||||||
ComputerSidebar.renderBackground(transform, leftPos, topPos + sidebarYOffset);
|
var spriteRenderer = SpriteRenderer.createForGui(graphics, RenderTypes.GUI_SPRITES);
|
||||||
|
ComputerSidebar.renderBackground(spriteRenderer, GuiSprites.getComputerTextures(family), leftPos, topPos + sidebarYOffset);
|
||||||
|
graphics.flush(); // Flush to ensure background textures are drawn before foreground.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,16 +4,13 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui.widgets;
|
package dan200.computercraft.client.gui.widgets;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import dan200.computercraft.client.gui.GuiSprites;
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.client.gui.widgets.DynamicImageButton.HintedMessage;
|
import dan200.computercraft.client.gui.widgets.DynamicImageButton.HintedMessage;
|
||||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
import dan200.computercraft.client.render.SpriteRenderer;
|
||||||
import dan200.computercraft.shared.computer.core.InputHandler;
|
import dan200.computercraft.shared.computer.core.InputHandler;
|
||||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||||
import net.minecraft.client.gui.components.AbstractWidget;
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -22,22 +19,18 @@ import java.util.function.Consumer;
|
|||||||
* Registers buttons to interact with a computer.
|
* Registers buttons to interact with a computer.
|
||||||
*/
|
*/
|
||||||
public final class ComputerSidebar {
|
public final class ComputerSidebar {
|
||||||
private static final ResourceLocation TEXTURE = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/buttons.png");
|
|
||||||
|
|
||||||
private static final int TEX_SIZE = 64;
|
|
||||||
|
|
||||||
private static final int ICON_WIDTH = 12;
|
private static final int ICON_WIDTH = 12;
|
||||||
private static final int ICON_HEIGHT = 12;
|
private static final int ICON_HEIGHT = 12;
|
||||||
private static final int ICON_MARGIN = 2;
|
private static final int ICON_MARGIN = 2;
|
||||||
|
|
||||||
private static final int ICON_TEX_Y_DIFF = 14;
|
|
||||||
|
|
||||||
private static final int CORNERS_BORDER = 3;
|
private static final int CORNERS_BORDER = 3;
|
||||||
private static final int FULL_BORDER = CORNERS_BORDER + ICON_MARGIN;
|
private static final int FULL_BORDER = CORNERS_BORDER + ICON_MARGIN;
|
||||||
|
|
||||||
private static final int BUTTONS = 2;
|
private static final int BUTTONS = 2;
|
||||||
private static final int HEIGHT = (ICON_HEIGHT + ICON_MARGIN * 2) * BUTTONS + CORNERS_BORDER * 2;
|
private static final int HEIGHT = (ICON_HEIGHT + ICON_MARGIN * 2) * BUTTONS + CORNERS_BORDER * 2;
|
||||||
|
|
||||||
|
private static final int TEX_HEIGHT = 14;
|
||||||
|
|
||||||
private ComputerSidebar() {
|
private ComputerSidebar() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,16 +44,18 @@ public final class ComputerSidebar {
|
|||||||
Component.translatable("gui.computercraft.tooltip.turn_off.key")
|
Component.translatable("gui.computercraft.tooltip.turn_off.key")
|
||||||
);
|
);
|
||||||
add.accept(new DynamicImageButton(
|
add.accept(new DynamicImageButton(
|
||||||
x, y, ICON_WIDTH, ICON_HEIGHT, () -> isOn.getAsBoolean() ? 15 : 1, 1, ICON_TEX_Y_DIFF,
|
x, y, ICON_WIDTH, ICON_HEIGHT,
|
||||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer(isOn, input),
|
h -> isOn.getAsBoolean() ? GuiSprites.TURNED_ON.get(h) : GuiSprites.TURNED_OFF.get(h),
|
||||||
|
b -> toggleComputer(isOn, input),
|
||||||
() -> isOn.getAsBoolean() ? turnOff : turnOn
|
() -> isOn.getAsBoolean() ? turnOff : turnOn
|
||||||
));
|
));
|
||||||
|
|
||||||
y += ICON_HEIGHT + ICON_MARGIN * 2;
|
y += ICON_HEIGHT + ICON_MARGIN * 2;
|
||||||
|
|
||||||
add.accept(new DynamicImageButton(
|
add.accept(new DynamicImageButton(
|
||||||
x, y, ICON_WIDTH, ICON_HEIGHT, 29, 1, ICON_TEX_Y_DIFF,
|
x, y, ICON_WIDTH, ICON_HEIGHT,
|
||||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> input.queueEvent("terminate"),
|
GuiSprites.TERMINATE::get,
|
||||||
|
b -> input.queueEvent("terminate"),
|
||||||
new HintedMessage(
|
new HintedMessage(
|
||||||
Component.translatable("gui.computercraft.tooltip.terminate"),
|
Component.translatable("gui.computercraft.tooltip.terminate"),
|
||||||
Component.translatable("gui.computercraft.tooltip.terminate.key")
|
Component.translatable("gui.computercraft.tooltip.terminate.key")
|
||||||
@@ -68,22 +63,12 @@ public final class ComputerSidebar {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renderBackground(PoseStack transform, int x, int y) {
|
public static void renderBackground(SpriteRenderer renderer, GuiSprites.ComputerTextures textures, int x, int y) {
|
||||||
Screen.blit(transform,
|
var texture = textures.sidebar();
|
||||||
x, y, 0, 102, AbstractComputerMenu.SIDEBAR_WIDTH, FULL_BORDER,
|
if (texture == null) throw new NullPointerException(textures + " has no sidebar texture");
|
||||||
ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
|
var sprite = GuiSprites.get(texture);
|
||||||
);
|
|
||||||
|
|
||||||
Screen.blit(transform,
|
renderer.blitVerticalSliced(sprite, x, y, AbstractComputerMenu.SIDEBAR_WIDTH, HEIGHT, FULL_BORDER, FULL_BORDER, TEX_HEIGHT);
|
||||||
x, y + FULL_BORDER, AbstractComputerMenu.SIDEBAR_WIDTH, HEIGHT - FULL_BORDER * 2,
|
|
||||||
0, 107, AbstractComputerMenu.SIDEBAR_WIDTH, 4,
|
|
||||||
ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
|
|
||||||
);
|
|
||||||
|
|
||||||
Screen.blit(transform,
|
|
||||||
x, y + HEIGHT - FULL_BORDER, 0, 111, AbstractComputerMenu.SIDEBAR_WIDTH, FULL_BORDER,
|
|
||||||
ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void toggleComputer(BooleanSupplier isOn, InputHandler input) {
|
private static void toggleComputer(BooleanSupplier isOn, InputHandler input) {
|
||||||
|
@@ -5,15 +5,15 @@
|
|||||||
package dan200.computercraft.client.gui.widgets;
|
package dan200.computercraft.client.gui.widgets;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import it.unimi.dsi.fastutil.booleans.Boolean2ObjectFunction;
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
import net.minecraft.client.gui.components.Tooltip;
|
import net.minecraft.client.gui.components.Tooltip;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.function.IntSupplier;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,59 +21,41 @@ import java.util.function.Supplier;
|
|||||||
* dynamically.
|
* dynamically.
|
||||||
*/
|
*/
|
||||||
public class DynamicImageButton extends Button {
|
public class DynamicImageButton extends Button {
|
||||||
private final ResourceLocation texture;
|
private final Boolean2ObjectFunction<TextureAtlasSprite> texture;
|
||||||
private final IntSupplier xTexStart;
|
|
||||||
private final int yTexStart;
|
|
||||||
private final int yDiffTex;
|
|
||||||
private final int textureWidth;
|
|
||||||
private final int textureHeight;
|
|
||||||
private final Supplier<HintedMessage> message;
|
private final Supplier<HintedMessage> message;
|
||||||
|
|
||||||
public DynamicImageButton(
|
public DynamicImageButton(
|
||||||
int x, int y, int width, int height, int xTexStart, int yTexStart, int yDiffTex,
|
int x, int y, int width, int height, Boolean2ObjectFunction<TextureAtlasSprite> texture, OnPress onPress,
|
||||||
ResourceLocation texture, int textureWidth, int textureHeight,
|
HintedMessage message
|
||||||
OnPress onPress, HintedMessage message
|
|
||||||
) {
|
) {
|
||||||
this(
|
this(x, y, width, height, texture, onPress, () -> message);
|
||||||
x, y, width, height, () -> xTexStart, yTexStart, yDiffTex,
|
|
||||||
texture, textureWidth, textureHeight,
|
|
||||||
onPress, () -> message
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DynamicImageButton(
|
public DynamicImageButton(
|
||||||
int x, int y, int width, int height, IntSupplier xTexStart, int yTexStart, int yDiffTex,
|
int x, int y, int width, int height,
|
||||||
ResourceLocation texture, int textureWidth, int textureHeight,
|
Boolean2ObjectFunction<TextureAtlasSprite> texture,
|
||||||
OnPress onPress, Supplier<HintedMessage> message
|
OnPress onPress, Supplier<HintedMessage> message
|
||||||
) {
|
) {
|
||||||
super(x, y, width, height, Component.empty(), onPress, DEFAULT_NARRATION);
|
super(x, y, width, height, Component.empty(), onPress, DEFAULT_NARRATION);
|
||||||
this.textureWidth = textureWidth;
|
|
||||||
this.textureHeight = textureHeight;
|
|
||||||
this.xTexStart = xTexStart;
|
|
||||||
this.yTexStart = yTexStart;
|
|
||||||
this.yDiffTex = yDiffTex;
|
|
||||||
this.texture = texture;
|
this.texture = texture;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderWidget(PoseStack stack, int mouseX, int mouseY, float partialTicks) {
|
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
RenderSystem.setShaderTexture(0, texture);
|
var texture = this.texture.get(isHoveredOrFocused());
|
||||||
|
|
||||||
RenderSystem.disableDepthTest();
|
RenderSystem.disableDepthTest();
|
||||||
|
graphics.blit(getX(), getY(), 0, width, height, texture);
|
||||||
var yTex = yTexStart;
|
|
||||||
if (isHoveredOrFocused()) yTex += yDiffTex;
|
|
||||||
|
|
||||||
blit(stack, getX(), getY(), xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight);
|
|
||||||
RenderSystem.enableDepthTest();
|
RenderSystem.enableDepthTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
var message = this.message.get();
|
var message = this.message.get();
|
||||||
setMessage(message.message());
|
setMessage(message.message());
|
||||||
setTooltip(message.tooltip());
|
setTooltip(message.tooltip());
|
||||||
super.render(stack, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public record HintedMessage(Component message, Tooltip tooltip) {
|
public record HintedMessage(Component message, Tooltip tooltip) {
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui.widgets;
|
package dan200.computercraft.client.gui.widgets;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import com.mojang.blaze3d.vertex.Tesselator;
|
import com.mojang.blaze3d.vertex.Tesselator;
|
||||||
import dan200.computercraft.client.render.RenderTypes;
|
import dan200.computercraft.client.render.RenderTypes;
|
||||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||||
@@ -12,6 +11,7 @@ import dan200.computercraft.core.terminal.Terminal;
|
|||||||
import dan200.computercraft.shared.computer.core.InputHandler;
|
import dan200.computercraft.shared.computer.core.InputHandler;
|
||||||
import net.minecraft.SharedConstants;
|
import net.minecraft.SharedConstants;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.components.AbstractWidget;
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
import net.minecraft.client.gui.narration.NarratedElementType;
|
import net.minecraft.client.gui.narration.NarratedElementType;
|
||||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||||
@@ -274,11 +274,11 @@ public class TerminalWidget extends AbstractWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderWidget(PoseStack transform, int mouseX, int mouseY, float partialTicks) {
|
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
if (!visible) return;
|
if (!visible) return;
|
||||||
|
|
||||||
var bufferSource = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
var bufferSource = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
||||||
var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, bufferSource.getBuffer(RenderTypes.TERMINAL));
|
var emitter = FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), bufferSource.getBuffer(RenderTypes.TERMINAL));
|
||||||
|
|
||||||
FixedWidthFontRenderer.drawTerminal(
|
FixedWidthFontRenderer.drawTerminal(
|
||||||
emitter,
|
emitter,
|
||||||
|
@@ -47,7 +47,7 @@ public class ShaderMod {
|
|||||||
Optional<ShaderMod> get();
|
Optional<ShaderMod> get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Storage {
|
private static final class Storage {
|
||||||
static final ShaderMod INSTANCE = ServiceLoader.load(Provider.class)
|
static final ShaderMod INSTANCE = ServiceLoader.load(Provider.class)
|
||||||
.stream()
|
.stream()
|
||||||
.flatMap(x -> x.get().get().stream())
|
.flatMap(x -> x.get().get().stream())
|
||||||
|
@@ -52,7 +52,7 @@ public abstract class AbstractClientNetworkContext implements ClientNetworkConte
|
|||||||
var player = Minecraft.getInstance().player;
|
var player = Minecraft.getInstance().player;
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
|
|
||||||
var te = player.level.getBlockEntity(pos);
|
var te = player.level().getBlockEntity(pos);
|
||||||
if (!(te instanceof MonitorBlockEntity monitor)) return;
|
if (!(te instanceof MonitorBlockEntity monitor)) return;
|
||||||
|
|
||||||
monitor.read(terminal);
|
monitor.read(terminal);
|
||||||
|
@@ -4,25 +4,17 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.Tesselator;
|
import dan200.computercraft.client.gui.GuiSprites;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import static dan200.computercraft.client.render.SpriteRenderer.u;
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import static dan200.computercraft.client.render.SpriteRenderer.v;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import org.joml.Matrix4f;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the borders of computers, either for a GUI ({@link dan200.computercraft.client.gui.ComputerScreen}) or
|
* Renders the borders of computers, either for a GUI ({@link dan200.computercraft.client.gui.ComputerScreen}) or
|
||||||
* {@linkplain PocketItemRenderer in-hand pocket computers}.
|
* {@linkplain PocketItemRenderer in-hand pocket computers}.
|
||||||
*/
|
*/
|
||||||
public class ComputerBorderRenderer {
|
public final class ComputerBorderRenderer {
|
||||||
public static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_normal.png");
|
|
||||||
public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_advanced.png");
|
|
||||||
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_command.png");
|
|
||||||
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_colour.png");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The margin between the terminal and its border.
|
* The margin between the terminal and its border.
|
||||||
*/
|
*/
|
||||||
@@ -33,100 +25,51 @@ public class ComputerBorderRenderer {
|
|||||||
*/
|
*/
|
||||||
public static final int BORDER = 12;
|
public static final int BORDER = 12;
|
||||||
|
|
||||||
private static final int CORNER_TOP_Y = 28;
|
|
||||||
private static final int CORNER_BOTTOM_Y = CORNER_TOP_Y + BORDER;
|
|
||||||
private static final int CORNER_LEFT_X = BORDER;
|
|
||||||
private static final int CORNER_RIGHT_X = CORNER_LEFT_X + BORDER;
|
|
||||||
private static final int BORDER_RIGHT_X = 36;
|
|
||||||
private static final int LIGHT_BORDER_Y = 56;
|
|
||||||
private static final int LIGHT_CORNER_Y = 80;
|
|
||||||
|
|
||||||
public static final int LIGHT_HEIGHT = 8;
|
public static final int LIGHT_HEIGHT = 8;
|
||||||
|
|
||||||
public static final int TEX_SIZE = 256;
|
private static final int TEX_SIZE = 36;
|
||||||
private static final float TEX_SCALE = 1 / (float) TEX_SIZE;
|
|
||||||
|
|
||||||
private final Matrix4f transform;
|
private ComputerBorderRenderer() {
|
||||||
private final VertexConsumer builder;
|
|
||||||
private final int light;
|
|
||||||
private final int z;
|
|
||||||
private final float r, g, b;
|
|
||||||
|
|
||||||
public ComputerBorderRenderer(Matrix4f transform, VertexConsumer builder, int z, int light, float r, float g, float b) {
|
|
||||||
this.transform = transform;
|
|
||||||
this.builder = builder;
|
|
||||||
this.z = z;
|
|
||||||
this.light = light;
|
|
||||||
this.r = r;
|
|
||||||
this.g = g;
|
|
||||||
this.b = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ResourceLocation getTexture(ComputerFamily family) {
|
public static void render(SpriteRenderer renderer, GuiSprites.ComputerTextures textures, int x, int y, int width, int height, boolean withLight) {
|
||||||
return switch (family) {
|
|
||||||
case NORMAL -> BACKGROUND_NORMAL;
|
|
||||||
case ADVANCED -> BACKGROUND_ADVANCED;
|
|
||||||
case COMMAND -> BACKGROUND_COMMAND;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RenderType getRenderType(ResourceLocation location) {
|
|
||||||
// See note in RenderTypes about why we use text rather than anything intuitive.
|
|
||||||
return RenderType.text(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void render(Matrix4f transform, ResourceLocation location, int x, int y, int light, int width, int height) {
|
|
||||||
var source = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
|
||||||
render(transform, source.getBuffer(getRenderType(location)), x, y, 1, light, width, height, false, 1, 1, 1);
|
|
||||||
source.endBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void render(Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b) {
|
|
||||||
new ComputerBorderRenderer(transform, buffer, z, light, r, g, b).doRender(x, y, width, height, withLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doRender(int x, int y, int width, int height, boolean withLight) {
|
|
||||||
var endX = x + width;
|
var endX = x + width;
|
||||||
var endY = y + height;
|
var endY = y + height;
|
||||||
|
|
||||||
// Vertical bars
|
var border = GuiSprites.get(textures.border());
|
||||||
renderLine(x - BORDER, y, 0, CORNER_TOP_Y, BORDER, endY - y);
|
|
||||||
renderLine(endX, y, BORDER_RIGHT_X, CORNER_TOP_Y, BORDER, endY - y);
|
|
||||||
|
|
||||||
// Top bar
|
// Top bar
|
||||||
renderLine(x, y - BORDER, 0, 0, endX - x, BORDER);
|
blitBorder(renderer, border, x - BORDER, y - BORDER, 0, 0, BORDER, BORDER);
|
||||||
renderCorner(x - BORDER, y - BORDER, CORNER_LEFT_X, CORNER_TOP_Y);
|
blitBorder(renderer, border, x, y - BORDER, BORDER, 0, width, BORDER);
|
||||||
renderCorner(endX, y - BORDER, CORNER_RIGHT_X, CORNER_TOP_Y);
|
blitBorder(renderer, border, endX, y - BORDER, BORDER * 2, 0, BORDER, BORDER);
|
||||||
|
|
||||||
|
// Vertical bars
|
||||||
|
blitBorder(renderer, border, x - BORDER, y, 0, BORDER, BORDER, height);
|
||||||
|
blitBorder(renderer, border, endX, y, BORDER * 2, BORDER, BORDER, height);
|
||||||
|
|
||||||
// Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the
|
// Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the
|
||||||
// pocket computer's lights).
|
// pocket computer's lights).
|
||||||
if (withLight) {
|
if (withLight) {
|
||||||
renderTexture(x, endY, 0, LIGHT_BORDER_Y, endX - x, BORDER + LIGHT_HEIGHT, BORDER, BORDER + LIGHT_HEIGHT);
|
var pocketBottomTexture = textures.pocketBottom();
|
||||||
renderTexture(x - BORDER, endY, CORNER_LEFT_X, LIGHT_CORNER_Y, BORDER, BORDER + LIGHT_HEIGHT);
|
if (pocketBottomTexture == null) throw new NullPointerException(textures + " has no pocket texture");
|
||||||
renderTexture(endX, endY, CORNER_RIGHT_X, LIGHT_CORNER_Y, BORDER, BORDER + LIGHT_HEIGHT);
|
var pocketBottom = GuiSprites.get(pocketBottomTexture);
|
||||||
|
|
||||||
|
renderer.blitHorizontalSliced(
|
||||||
|
pocketBottom, x - BORDER, endY, width + BORDER * 2, BORDER + LIGHT_HEIGHT,
|
||||||
|
BORDER, BORDER, BORDER * 3
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
renderLine(x, endY, 0, BORDER, endX - x, BORDER);
|
blitBorder(renderer, border, x - BORDER, endY, 0, BORDER * 2, BORDER, BORDER);
|
||||||
renderCorner(x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y);
|
blitBorder(renderer, border, x, endY, BORDER, BORDER * 2, width, BORDER);
|
||||||
renderCorner(endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y);
|
blitBorder(renderer, border, endX, endY, BORDER * 2, BORDER * 2, BORDER, BORDER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderCorner(int x, int y, int u, int v) {
|
private static void blitBorder(SpriteRenderer renderer, TextureAtlasSprite sprite, int x, int y, int u, int v, int width, int height) {
|
||||||
renderTexture(x, y, u, v, BORDER, BORDER, BORDER, BORDER);
|
renderer.blit(
|
||||||
}
|
x, y, width, height,
|
||||||
|
u(sprite, u, TEX_SIZE), v(sprite, v, TEX_SIZE),
|
||||||
private void renderLine(int x, int y, int u, int v, int width, int height) {
|
u(sprite, u + BORDER, TEX_SIZE), v(sprite, v + BORDER, TEX_SIZE)
|
||||||
renderTexture(x, y, u, v, width, height, BORDER, BORDER);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
private void renderTexture(int x, int y, int u, int v, int width, int height) {
|
|
||||||
renderTexture(x, y, u, v, width, height, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderTexture(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) {
|
|
||||||
builder.vertex(transform, x, y + height, z).color(r, g, b, 1.0f).uv(u * TEX_SCALE, (v + textureHeight) * TEX_SCALE).uv2(light).endVertex();
|
|
||||||
builder.vertex(transform, x + width, y + height, z).color(r, g, b, 1.0f).uv((u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE).uv2(light).endVertex();
|
|
||||||
builder.vertex(transform, x + width, y, z).color(r, g, b, 1.0f).uv((u + textureWidth) * TEX_SCALE, v * TEX_SCALE).uv2(light).endVertex();
|
|
||||||
builder.vertex(transform, x, y, z).color(r, g, b, 1.0f).uv(u * TEX_SCALE, v * TEX_SCALE).uv2(light).endVertex();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ package dan200.computercraft.client.render;
|
|||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.math.Axis;
|
import com.mojang.math.Axis;
|
||||||
|
import dan200.computercraft.client.gui.GuiSprites;
|
||||||
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
||||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||||
import dan200.computercraft.core.util.Colour;
|
import dan200.computercraft.core.util.Colour;
|
||||||
@@ -72,13 +73,14 @@ public final class PocketItemRenderer extends ItemMapLikeRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void renderFrame(Matrix4f transform, MultiBufferSource render, ComputerFamily family, int colour, int light, int width, int height) {
|
private static void renderFrame(Matrix4f transform, MultiBufferSource render, ComputerFamily family, int colour, int light, int width, int height) {
|
||||||
var texture = colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture(family);
|
var texture = colour != -1 ? GuiSprites.COMPUTER_COLOUR : GuiSprites.getComputerTextures(family);
|
||||||
|
|
||||||
var r = ((colour >>> 16) & 0xFF) / 255.0f;
|
var r = (colour >>> 16) & 0xFF;
|
||||||
var g = ((colour >>> 8) & 0xFF) / 255.0f;
|
var g = (colour >>> 8) & 0xFF;
|
||||||
var b = (colour & 0xFF) / 255.0f;
|
var b = colour & 0xFF;
|
||||||
|
|
||||||
ComputerBorderRenderer.render(transform, render.getBuffer(ComputerBorderRenderer.getRenderType(texture)), 0, 0, 0, light, width, height, true, r, g, b);
|
var spriteRenderer = new SpriteRenderer(transform, render.getBuffer(RenderTypes.GUI_SPRITES), 0, light, r, g, b);
|
||||||
|
ComputerBorderRenderer.render(spriteRenderer, texture, 0, 0, width, height, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderLight(PoseStack transform, MultiBufferSource render, int colour, int width, int height) {
|
private static void renderLight(PoseStack transform, MultiBufferSource render, int colour, int width, int height) {
|
||||||
|
@@ -7,6 +7,7 @@ package dan200.computercraft.client.render;
|
|||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.client.gui.GuiSprites;
|
||||||
import dan200.computercraft.client.render.monitor.MonitorTextureBufferShader;
|
import dan200.computercraft.client.render.monitor.MonitorTextureBufferShader;
|
||||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||||
import net.minecraft.client.renderer.GameRenderer;
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
@@ -53,6 +54,11 @@ public class RenderTypes {
|
|||||||
*/
|
*/
|
||||||
public static final RenderType PRINTOUT_BACKGROUND = RenderType.text(new ResourceLocation("computercraft", "textures/gui/printout.png"));
|
public static final RenderType PRINTOUT_BACKGROUND = RenderType.text(new ResourceLocation("computercraft", "textures/gui/printout.png"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render type for {@linkplain GuiSprites GUI sprites}.
|
||||||
|
*/
|
||||||
|
public static final RenderType GUI_SPRITES = RenderType.text(GuiSprites.TEXTURE);
|
||||||
|
|
||||||
public static MonitorTextureBufferShader getMonitorTextureBufferShader() {
|
public static MonitorTextureBufferShader getMonitorTextureBufferShader() {
|
||||||
if (monitorTboShader == null) throw new NullPointerException("MonitorTboShader has not been registered");
|
if (monitorTboShader == null) throw new NullPointerException("MonitorTboShader has not been registered");
|
||||||
return monitorTboShader;
|
return monitorTboShader;
|
||||||
|
@@ -0,0 +1,134 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link GuiGraphics}-equivalent which is suitable for both rendering in to a GUI and in-world (as part of an entity
|
||||||
|
* renderer).
|
||||||
|
* <p>
|
||||||
|
* This batches all render calls together, though requires that all {@link TextureAtlasSprite}s are on the same sprite
|
||||||
|
* sheet.
|
||||||
|
*/
|
||||||
|
public class SpriteRenderer {
|
||||||
|
private final Matrix4f transform;
|
||||||
|
private final VertexConsumer builder;
|
||||||
|
private final int light;
|
||||||
|
private final int z;
|
||||||
|
private final int r, g, b;
|
||||||
|
|
||||||
|
public SpriteRenderer(Matrix4f transform, VertexConsumer builder, int z, int light, int r, int g, int b) {
|
||||||
|
this.transform = transform;
|
||||||
|
this.builder = builder;
|
||||||
|
this.z = z;
|
||||||
|
this.light = light;
|
||||||
|
this.r = r;
|
||||||
|
this.g = g;
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpriteRenderer createForGui(GuiGraphics graphics, RenderType renderType) {
|
||||||
|
return new SpriteRenderer(
|
||||||
|
graphics.pose().last().pose(), graphics.bufferSource().getBuffer(renderType),
|
||||||
|
0, RenderTypes.FULL_BRIGHT_LIGHTMAP, 255, 255, 255
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a single sprite.
|
||||||
|
*
|
||||||
|
* @param sprite The texture to draw.
|
||||||
|
* @param x The x position of the rectangle we'll draw.
|
||||||
|
* @param y The x position of the rectangle we'll draw.
|
||||||
|
* @param width The width of the rectangle we'll draw.
|
||||||
|
* @param height The height of the rectangle we'll draw.
|
||||||
|
*/
|
||||||
|
public void blit(TextureAtlasSprite sprite, int x, int y, int width, int height) {
|
||||||
|
blit(x, y, width, height, sprite.getU0(), sprite.getV0(), sprite.getU1(), sprite.getV1());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a horizontal 3-sliced texture (i.e. split into left, middle and right). Unlike {@link GuiGraphics#blitNineSliced},
|
||||||
|
* the middle texture is stretched rather than repeated.
|
||||||
|
*
|
||||||
|
* @param sprite The texture to draw.
|
||||||
|
* @param x The x position of the rectangle we'll draw.
|
||||||
|
* @param y The x position of the rectangle we'll draw.
|
||||||
|
* @param width The width of the rectangle we'll draw.
|
||||||
|
* @param height The height of the rectangle we'll draw.
|
||||||
|
* @param leftBorder The width of the left border.
|
||||||
|
* @param rightBorder The width of the right border.
|
||||||
|
* @param textureWidth The width of the whole texture.
|
||||||
|
*/
|
||||||
|
public void blitHorizontalSliced(TextureAtlasSprite sprite, int x, int y, int width, int height, int leftBorder, int rightBorder, int textureWidth) {
|
||||||
|
// TODO(1.20.2)/TODO(1.21.0): Drive this from mcmeta files, like vanilla does.
|
||||||
|
if (width < leftBorder + rightBorder) throw new IllegalArgumentException("width is less than two borders");
|
||||||
|
|
||||||
|
var centerStart = SpriteRenderer.u(sprite, leftBorder, textureWidth);
|
||||||
|
var centerEnd = SpriteRenderer.u(sprite, textureWidth - rightBorder, textureWidth);
|
||||||
|
|
||||||
|
blit(x, y, leftBorder, height, sprite.getU0(), sprite.getV0(), centerStart, sprite.getV1());
|
||||||
|
blit(x + leftBorder, y, width - leftBorder - rightBorder, height, centerStart, sprite.getV0(), centerEnd, sprite.getV1());
|
||||||
|
blit(x + width - rightBorder, y, rightBorder, height, centerEnd, sprite.getV0(), sprite.getU1(), sprite.getV1());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a vertical 3-sliced texture (i.e. split into top, middle and bottom). Unlike {@link GuiGraphics#blitNineSliced},
|
||||||
|
* the middle texture is stretched rather than repeated.
|
||||||
|
*
|
||||||
|
* @param sprite The texture to draw.
|
||||||
|
* @param x The x position of the rectangle we'll draw.
|
||||||
|
* @param y The x position of the rectangle we'll draw.
|
||||||
|
* @param width The width of the rectangle we'll draw.
|
||||||
|
* @param height The height of the rectangle we'll draw.
|
||||||
|
* @param topBorder The height of the top border.
|
||||||
|
* @param bottomBorder The height of the bottom border.
|
||||||
|
* @param textureHeight The height of the whole texture.
|
||||||
|
*/
|
||||||
|
public void blitVerticalSliced(TextureAtlasSprite sprite, int x, int y, int width, int height, int topBorder, int bottomBorder, int textureHeight) {
|
||||||
|
// TODO(1.20.2)/TODO(1.21.0): Drive this from mcmeta files, like vanilla does.
|
||||||
|
if (width < topBorder + bottomBorder) throw new IllegalArgumentException("height is less than two borders");
|
||||||
|
|
||||||
|
var centerStart = SpriteRenderer.v(sprite, topBorder, textureHeight);
|
||||||
|
var centerEnd = SpriteRenderer.v(sprite, textureHeight - bottomBorder, textureHeight);
|
||||||
|
|
||||||
|
blit(x, y, width, topBorder, sprite.getU0(), sprite.getV0(), sprite.getU1(), centerStart);
|
||||||
|
blit(x, y + topBorder, width, height - topBorder - bottomBorder, sprite.getU0(), centerStart, sprite.getU1(), centerEnd);
|
||||||
|
blit(x, y + height - bottomBorder, width, bottomBorder, sprite.getU0(), centerEnd, sprite.getU1(), sprite.getV1());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The low-level blit function, used to render a portion of the sprite sheet. Unlike other functions, this takes uvs rather than a single sprite.
|
||||||
|
*
|
||||||
|
* @param x The x position of the rectangle we'll draw.
|
||||||
|
* @param y The x position of the rectangle we'll draw.
|
||||||
|
* @param width The width of the rectangle we'll draw.
|
||||||
|
* @param height The height of the rectangle we'll draw.
|
||||||
|
* @param u0 The first U coordinate.
|
||||||
|
* @param v0 The first V coordinate.
|
||||||
|
* @param u1 The second U coordinate.
|
||||||
|
* @param v1 The second V coordinate.
|
||||||
|
*/
|
||||||
|
public void blit(
|
||||||
|
int x, int y, int width, int height, float u0, float v0, float u1, float v1) {
|
||||||
|
builder.vertex(transform, x, y + height, z).color(r, g, b, 255).uv(u0, v1).uv2(light).endVertex();
|
||||||
|
builder.vertex(transform, x + width, y + height, z).color(r, g, b, 255).uv(u1, v1).uv2(light).endVertex();
|
||||||
|
builder.vertex(transform, x + width, y, z).color(r, g, b, 255).uv(u1, v0).uv2(light).endVertex();
|
||||||
|
builder.vertex(transform, x, y, z).color(r, g, b, 255).uv(u0, v0).uv2(light).endVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float u(TextureAtlasSprite sprite, int x, int width) {
|
||||||
|
return sprite.getU((double) x / width * 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float v(TextureAtlasSprite sprite, int y, int height) {
|
||||||
|
return sprite.getV((double) y / height * 16);
|
||||||
|
}
|
||||||
|
}
|
@@ -7,10 +7,7 @@ package dan200.computercraft.client.render.monitor;
|
|||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.*;
|
||||||
import com.mojang.blaze3d.vertex.Tesselator;
|
|
||||||
import com.mojang.blaze3d.vertex.VertexBuffer;
|
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
|
||||||
import com.mojang.math.Axis;
|
import com.mojang.math.Axis;
|
||||||
import dan200.computercraft.client.FrameInfo;
|
import dan200.computercraft.client.FrameInfo;
|
||||||
import dan200.computercraft.client.integration.ShaderMod;
|
import dan200.computercraft.client.integration.ShaderMod;
|
||||||
@@ -170,7 +167,7 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
|||||||
tboVertex(buffer, matrix, -xMargin, pixelHeight + yMargin);
|
tboVertex(buffer, matrix, -xMargin, pixelHeight + yMargin);
|
||||||
tboVertex(buffer, matrix, pixelWidth + xMargin, -yMargin);
|
tboVertex(buffer, matrix, pixelWidth + xMargin, -yMargin);
|
||||||
tboVertex(buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin);
|
tboVertex(buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin);
|
||||||
RenderTypes.MONITOR_TBO.end(buffer, 0, 0, 0);
|
RenderTypes.MONITOR_TBO.end(buffer, VertexSorting.DISTANCE_TO_ORIGIN);
|
||||||
}
|
}
|
||||||
case VBO -> {
|
case VBO -> {
|
||||||
var backgroundBuffer = assertNonNull(renderState.backgroundBuffer);
|
var backgroundBuffer = assertNonNull(renderState.backgroundBuffer);
|
||||||
|
@@ -14,10 +14,10 @@ import dan200.computercraft.core.terminal.TextBuffer;
|
|||||||
import dan200.computercraft.core.util.Colour;
|
import dan200.computercraft.core.util.Colour;
|
||||||
import net.minecraft.client.renderer.ShaderInstance;
|
import net.minecraft.client.renderer.ShaderInstance;
|
||||||
import net.minecraft.server.packs.resources.ResourceProvider;
|
import net.minecraft.server.packs.resources.ResourceProvider;
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.lwjgl.opengl.GL13;
|
import org.lwjgl.opengl.GL13;
|
||||||
import org.lwjgl.opengl.GL31;
|
import org.lwjgl.opengl.GL31;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -36,12 +36,12 @@ import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.get
|
|||||||
* @see RenderTypes#getMonitorTextureBufferShader()
|
* @see RenderTypes#getMonitorTextureBufferShader()
|
||||||
*/
|
*/
|
||||||
public class MonitorTextureBufferShader extends ShaderInstance {
|
public class MonitorTextureBufferShader extends ShaderInstance {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(MonitorTextureBufferShader.class);
|
||||||
|
|
||||||
public static final int UNIFORM_SIZE = 4 * 4 * 16 + 4 + 4 + 2 * 4 + 4;
|
public static final int UNIFORM_SIZE = 4 * 4 * 16 + 4 + 4 + 2 * 4 + 4;
|
||||||
|
|
||||||
static final int TEXTURE_INDEX = GL13.GL_TEXTURE3;
|
static final int TEXTURE_INDEX = GL13.GL_TEXTURE3;
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
|
||||||
|
|
||||||
private final int monitorData;
|
private final int monitorData;
|
||||||
private int uniformBuffer = 0;
|
private int uniformBuffer = 0;
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ public class MonitorTextureBufferShader extends ShaderInstance {
|
|||||||
private Uniform getUniformChecked(String name) {
|
private Uniform getUniformChecked(String name) {
|
||||||
var uniform = getUniform(name);
|
var uniform = getUniform(name);
|
||||||
if (uniform == null) {
|
if (uniform == null) {
|
||||||
LOGGER.warn("Monitor shader {} should have uniform {}, but it was not present.", getName(), name);
|
LOG.warn("Monitor shader {} should have uniform {}, but it was not present.", getName(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return uniform;
|
return uniform;
|
||||||
|
@@ -25,6 +25,7 @@ public class DirectVertexBuffer extends VertexBuffer {
|
|||||||
private int actualIndexCount;
|
private int actualIndexCount;
|
||||||
|
|
||||||
public DirectVertexBuffer() {
|
public DirectVertexBuffer() {
|
||||||
|
super(Usage.STATIC);
|
||||||
if (DirectBuffers.HAS_DSA) {
|
if (DirectBuffers.HAS_DSA) {
|
||||||
RenderSystem.glDeleteBuffers(vertexBufferId);
|
RenderSystem.glDeleteBuffers(vertexBufferId);
|
||||||
if (DirectBuffers.ON_LINUX) BufferUploader.reset(); // See comment on DirectBuffers.deleteBuffer.
|
if (DirectBuffers.ON_LINUX) BufferUploader.reset(); // See comment on DirectBuffers.deleteBuffer.
|
||||||
|
@@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
package dan200.computercraft.data.client;
|
package dan200.computercraft.data.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.client.gui.GuiSprites;
|
||||||
import dan200.computercraft.data.DataProviders;
|
import dan200.computercraft.data.DataProviders;
|
||||||
import dan200.computercraft.shared.turtle.inventory.UpgradeSlot;
|
import dan200.computercraft.shared.turtle.inventory.UpgradeSlot;
|
||||||
|
import net.minecraft.client.renderer.texture.atlas.SpriteSource;
|
||||||
import net.minecraft.client.renderer.texture.atlas.SpriteSources;
|
import net.minecraft.client.renderer.texture.atlas.SpriteSources;
|
||||||
import net.minecraft.client.renderer.texture.atlas.sources.SingleFile;
|
import net.minecraft.client.renderer.texture.atlas.sources.SingleFile;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@@ -13,6 +15,7 @@ import net.minecraft.server.packs.PackType;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A version of {@link DataProviders} which relies on client-side classes.
|
* A version of {@link DataProviders} which relies on client-side classes.
|
||||||
@@ -29,6 +32,17 @@ public final class ClientDataProviders {
|
|||||||
new SingleFile(UpgradeSlot.LEFT_UPGRADE, Optional.empty()),
|
new SingleFile(UpgradeSlot.LEFT_UPGRADE, Optional.empty()),
|
||||||
new SingleFile(UpgradeSlot.RIGHT_UPGRADE, Optional.empty())
|
new SingleFile(UpgradeSlot.RIGHT_UPGRADE, Optional.empty())
|
||||||
));
|
));
|
||||||
|
out.accept(GuiSprites.SPRITE_SHEET, Stream.of(
|
||||||
|
// Buttons
|
||||||
|
GuiSprites.TURNED_OFF.textures(),
|
||||||
|
GuiSprites.TURNED_ON.textures(),
|
||||||
|
GuiSprites.TERMINATE.textures(),
|
||||||
|
// Computers
|
||||||
|
GuiSprites.COMPUTER_NORMAL.textures(),
|
||||||
|
GuiSprites.COMPUTER_ADVANCED.textures(),
|
||||||
|
GuiSprites.COMPUTER_COMMAND.textures(),
|
||||||
|
GuiSprites.COMPUTER_COLOUR.textures()
|
||||||
|
).flatMap(x -> x).<SpriteSource>map(x -> new SingleFile(x, Optional.empty())).toList());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -139,8 +139,6 @@ public final class LanguageProvider implements DataProvider {
|
|||||||
add("commands.computercraft.tp.synopsis", "Teleport to a specific computer.");
|
add("commands.computercraft.tp.synopsis", "Teleport to a specific computer.");
|
||||||
add("commands.computercraft.tp.desc", "Teleport to the location of a computer. You can either specify the computer's instance id (e.g. 123) or computer id (e.g #123).");
|
add("commands.computercraft.tp.desc", "Teleport to the location of a computer. You can either specify the computer's instance id (e.g. 123) or computer id (e.g #123).");
|
||||||
add("commands.computercraft.tp.action", "Teleport to this computer");
|
add("commands.computercraft.tp.action", "Teleport to this computer");
|
||||||
add("commands.computercraft.tp.not_player", "Cannot open terminal for non-player");
|
|
||||||
add("commands.computercraft.tp.not_there", "Cannot locate computer in the world");
|
|
||||||
add("commands.computercraft.view.synopsis", "View the terminal of a computer.");
|
add("commands.computercraft.view.synopsis", "View the terminal of a computer.");
|
||||||
add("commands.computercraft.view.desc", "Open the terminal of a computer, allowing remote control of a computer. This does not provide access to turtle's inventories. You can either specify the computer's instance id (e.g. 123) or computer id (e.g #123).");
|
add("commands.computercraft.view.desc", "Open the terminal of a computer, allowing remote control of a computer. This does not provide access to turtle's inventories. You can either specify the computer's instance id (e.g. 123) or computer id (e.g #123).");
|
||||||
add("commands.computercraft.view.action", "View this computer");
|
add("commands.computercraft.view.action", "View this computer");
|
||||||
@@ -215,7 +213,6 @@ public final class LanguageProvider implements DataProvider {
|
|||||||
addConfigEntry(ConfigSpec.floppySpaceLimit, "Floppy Disk space limit (bytes)");
|
addConfigEntry(ConfigSpec.floppySpaceLimit, "Floppy Disk space limit (bytes)");
|
||||||
addConfigEntry(ConfigSpec.uploadMaxSize, "File upload size limit (bytes)");
|
addConfigEntry(ConfigSpec.uploadMaxSize, "File upload size limit (bytes)");
|
||||||
addConfigEntry(ConfigSpec.maximumFilesOpen, "Maximum files open per computer");
|
addConfigEntry(ConfigSpec.maximumFilesOpen, "Maximum files open per computer");
|
||||||
addConfigEntry(ConfigSpec.disableLua51Features, "Disable Lua 5.1 features");
|
|
||||||
addConfigEntry(ConfigSpec.defaultComputerSettings, "Default Computer settings");
|
addConfigEntry(ConfigSpec.defaultComputerSettings, "Default Computer settings");
|
||||||
addConfigEntry(ConfigSpec.logComputerErrors, "Log computer errors");
|
addConfigEntry(ConfigSpec.logComputerErrors, "Log computer errors");
|
||||||
addConfigEntry(ConfigSpec.commandRequireCreative, "Command computers require creative");
|
addConfigEntry(ConfigSpec.commandRequireCreative, "Command computers require creative");
|
||||||
|
@@ -23,7 +23,7 @@ import net.minecraft.world.level.storage.loot.entries.LootItem;
|
|||||||
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
|
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
|
||||||
import net.minecraft.world.level.storage.loot.functions.CopyNameFunction;
|
import net.minecraft.world.level.storage.loot.functions.CopyNameFunction;
|
||||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
||||||
import net.minecraft.world.level.storage.loot.predicates.AlternativeLootItemCondition;
|
import net.minecraft.world.level.storage.loot.predicates.AnyOfCondition;
|
||||||
import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition;
|
import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition;
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition;
|
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition;
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
|
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
|
||||||
@@ -79,7 +79,7 @@ class LootTableProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void registerGeneric(BiConsumer<ResourceLocation, LootTable.Builder> add) {
|
private static void registerGeneric(BiConsumer<ResourceLocation, LootTable.Builder> add) {
|
||||||
add.accept(CommonHooks.LOOT_TREASURE_DISK, LootTable.lootTable());
|
add.accept(CommonHooks.TREASURE_DISK_LOOT, LootTable.lootTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void selfDrop(BiConsumer<ResourceLocation, LootTable.Builder> add, Supplier<? extends Block> wrapper) {
|
private static void selfDrop(BiConsumer<ResourceLocation, LootTable.Builder> add, Supplier<? extends Block> wrapper) {
|
||||||
@@ -98,7 +98,7 @@ class LootTableProvider {
|
|||||||
blockDrop(
|
blockDrop(
|
||||||
add, block,
|
add, block,
|
||||||
DynamicLoot.dynamicEntry(new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer")),
|
DynamicLoot.dynamicEntry(new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer")),
|
||||||
AlternativeLootItemCondition.alternative(
|
AnyOfCondition.anyOf(
|
||||||
BlockNamedEntityLootCondition.BUILDER,
|
BlockNamedEntityLootCondition.BUILDER,
|
||||||
HasComputerIdLootCondition.BUILDER,
|
HasComputerIdLootCondition.BUILDER,
|
||||||
PlayerCreativeLootCondition.BUILDER.invert()
|
PlayerCreativeLootCondition.BUILDER.invert()
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
package dan200.computercraft.data;
|
package dan200.computercraft.data;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
||||||
@@ -25,15 +26,12 @@ import net.minecraft.core.registries.Registries;
|
|||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
import net.minecraft.data.recipes.*;
|
import net.minecraft.data.recipes.*;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.util.GsonHelper;
|
import net.minecraft.util.GsonHelper;
|
||||||
import net.minecraft.world.item.DyeColor;
|
import net.minecraft.world.item.*;
|
||||||
import net.minecraft.world.item.DyeItem;
|
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.item.Items;
|
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
|
||||||
import net.minecraft.world.item.crafting.ShapedRecipe;
|
import net.minecraft.world.item.crafting.ShapedRecipe;
|
||||||
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
||||||
import net.minecraft.world.level.ItemLike;
|
import net.minecraft.world.level.ItemLike;
|
||||||
@@ -41,6 +39,7 @@ import net.minecraft.world.level.block.Blocks;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER;
|
import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER;
|
||||||
@@ -443,7 +442,7 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.requires(ModRegistry.Items.MONITOR_NORMAL.get())
|
.requires(ModRegistry.Items.MONITOR_NORMAL.get())
|
||||||
.unlockedBy("has_monitor", inventoryChange(ModRegistry.Items.MONITOR_NORMAL.get()))
|
.unlockedBy("has_monitor", inventoryChange(ModRegistry.Items.MONITOR_NORMAL.get()))
|
||||||
.save(
|
.save(
|
||||||
RecipeWrapper.wrap(RecipeSerializer.SHAPELESS_RECIPE, add)
|
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.SHAPELESS.get(), add)
|
||||||
.withResultTag(playerHead("Cloudhunter", "6d074736-b1e9-4378-a99b-bd8777821c9c")),
|
.withResultTag(playerHead("Cloudhunter", "6d074736-b1e9-4378-a99b-bd8777821c9c")),
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_cloudy")
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_cloudy")
|
||||||
);
|
);
|
||||||
@@ -454,7 +453,7 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.requires(ModRegistry.Items.COMPUTER_ADVANCED.get())
|
.requires(ModRegistry.Items.COMPUTER_ADVANCED.get())
|
||||||
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_ADVANCED.get()))
|
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_ADVANCED.get()))
|
||||||
.save(
|
.save(
|
||||||
RecipeWrapper.wrap(RecipeSerializer.SHAPELESS_RECIPE, add)
|
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.SHAPELESS.get(), add)
|
||||||
.withResultTag(playerHead("dan200", "f3c8d69b-0776-4512-8434-d1b2165909eb")),
|
.withResultTag(playerHead("dan200", "f3c8d69b-0776-4512-8434-d1b2165909eb")),
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_dan200")
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_dan200")
|
||||||
);
|
);
|
||||||
@@ -513,17 +512,15 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static CompoundTag playerHead(String name, String uuid) {
|
private static CompoundTag playerHead(String name, String uuid) {
|
||||||
var owner = new CompoundTag();
|
var owner = NbtUtils.writeGameProfile(new CompoundTag(), new GameProfile(UUID.fromString(uuid), name));
|
||||||
owner.putString("Name", name);
|
|
||||||
owner.putString("Id", uuid);
|
|
||||||
|
|
||||||
var tag = new CompoundTag();
|
var tag = new CompoundTag();
|
||||||
tag.put("SkullOwner", owner);
|
tag.put(PlayerHeadItem.TAG_SKULL_OWNER, owner);
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Consumer<JsonObject> family(ComputerFamily family) {
|
private static Consumer<JsonObject> family(ComputerFamily family) {
|
||||||
return json -> json.addProperty("family", family.toString());
|
return json -> json.addProperty("family", family.getSerializedName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addSpecial(Consumer<FinishedRecipe> add, SimpleCraftingRecipeSerializer<?> special) {
|
private static void addSpecial(Consumer<FinishedRecipe> add, SimpleCraftingRecipeSerializer<?> special) {
|
||||||
|
@@ -35,6 +35,8 @@ class TagProvider {
|
|||||||
tags.tag(ComputerCraftTags.Blocks.WIRED_MODEM).add(ModRegistry.Blocks.CABLE.get(), ModRegistry.Blocks.WIRED_MODEM_FULL.get());
|
tags.tag(ComputerCraftTags.Blocks.WIRED_MODEM).add(ModRegistry.Blocks.CABLE.get(), ModRegistry.Blocks.WIRED_MODEM_FULL.get());
|
||||||
tags.tag(ComputerCraftTags.Blocks.MONITOR).add(ModRegistry.Blocks.MONITOR_NORMAL.get(), ModRegistry.Blocks.MONITOR_ADVANCED.get());
|
tags.tag(ComputerCraftTags.Blocks.MONITOR).add(ModRegistry.Blocks.MONITOR_NORMAL.get(), ModRegistry.Blocks.MONITOR_ADVANCED.get());
|
||||||
|
|
||||||
|
tags.tag(ComputerCraftTags.Blocks.PERIPHERAL_HUB_IGNORE).addTag(ComputerCraftTags.Blocks.WIRED_MODEM);
|
||||||
|
|
||||||
tags.tag(ComputerCraftTags.Blocks.TURTLE_ALWAYS_BREAKABLE).addTag(BlockTags.LEAVES).add(
|
tags.tag(ComputerCraftTags.Blocks.TURTLE_ALWAYS_BREAKABLE).addTag(BlockTags.LEAVES).add(
|
||||||
Blocks.BAMBOO, Blocks.BAMBOO_SAPLING // Bamboo isn't instabreak for some odd reason.
|
Blocks.BAMBOO, Blocks.BAMBOO_SAPLING // Bamboo isn't instabreak for some odd reason.
|
||||||
);
|
);
|
||||||
@@ -88,6 +90,8 @@ class TagProvider {
|
|||||||
ModRegistry.Items.MONITOR_ADVANCED.get()
|
ModRegistry.Items.MONITOR_ADVANCED.get()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
tags.tag(ItemTags.BOOKSHELF_BOOKS).add(ModRegistry.Items.PRINTED_BOOK.get());
|
||||||
|
|
||||||
tags.tag(ComputerCraftTags.Items.TURTLE_CAN_PLACE)
|
tags.tag(ComputerCraftTags.Items.TURTLE_CAN_PLACE)
|
||||||
.add(Items.GLASS_BOTTLE)
|
.add(Items.GLASS_BOTTLE)
|
||||||
.addTag(ItemTags.BOATS);
|
.addTag(ItemTags.BOATS);
|
||||||
|
@@ -18,8 +18,8 @@ import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
|
|||||||
import net.minecraft.util.GsonHelper;
|
import net.minecraft.util.GsonHelper;
|
||||||
import net.minecraft.util.profiling.ProfilerFiller;
|
import net.minecraft.util.profiling.ProfilerFiller;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.slf4j.Logger;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -37,7 +37,7 @@ import java.util.stream.Collectors;
|
|||||||
* @see PocketUpgrades
|
* @see PocketUpgrades
|
||||||
*/
|
*/
|
||||||
public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase> extends SimpleJsonResourceReloadListener {
|
public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase> extends SimpleJsonResourceReloadListener {
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOG = LoggerFactory.getLogger(UpgradeManager.class);
|
||||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||||
|
|
||||||
public record UpgradeWrapper<R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase>(
|
public record UpgradeWrapper<R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase>(
|
||||||
@@ -48,8 +48,8 @@ public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends
|
|||||||
private final String kind;
|
private final String kind;
|
||||||
private final ResourceKey<Registry<R>> registry;
|
private final ResourceKey<Registry<R>> registry;
|
||||||
|
|
||||||
private Map<String, UpgradeWrapper<R, T>> current = Collections.emptyMap();
|
private Map<String, UpgradeWrapper<R, T>> current = Map.of();
|
||||||
private Map<T, UpgradeWrapper<R, T>> currentWrappers = Collections.emptyMap();
|
private Map<T, UpgradeWrapper<R, T>> currentWrappers = Map.of();
|
||||||
|
|
||||||
public UpgradeManager(String kind, String path, ResourceKey<Registry<R>> registry) {
|
public UpgradeManager(String kind, String path, ResourceKey<Registry<R>> registry) {
|
||||||
super(GSON, path);
|
super(GSON, path);
|
||||||
@@ -103,13 +103,13 @@ public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends
|
|||||||
try {
|
try {
|
||||||
loadUpgrade(newUpgrades, element.getKey(), element.getValue());
|
loadUpgrade(newUpgrades, element.getKey(), element.getValue());
|
||||||
} catch (IllegalArgumentException | JsonParseException e) {
|
} catch (IllegalArgumentException | JsonParseException e) {
|
||||||
LOGGER.error("Error loading {} {} from JSON file", kind, element.getKey(), e);
|
LOG.error("Error loading {} {} from JSON file", kind, element.getKey(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current = Collections.unmodifiableMap(newUpgrades);
|
current = Collections.unmodifiableMap(newUpgrades);
|
||||||
currentWrappers = newUpgrades.values().stream().collect(Collectors.toUnmodifiableMap(UpgradeWrapper::upgrade, x -> x));
|
currentWrappers = newUpgrades.values().stream().collect(Collectors.toUnmodifiableMap(UpgradeWrapper::upgrade, x -> x));
|
||||||
LOGGER.info("Loaded {} {}s", current.size(), kind);
|
LOG.info("Loaded {} {}s", current.size(), kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadUpgrade(Map<String, UpgradeWrapper<R, T>> current, ResourceLocation id, JsonElement json) {
|
private void loadUpgrade(Map<String, UpgradeWrapper<R, T>> current, ResourceLocation id, JsonElement json) {
|
||||||
|
@@ -12,7 +12,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
final class WiredNetworkChangeImpl implements WiredNetworkChange {
|
final class WiredNetworkChangeImpl implements WiredNetworkChange {
|
||||||
private static final WiredNetworkChangeImpl EMPTY = new WiredNetworkChangeImpl(Collections.emptyMap(), Collections.emptyMap());
|
private static final WiredNetworkChangeImpl EMPTY = new WiredNetworkChangeImpl(Map.of(), Map.of());
|
||||||
|
|
||||||
private final Map<String, IPeripheral> removed;
|
private final Map<String, IPeripheral> removed;
|
||||||
private final Map<String, IPeripheral> added;
|
private final Map<String, IPeripheral> added;
|
||||||
@@ -27,11 +27,11 @@ final class WiredNetworkChangeImpl implements WiredNetworkChange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WiredNetworkChangeImpl added(Map<String, IPeripheral> added) {
|
static WiredNetworkChangeImpl added(Map<String, IPeripheral> added) {
|
||||||
return added.isEmpty() ? EMPTY : new WiredNetworkChangeImpl(Collections.emptyMap(), Collections.unmodifiableMap(added));
|
return added.isEmpty() ? EMPTY : new WiredNetworkChangeImpl(Map.of(), Collections.unmodifiableMap(added));
|
||||||
}
|
}
|
||||||
|
|
||||||
static WiredNetworkChangeImpl removed(Map<String, IPeripheral> removed) {
|
static WiredNetworkChangeImpl removed(Map<String, IPeripheral> removed) {
|
||||||
return removed.isEmpty() ? EMPTY : new WiredNetworkChangeImpl(Collections.unmodifiableMap(removed), Collections.emptyMap());
|
return removed.isEmpty() ? EMPTY : new WiredNetworkChangeImpl(Collections.unmodifiableMap(removed), Map.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
static WiredNetworkChangeImpl changeOf(Map<String, IPeripheral> oldPeripherals, Map<String, IPeripheral> newPeripherals) {
|
static WiredNetworkChangeImpl changeOf(Map<String, IPeripheral> oldPeripherals, Map<String, IPeripheral> newPeripherals) {
|
||||||
@@ -39,9 +39,9 @@ final class WiredNetworkChangeImpl implements WiredNetworkChange {
|
|||||||
if (oldPeripherals.isEmpty() && newPeripherals.isEmpty()) {
|
if (oldPeripherals.isEmpty() && newPeripherals.isEmpty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else if (oldPeripherals.isEmpty()) {
|
} else if (oldPeripherals.isEmpty()) {
|
||||||
return new WiredNetworkChangeImpl(Collections.emptyMap(), newPeripherals);
|
return new WiredNetworkChangeImpl(Map.of(), newPeripherals);
|
||||||
} else if (newPeripherals.isEmpty()) {
|
} else if (newPeripherals.isEmpty()) {
|
||||||
return new WiredNetworkChangeImpl(oldPeripherals, Collections.emptyMap());
|
return new WiredNetworkChangeImpl(oldPeripherals, Map.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, IPeripheral> added = new HashMap<>(newPeripherals);
|
Map<String, IPeripheral> added = new HashMap<>(newPeripherals);
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.impl.network.wired;
|
package dan200.computercraft.impl.network.wired;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import dan200.computercraft.api.network.Packet;
|
import dan200.computercraft.api.network.Packet;
|
||||||
import dan200.computercraft.api.network.wired.WiredNetwork;
|
import dan200.computercraft.api.network.wired.WiredNetwork;
|
||||||
import dan200.computercraft.api.network.wired.WiredNode;
|
import dan200.computercraft.api.network.wired.WiredNode;
|
||||||
@@ -24,7 +23,7 @@ final class WiredNetworkImpl implements WiredNetwork {
|
|||||||
nodes.add(node);
|
nodes.add(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WiredNetworkImpl(HashSet<WiredNodeImpl> nodes) {
|
private WiredNetworkImpl(Set<WiredNodeImpl> nodes) {
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +56,10 @@ final class WiredNetworkImpl implements WiredNetwork {
|
|||||||
// Move all nodes across into this network, destroying the original nodes.
|
// Move all nodes across into this network, destroying the original nodes.
|
||||||
nodes.addAll(otherNodes);
|
nodes.addAll(otherNodes);
|
||||||
for (var node : otherNodes) node.network = this;
|
for (var node : otherNodes) node.network = this;
|
||||||
other.nodes = Collections.emptySet();
|
other.nodes = Set.of();
|
||||||
|
|
||||||
// Move all peripherals across,
|
// Move all peripherals across,
|
||||||
other.peripherals = Collections.emptyMap();
|
other.peripherals = Map.of();
|
||||||
peripherals.putAll(otherPeripherals);
|
peripherals.putAll(otherPeripherals);
|
||||||
|
|
||||||
if (!thisPeripherals.isEmpty()) {
|
if (!thisPeripherals.isEmpty()) {
|
||||||
@@ -217,7 +216,7 @@ final class WiredNetworkImpl implements WiredNetwork {
|
|||||||
try {
|
try {
|
||||||
// We special case the original node: detaching all peripherals when needed.
|
// We special case the original node: detaching all peripherals when needed.
|
||||||
wired.network = wiredNetwork;
|
wired.network = wiredNetwork;
|
||||||
wired.peripherals = Collections.emptyMap();
|
wired.peripherals = Map.of();
|
||||||
|
|
||||||
// Ensure every network is finalised
|
// Ensure every network is finalised
|
||||||
for (var network : maximals) {
|
for (var network : maximals) {
|
||||||
@@ -260,7 +259,7 @@ final class WiredNetworkImpl implements WiredNetwork {
|
|||||||
var change = WiredNetworkChangeImpl.changeOf(oldPeripherals, newPeripherals);
|
var change = WiredNetworkChangeImpl.changeOf(oldPeripherals, newPeripherals);
|
||||||
if (change.isEmpty()) return;
|
if (change.isEmpty()) return;
|
||||||
|
|
||||||
wired.peripherals = ImmutableMap.copyOf(newPeripherals);
|
wired.peripherals = Map.copyOf(newPeripherals);
|
||||||
|
|
||||||
// Detach the old peripherals then remove them.
|
// Detach the old peripherals then remove them.
|
||||||
peripherals.keySet().removeAll(change.peripheralsRemoved().keySet());
|
peripherals.keySet().removeAll(change.peripheralsRemoved().keySet());
|
||||||
@@ -333,7 +332,7 @@ final class WiredNetworkImpl implements WiredNetwork {
|
|||||||
// Detach the old peripherals then remove them from the old network
|
// Detach the old peripherals then remove them from the old network
|
||||||
wired.network = wiredNetwork;
|
wired.network = wiredNetwork;
|
||||||
wired.neighbours.clear();
|
wired.neighbours.clear();
|
||||||
wired.peripherals = Collections.emptyMap();
|
wired.peripherals = Map.of();
|
||||||
|
|
||||||
// Broadcast the change
|
// Broadcast the change
|
||||||
if (!peripherals.isEmpty()) WiredNetworkChangeImpl.removed(peripherals).broadcast(wired);
|
if (!peripherals.isEmpty()) WiredNetworkChangeImpl.removed(peripherals).broadcast(wired);
|
||||||
@@ -375,7 +374,7 @@ final class WiredNetworkImpl implements WiredNetwork {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HashSet<WiredNodeImpl> reachableNodes(WiredNodeImpl start) {
|
private static Set<WiredNodeImpl> reachableNodes(WiredNodeImpl start) {
|
||||||
Queue<WiredNodeImpl> enqueued = new ArrayDeque<>();
|
Queue<WiredNodeImpl> enqueued = new ArrayDeque<>();
|
||||||
var reachable = new HashSet<WiredNodeImpl>();
|
var reachable = new HashSet<WiredNodeImpl>();
|
||||||
|
|
||||||
|
@@ -13,13 +13,16 @@ import dan200.computercraft.api.network.wired.WiredSender;
|
|||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public final class WiredNodeImpl implements WiredNode {
|
public final class WiredNodeImpl implements WiredNode {
|
||||||
private @Nullable Set<PacketReceiver> receivers;
|
private @Nullable Set<PacketReceiver> receivers;
|
||||||
|
|
||||||
final WiredElement element;
|
final WiredElement element;
|
||||||
Map<String, IPeripheral> peripherals = Collections.emptyMap();
|
Map<String, IPeripheral> peripherals = Map.of();
|
||||||
|
|
||||||
final HashSet<WiredNodeImpl> neighbours = new HashSet<>();
|
final HashSet<WiredNodeImpl> neighbours = new HashSet<>();
|
||||||
volatile WiredNetworkImpl network;
|
volatile WiredNetworkImpl network;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user