mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-18 07:27:39 +00:00
Compare commits
102 Commits
v1.21-1.11
...
v1.20.1-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1963e0160f | ||
![]() |
9a06904634 | ||
![]() |
5e24ad17d7 | ||
![]() |
8b1cb09ddf | ||
![]() |
d1a6b043c2 | ||
![]() |
cddb8fec11 | ||
![]() |
1d7d8006d4 | ||
![]() |
63bdc2537c | ||
![]() |
f776b17150 | ||
![]() |
31da2555cb | ||
![]() |
9b19a93ab9 | ||
![]() |
ad52117f0f | ||
![]() |
bdffabc08e | ||
![]() |
87ce41f251 | ||
![]() |
e7c7919cad | ||
![]() |
4f66ac79d3 | ||
![]() |
ba6da3bc6c | ||
![]() |
b742745854 | ||
![]() |
3293639adf | ||
![]() |
064ff31830 | ||
![]() |
5d473725d5 | ||
![]() |
97a2f2dbdd | ||
![]() |
37c4789fa4 | ||
![]() |
0aaeeeee24 | ||
![]() |
2155ec3d63 | ||
![]() |
0da906fc93 | ||
![]() |
9e5e6a1b60 | ||
![]() |
dcc74e15c7 | ||
![]() |
c271ed7c7f | ||
![]() |
d6a246c122 | ||
![]() |
0bef3ee0d8 | ||
![]() |
bb04df7086 | ||
![]() |
a70baf0d74 | ||
![]() |
86e2f92493 | ||
![]() |
e9aceca1de | ||
![]() |
3042950507 | ||
![]() |
f7a6aac657 | ||
![]() |
782564e6ab | ||
![]() |
6b8ba8b80b | ||
![]() |
52b76d8886 | ||
![]() |
ba36c69583 | ||
![]() |
370e5f92a0 | ||
![]() |
36d05e4774 | ||
![]() |
89d1be17c9 | ||
![]() |
0069591af9 | ||
![]() |
c36c8605bf | ||
![]() |
3c72a00d46 | ||
![]() |
58aefc8df8 | ||
![]() |
97ddfc2794 | ||
![]() |
6e4ec86586 | ||
![]() |
d24984c1d5 | ||
![]() |
8080dcdd9e | ||
![]() |
d7cea55e2a | ||
![]() |
9b2f974a81 | ||
![]() |
43770fa9bd | ||
![]() |
80c7a54ad4 | ||
![]() |
e57b6fede2 | ||
![]() |
34a2fd039f | ||
![]() |
3299d0e72a | ||
![]() |
b89e2615db | ||
![]() |
cdcd82679c | ||
![]() |
cdfa866760 | ||
![]() |
aa8078ddeb | ||
![]() |
7e53c19d74 | ||
![]() |
b7a8432cfb | ||
![]() |
356c8e8aeb | ||
![]() |
ed283155f7 | ||
![]() |
87dfad026e | ||
![]() |
bb97c465d9 | ||
![]() |
9484315d37 | ||
![]() |
be59f1a875 | ||
![]() |
bfb28b4710 | ||
![]() |
216f0adb3c | ||
![]() |
77af4bc213 | ||
![]() |
5abab982c7 | ||
![]() |
764e1aa332 | ||
![]() |
c47718b09d | ||
![]() |
08d4f91c8b | ||
![]() |
b9eac4e509 | ||
![]() |
dc3d8ea198 | ||
![]() |
cbe075b001 | ||
![]() |
ed0b156e05 | ||
![]() |
4dd0735066 | ||
![]() |
38e516d7c7 | ||
![]() |
70a31855ac | ||
![]() |
6c8e64ffcd | ||
![]() |
7285c32d58 | ||
![]() |
99c60ac54b | ||
![]() |
63e40cf3cb | ||
![]() |
1d45935a25 | ||
![]() |
f80373e7a2 | ||
![]() |
63185629b7 | ||
![]() |
4bfb9ac323 | ||
![]() |
5926b6c994 | ||
![]() |
f5ed43584d | ||
![]() |
d77f5f135f | ||
![]() |
7744d2663b | ||
![]() |
4566cb8273 | ||
![]() |
052e7a7ae5 | ||
![]() |
0895200681 | ||
![]() |
09d0f563b7 | ||
![]() |
e188f1d3fa |
16
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
16
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -6,12 +6,11 @@ body:
|
|||||||
id: mc-version
|
id: mc-version
|
||||||
attributes:
|
attributes:
|
||||||
label: Minecraft Version
|
label: Minecraft Version
|
||||||
description: What version of Minecraft are you using?
|
description: |
|
||||||
|
What version of Minecraft are you using? If your version is not listed, please try to reproduce on one of the supported versions.
|
||||||
options:
|
options:
|
||||||
- 1.16.x
|
- 1.20.1
|
||||||
- 1.18.x
|
- 1.21.x
|
||||||
- 1.19.x
|
|
||||||
- 1.20.x
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
@@ -28,8 +27,5 @@ body:
|
|||||||
label: Details
|
label: Details
|
||||||
description: |
|
description: |
|
||||||
Description of the bug. Please include the following:
|
Description of the bug. Please include the following:
|
||||||
- Logs: These will be located in the `logs/` directory of your Minecraft
|
- Logs: These will be located in the `logs/` directory of your Minecraft instance. This is always useful, even if it doesn't include errors, so please upload this!
|
||||||
instance. Please upload them as a gist or directly into this editor.
|
- Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.
|
||||||
- Detailed reproduction steps: sometimes I can spot a bug pretty easily,
|
|
||||||
but often it's much more obscure. The more information I have to help
|
|
||||||
reproduce it, the quicker it'll get fixed.
|
|
||||||
|
22
.github/workflows/main-ci.yml
vendored
22
.github/workflows/main-ci.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
- name: 📥 Set up Java
|
- name: 📥 Set up Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 21
|
java-version: 17
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
|
||||||
- name: 📥 Setup Gradle
|
- name: 📥 Setup Gradle
|
||||||
@@ -30,8 +30,16 @@ jobs:
|
|||||||
- name: ⚒️ Build
|
- name: ⚒️ Build
|
||||||
run: ./gradlew assemble || ./gradlew assemble
|
run: ./gradlew assemble || ./gradlew assemble
|
||||||
|
|
||||||
|
- name: Cache pre-commit
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pre-commit
|
||||||
|
key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
||||||
|
|
||||||
- name: 💡 Lint
|
- name: 💡 Lint
|
||||||
uses: pre-commit/action@v3.0.0
|
run: |
|
||||||
|
pipx install pre-commit
|
||||||
|
pre-commit run --show-diff-on-failure --color=always
|
||||||
|
|
||||||
- name: 🧪 Run tests
|
- name: 🧪 Run tests
|
||||||
run: ./gradlew test validateMixinNames checkChangelog
|
run: ./gradlew test validateMixinNames checkChangelog
|
||||||
@@ -42,11 +50,6 @@ jobs:
|
|||||||
- name: 🧪 Run integration tests
|
- name: 🧪 Run integration tests
|
||||||
run: ./gradlew runGametest
|
run: ./gradlew runGametest
|
||||||
|
|
||||||
- name: 🧪 Run client tests
|
|
||||||
run: ./gradlew runGametestClient # Not checkClient, as no point running rendering tests.
|
|
||||||
# These are a little flaky on GH actions: its useful to run them, but don't break the build.
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: 🧪 Parse test reports
|
- name: 🧪 Parse test reports
|
||||||
run: ./tools/parse-reports.py
|
run: ./tools/parse-reports.py
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
@@ -63,9 +66,6 @@ jobs:
|
|||||||
name: CC-Tweaked
|
name: CC-Tweaked
|
||||||
path: ./jars
|
path: ./jars
|
||||||
|
|
||||||
- name: 📤 Upload coverage
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
|
|
||||||
build-core:
|
build-core:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -87,7 +87,7 @@ jobs:
|
|||||||
- name: 📥 Set up Java
|
- name: 📥 Set up Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 21
|
java-version: 17
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
|
||||||
- name: 📥 Setup Gradle
|
- name: 📥 Setup Gradle
|
||||||
|
2
.github/workflows/make-doc.yml
vendored
2
.github/workflows/make-doc.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: 📥 Set up Java
|
- name: 📥 Set up Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 21
|
java-version: 17
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
|
||||||
- name: 📥 Setup Gradle
|
- name: 📥 Setup Gradle
|
||||||
|
@@ -27,7 +27,7 @@ repos:
|
|||||||
exclude: "^(.*\\.(bat)|LICENSE)$"
|
exclude: "^(.*\\.(bat)|LICENSE)$"
|
||||||
|
|
||||||
- repo: https://github.com/fsfe/reuse-tool
|
- repo: https://github.com/fsfe/reuse-tool
|
||||||
rev: v2.1.0
|
rev: v4.0.3
|
||||||
hooks:
|
hooks:
|
||||||
- id: reuse
|
- id: reuse
|
||||||
|
|
||||||
|
100
.reuse/dep5
100
.reuse/dep5
@@ -1,100 +0,0 @@
|
|||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
||||||
Source: https://github.com/cc-tweaked/cc-tweaked
|
|
||||||
Upstream-Name: CC: Tweaked
|
|
||||||
Upstream-Contact: Jonathan Coates <git@squiddev.cc>
|
|
||||||
|
|
||||||
Files:
|
|
||||||
projects/common/src/main/resources/assets/computercraft/sounds.json
|
|
||||||
projects/common/src/main/resources/assets/computercraft/sounds/empty.ogg
|
|
||||||
projects/common/src/testMod/resources/data/cctest/computercraft/turtle_upgrade/*
|
|
||||||
projects/common/src/testMod/resources/data/cctest/structures/*
|
|
||||||
projects/*/src/generated/*
|
|
||||||
projects/web/src/htmlTransform/export/index.json
|
|
||||||
projects/web/src/htmlTransform/export/items/minecraft/*
|
|
||||||
Comment: Generated/data files are CC0.
|
|
||||||
Copyright: The CC: Tweaked Developers
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files:
|
|
||||||
doc/images/*
|
|
||||||
package.json
|
|
||||||
package-lock.json
|
|
||||||
projects/common/src/client/resources/computercraft-client.mixins.json
|
|
||||||
projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json
|
|
||||||
projects/common/src/main/resources/computercraft.mixins.json
|
|
||||||
projects/common/src/testMod/resources/computercraft-gametest.mixins.json
|
|
||||||
projects/common/src/testMod/resources/data/computercraft/loot_tables/treasure_disk.json
|
|
||||||
projects/common/src/testMod/resources/pack.mcmeta
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/modules/command/.ignoreme
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/.ignoreme
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/modules/turtle/.ignoreme
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/motd.txt
|
|
||||||
projects/fabric-api/src/main/modJson/fabric.mod.json
|
|
||||||
projects/fabric/src/client/resources/computercraft-client.fabric.mixins.json
|
|
||||||
projects/fabric/src/main/resources/computercraft.fabric.mixins.json
|
|
||||||
projects/fabric/src/main/resources/fabric.mod.json
|
|
||||||
projects/fabric/src/testMod/resources/computercraft-gametest.fabric.mixins.json
|
|
||||||
projects/fabric/src/testMod/resources/fabric.mod.json
|
|
||||||
projects/forge/src/client/resources/computercraft-client.forge.mixins.json
|
|
||||||
projects/forge/src/main/resources/computercraft.forge.mixins.json
|
|
||||||
projects/web/src/frontend/mount/.settings
|
|
||||||
projects/web/src/frontend/mount/example.nfp
|
|
||||||
projects/web/src/frontend/mount/example.nft
|
|
||||||
projects/web/src/frontend/mount/expr_template.lua
|
|
||||||
projects/web/tsconfig.json
|
|
||||||
Comment: Several assets where it's inconvenient to create a .license file.
|
|
||||||
Copyright: The CC: Tweaked Developers
|
|
||||||
License: MPL-2.0
|
|
||||||
|
|
||||||
Files:
|
|
||||||
doc/logo.png
|
|
||||||
doc/logo-darkmode.png
|
|
||||||
projects/common/src/main/resources/assets/computercraft/models/*
|
|
||||||
projects/common/src/main/resources/assets/computercraft/textures/*
|
|
||||||
projects/common/src/main/resources/pack.mcmeta
|
|
||||||
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/help/*
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/programs/fun/advanced/levels/*
|
|
||||||
projects/web/src/htmlTransform/export/items/computercraft/*
|
|
||||||
Comment: Bulk-license original assets as CCPL.
|
|
||||||
Copyright: 2011 Daniel Ratcliffe
|
|
||||||
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:
|
|
||||||
projects/common/src/main/resources/assets/computercraft/lang/*
|
|
||||||
Comment: Community-contributed license files
|
|
||||||
Copyright: 2017 The CC: Tweaked Developers
|
|
||||||
License: MPL-2.0
|
|
||||||
|
|
||||||
Files:
|
|
||||||
.github/*
|
|
||||||
Comment:
|
|
||||||
GitHub build scripts are CC0. While we could add a header to each file,
|
|
||||||
it's unclear if it will break actions or issue templates in some way.
|
|
||||||
Copyright: Jonathan Coates <git@squiddev.cc>
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files:
|
|
||||||
gradle/wrapper/*
|
|
||||||
gradlew
|
|
||||||
gradlew.bat
|
|
||||||
Copyright: Gradle Inc
|
|
||||||
License: Apache-2.0
|
|
||||||
|
|
||||||
Files: projects/core/src/test/resources/test-rom/data/json-parsing/*
|
|
||||||
Copyright: 2016 Nicolas Seriot
|
|
||||||
License: MIT
|
|
@@ -22,16 +22,16 @@ If you have a bug, suggestion, or other feedback, the best thing to do is [file
|
|||||||
use the issue templates - they provide a useful hint on what information to provide.
|
use the issue templates - they provide a useful hint on what information to provide.
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
Translations are managed through [Weblate], an online interface for managing language strings. This is synced
|
Translations are managed through [CrowdIn], an online interface for managing language strings. Translations may either
|
||||||
automatically with GitHub, so please don't submit PRs adding/changing translations!
|
be contributed there, or directly via a pull request.
|
||||||
|
|
||||||
## Setting up a development environment
|
## Setting up a development environment
|
||||||
In order to develop CC: Tweaked, you'll need to download the source code and then run it.
|
In order to develop CC: Tweaked, you'll need to download the source code and then run it.
|
||||||
|
|
||||||
- Make sure you've got the following software installed:
|
- Make sure you've got the following software installed:
|
||||||
- Java Development Kit (JDK). This can be downloaded from [Adoptium].
|
- Java Development Kit 17 (JDK). This can be downloaded from [Adoptium].
|
||||||
- [Git](https://git-scm.com/).
|
- [Git](https://git-scm.com/).
|
||||||
- [NodeJS][node].
|
- [NodeJS 20 or later][node].
|
||||||
|
|
||||||
- Download CC: Tweaked's source code:
|
- Download CC: Tweaked's source code:
|
||||||
```
|
```
|
||||||
@@ -101,10 +101,10 @@ about how you can build on that until you've covered everything!
|
|||||||
[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"
|
||||||
[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"
|
|
||||||
[docs]: https://tweaked.cc/ "CC: Tweaked documentation"
|
[docs]: https://tweaked.cc/ "CC: Tweaked documentation"
|
||||||
[ldoc]: http://stevedonovan.github.io/ldoc/ "ldoc, a Lua documentation generator."
|
[ldoc]: http://stevedonovan.github.io/ldoc/ "ldoc, a Lua documentation generator."
|
||||||
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg
|
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg
|
||||||
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
|
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
|
||||||
[node]: https://nodejs.org/en/ "Node.js"
|
[node]: https://nodejs.org/en/ "Node.js"
|
||||||
[architecture]: projects/ARCHITECTURE.md
|
[architecture]: projects/ARCHITECTURE.md
|
||||||
|
[Crowdin]: https://crowdin.com/project/cc-tweaked/
|
||||||
|
20
README.md
20
README.md
@@ -11,14 +11,13 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
</picture>
|
</picture>
|
||||||
|
|
||||||
[](https://github.com/cc-tweaked/CC-Tweaked/actions "Current build status")
|
[](https://github.com/cc-tweaked/CC-Tweaked/actions "Current build status")
|
||||||
[][CurseForge]
|
|
||||||
[][Modrinth]
|
[][Modrinth]
|
||||||
|
|
||||||
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the
|
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the
|
||||||
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
|
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
|
||||||
new features.
|
new features.
|
||||||
|
|
||||||
CC: Tweaked can be installed from [CurseForge] or [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
|
CC: Tweaked can be installed from [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. If you want to get started
|
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. If you want to get started
|
||||||
@@ -26,8 +25,9 @@ developing the mod, [check out the instructions here](CONTRIBUTING.md#developing
|
|||||||
|
|
||||||
## Community
|
## Community
|
||||||
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
||||||
ComputerCraft, do check out our [forum] and [GitHub discussions page][GitHub discussions]! There's also a fairly
|
ComputerCraft, do check out our [GitHub discussions page][GitHub discussions]! There's also a fairly populated,
|
||||||
populated, albeit quiet [IRC channel][irc], if that's more your cup of tea.
|
albeit quiet IRC channel on [EsperNet], if that's more your cup of tea. You can join `#computercraft` through your
|
||||||
|
desktop client, or online using [KiwiIRC].
|
||||||
|
|
||||||
We also host fairly comprehensive documentation at [tweaked.cc](https://tweaked.cc/ "The CC: Tweaked website").
|
We also host fairly comprehensive documentation at [tweaked.cc](https://tweaked.cc/ "The CC: Tweaked website").
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ on is present.
|
|||||||
```groovy
|
```groovy
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
url "https://squiddev.cc/maven/"
|
url "https://maven.squiddev.cc"
|
||||||
content {
|
content {
|
||||||
includeGroup("cc.tweaked")
|
includeGroup("cc.tweaked")
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,9 @@ dependencies {
|
|||||||
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-common-api:$cctVersion")
|
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-common-api:$cctVersion")
|
||||||
|
|
||||||
// Forge Gradle
|
// Forge Gradle
|
||||||
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-forge-api:$cctVersion")
|
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-core-api:$cctVersion")
|
||||||
runtimeOnly("cc.tweaked:cc-tweaked-$mcVersion-forge:$cctVersion")
|
compileOnly(fg.deobf("cc.tweaked:cc-tweaked-$mcVersion-forge-api:$cctVersion"))
|
||||||
|
runtimeOnly(fg.deobf("cc.tweaked:cc-tweaked-$mcVersion-forge:$cctVersion"))
|
||||||
|
|
||||||
// Fabric Loom
|
// Fabric Loom
|
||||||
modCompileOnly("cc.tweaked:cc-tweaked-$mcVersion-fabric-api:$cctVersion")
|
modCompileOnly("cc.tweaked:cc-tweaked-$mcVersion-fabric-api:$cctVersion")
|
||||||
@@ -81,10 +82,9 @@ We bundle the API sources with the jar, so documentation should be easily viewab
|
|||||||
the generated documentation [can be browsed online](https://tweaked.cc/javadoc/).
|
the generated documentation [can be browsed online](https://tweaked.cc/javadoc/).
|
||||||
|
|
||||||
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
||||||
[curseforge]: https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked from CurseForge"
|
|
||||||
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
||||||
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."
|
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."
|
||||||
[forum]: https://forums.computercraft.cc/
|
|
||||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
[EsperNet]: https://www.esper.net/
|
||||||
|
[KiwiIRC]: https://kiwiirc.com/nextclient/#irc://irc.esper.net:+6697/#computercraft "#computercraft on EsperNet"
|
||||||
|
110
REUSE.toml
Normal file
110
REUSE.toml
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2017 The CC: Tweaked Developers
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
version = 1
|
||||||
|
SPDX-PackageName = "CC: Tweaked"
|
||||||
|
SPDX-PackageSupplier = "Jonathan Coates <git@squiddev.cc>"
|
||||||
|
SPDX-PackageDownloadLocation = "https://github.com/cc-tweaked/cc-tweaked"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Generated/data files are CC0.
|
||||||
|
SPDX-FileCopyrightText = "The CC: Tweaked Developers"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
path = [
|
||||||
|
"gradle/gradle-daemon-jvm.properties",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/sounds.json",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/sounds/empty.ogg",
|
||||||
|
"projects/common/src/testMod/resources/data/cctest/computercraft/turtle_upgrades/**",
|
||||||
|
"projects/common/src/testMod/resources/data/cctest/structures/**",
|
||||||
|
"projects/**/src/generated/**",
|
||||||
|
"projects/web/src/htmlTransform/export/index.json",
|
||||||
|
"projects/web/src/htmlTransform/export/items/minecraft/**",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Several assets where it's inconvenient to create a .license file.
|
||||||
|
SPDX-FileCopyrightText = "The CC: Tweaked Developers"
|
||||||
|
SPDX-License-Identifier = "MPL-2.0"
|
||||||
|
path = [
|
||||||
|
"doc/images/**",
|
||||||
|
"package.json",
|
||||||
|
"package-lock.json",
|
||||||
|
"projects/common/src/client/resources/computercraft-client.mixins.json",
|
||||||
|
"projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json",
|
||||||
|
"projects/common/src/main/resources/computercraft.mixins.json",
|
||||||
|
"projects/common/src/testMod/resources/computercraft-gametest.mixins.json",
|
||||||
|
"projects/common/src/testMod/resources/data/computercraft/loot_tables/treasure_disk.json",
|
||||||
|
"projects/common/src/testMod/resources/pack.mcmeta",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/modules/command/.ignoreme",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/.ignoreme",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/modules/turtle/.ignoreme",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/motd.txt",
|
||||||
|
"projects/fabric-api/src/main/modJson/fabric.mod.json",
|
||||||
|
"projects/fabric/src/client/resources/computercraft-client.fabric.mixins.json",
|
||||||
|
"projects/fabric/src/main/resources/computercraft.fabric.mixins.json",
|
||||||
|
"projects/fabric/src/main/resources/fabric.mod.json",
|
||||||
|
"projects/fabric/src/testMod/resources/computercraft-gametest.fabric.mixins.json",
|
||||||
|
"projects/fabric/src/testMod/resources/fabric.mod.json",
|
||||||
|
"projects/forge/src/client/resources/computercraft-client.forge.mixins.json",
|
||||||
|
"projects/web/src/frontend/mount/.settings",
|
||||||
|
"projects/web/src/frontend/mount/example.nfp",
|
||||||
|
"projects/web/src/frontend/mount/example.nft",
|
||||||
|
"projects/web/src/frontend/mount/expr_template.lua",
|
||||||
|
"projects/web/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Bulk-license original assets as CCPL.
|
||||||
|
SPDX-FileCopyrightText = "2011 Daniel Ratcliffe"
|
||||||
|
SPDX-License-Identifier = "LicenseRef-CCPL"
|
||||||
|
path = [
|
||||||
|
"doc/logo.png",
|
||||||
|
"doc/logo-darkmode.png",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/models/**",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/textures/**",
|
||||||
|
"projects/common/src/main/resources/pack.mcmeta",
|
||||||
|
"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/help/**",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/programs/fun/advanced/levels/**",
|
||||||
|
"projects/web/src/htmlTransform/export/items/computercraft/**",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Community-contributed license files
|
||||||
|
SPDX-FileCopyrightText = "2017 The CC: Tweaked Developers"
|
||||||
|
SPDX-License-Identifier = "LicenseRef-CCPL"
|
||||||
|
path = [
|
||||||
|
"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",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Community-contributed license files
|
||||||
|
SPDX-FileCopyrightText = "2017 The CC: Tweaked Developers"
|
||||||
|
SPDX-License-Identifier = "MPL-2.0"
|
||||||
|
path = "projects/common/src/main/resources/assets/computercraft/lang/**"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# GitHub build scripts are CC0. While we could add a header to each file,
|
||||||
|
# it's unclear if it will break actions or issue templates in some way.
|
||||||
|
SPDX-FileCopyrightText = "Jonathan Coates <git@squiddev.cc>"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
path = ".github/**"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ["gradle/wrapper/**"]
|
||||||
|
SPDX-FileCopyrightText = "Gradle Inc"
|
||||||
|
SPDX-License-Identifier = "Apache-2.0"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "projects/core/src/test/resources/test-rom/data/json-parsing/**"
|
||||||
|
SPDX-FileCopyrightText = "2016 Nicolas Seriot"
|
||||||
|
SPDX-License-Identifier = "MIT"
|
@@ -14,14 +14,18 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
|
|
||||||
maven("https://maven.neoforged.net/releases") {
|
maven("https://maven.minecraftforge.net") {
|
||||||
name = "NeoForge"
|
name = "Forge"
|
||||||
content {
|
content {
|
||||||
includeGroup("net.minecraftforge")
|
includeGroup("net.minecraftforge")
|
||||||
includeGroup("net.neoforged")
|
includeGroup("net.minecraftforge.gradle")
|
||||||
includeGroup("net.neoforged.gradle")
|
}
|
||||||
includeModule("codechicken", "DiffPatch")
|
}
|
||||||
includeModule("net.covers1624", "Quack")
|
|
||||||
|
maven("https://maven.parchmentmc.org") {
|
||||||
|
name = "Librarian"
|
||||||
|
content {
|
||||||
|
includeGroupByRegex("^org\\.parchmentmc.*")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +36,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
maven("https://squiddev.cc/maven") {
|
maven("https://maven.squiddev.cc") {
|
||||||
name = "SquidDev"
|
name = "SquidDev"
|
||||||
content {
|
content {
|
||||||
includeGroup("cc.tweaked.vanilla-extract")
|
includeGroup("cc.tweaked.vanilla-extract")
|
||||||
@@ -45,11 +49,11 @@ dependencies {
|
|||||||
implementation(libs.kotlin.plugin)
|
implementation(libs.kotlin.plugin)
|
||||||
implementation(libs.spotless)
|
implementation(libs.spotless)
|
||||||
|
|
||||||
implementation(libs.curseForgeGradle)
|
|
||||||
implementation(libs.fabric.loom)
|
implementation(libs.fabric.loom)
|
||||||
|
implementation(libs.forgeGradle)
|
||||||
implementation(libs.ideaExt)
|
implementation(libs.ideaExt)
|
||||||
|
implementation(libs.librarian)
|
||||||
implementation(libs.minotaur)
|
implementation(libs.minotaur)
|
||||||
implementation(libs.neoGradle.userdev)
|
|
||||||
implementation(libs.vanillaExtract)
|
implementation(libs.vanillaExtract)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,8 +10,10 @@ import cc.tweaked.gradle.IdeaRunConfigurations
|
|||||||
import cc.tweaked.gradle.MinecraftConfigurations
|
import cc.tweaked.gradle.MinecraftConfigurations
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
|
id("net.minecraftforge.gradle")
|
||||||
|
// We must apply java-convention after Forge, as we need the fg extension to be present.
|
||||||
id("cc-tweaked.java-convention")
|
id("cc-tweaked.java-convention")
|
||||||
id("net.neoforged.gradle.userdev")
|
id("org.parchmentmc.librarian.forgegradle")
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins.apply(CCTweakedPlugin::class.java)
|
plugins.apply(CCTweakedPlugin::class.java)
|
||||||
@@ -19,15 +21,10 @@ plugins.apply(CCTweakedPlugin::class.java)
|
|||||||
val mcVersion: String by extra
|
val mcVersion: String by extra
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
modIdentifier("computercraft")
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
}
|
mappings("parchment", "${libs.findVersion("parchmentMc").get()}-${libs.findVersion("parchment").get()}-$mcVersion")
|
||||||
|
|
||||||
subsystems {
|
accessTransformer(project(":forge").file("src/main/resources/META-INF/accesstransformer.cfg"))
|
||||||
parchment {
|
|
||||||
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
|
||||||
minecraftVersion = libs.findVersion("parchmentMc").get().toString()
|
|
||||||
mappingsVersion = libs.findVersion("parchment").get().toString()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MinecraftConfigurations.setup(project)
|
MinecraftConfigurations.setup(project)
|
||||||
@@ -35,3 +32,13 @@ MinecraftConfigurations.setup(project)
|
|||||||
extensions.configure(CCTweakedExtension::class.java) {
|
extensions.configure(CCTweakedExtension::class.java) {
|
||||||
linters(minecraft = true, loader = "forge")
|
linters(minecraft = true, loader = "forge")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
"minecraft"("net.minecraftforge:forge:$mcVersion-${libs.findVersion("forge").get()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.configureEach {
|
||||||
|
// genIntellijRuns isn't registered until much later, so we need this silly hijinks.
|
||||||
|
if (name == "genIntellijRuns") doLast { IdeaRunConfigurations(project).patch() }
|
||||||
|
}
|
||||||
|
@@ -38,15 +38,23 @@ java {
|
|||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
||||||
val mainMaven = maven("https://squiddev.cc/maven") {
|
val mainMaven = maven("https://maven.squiddev.cc/mirror") {
|
||||||
name = "SquidDev"
|
name = "SquidDev"
|
||||||
}
|
}
|
||||||
|
|
||||||
exclusiveContent {
|
exclusiveContent {
|
||||||
forRepositories(mainMaven)
|
forRepositories(mainMaven)
|
||||||
|
|
||||||
|
// Include the ForgeGradle repository if present. This requires that ForgeGradle is already present, which we
|
||||||
|
// enforce in our Forge overlay.
|
||||||
|
val fg =
|
||||||
|
project.extensions.findByType(net.minecraftforge.gradle.userdev.DependencyManagementExtension::class.java)
|
||||||
|
if (fg != null) forRepositories(fg.repository)
|
||||||
|
|
||||||
filter {
|
filter {
|
||||||
includeGroup("cc.tweaked")
|
includeGroup("cc.tweaked")
|
||||||
// Things we mirror
|
// Things we mirror
|
||||||
|
includeGroup("com.simibubi.create")
|
||||||
includeGroup("commoble.morered")
|
includeGroup("commoble.morered")
|
||||||
includeGroup("dev.architectury")
|
includeGroup("dev.architectury")
|
||||||
includeGroup("dev.emi")
|
includeGroup("dev.emi")
|
||||||
@@ -56,6 +64,7 @@ repositories {
|
|||||||
includeGroup("mezz.jei")
|
includeGroup("mezz.jei")
|
||||||
includeGroup("org.teavm")
|
includeGroup("org.teavm")
|
||||||
includeModule("com.terraformersmc", "modmenu")
|
includeModule("com.terraformersmc", "modmenu")
|
||||||
|
includeModule("me.lucko", "fabric-permissions-api")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,16 +86,8 @@ dependencies {
|
|||||||
// Configure default JavaCompile tasks with our arguments.
|
// Configure default JavaCompile tasks with our arguments.
|
||||||
sourceSets.all {
|
sourceSets.all {
|
||||||
tasks.named(compileJavaTaskName, JavaCompile::class.java) {
|
tasks.named(compileJavaTaskName, JavaCompile::class.java) {
|
||||||
|
// Processing just gives us "No processor claimed any of these annotations", so skip that!
|
||||||
options.compilerArgs.addAll(
|
options.compilerArgs.addAll(listOf("-Xlint", "-Xlint:-processing"))
|
||||||
listOf(
|
|
||||||
"-Xlint",
|
|
||||||
// Processing just gives us "No processor claimed any of these annotations", so skip that!
|
|
||||||
"-Xlint:-processing",
|
|
||||||
// We violate this pattern too often for it to be a helpful warning. Something to improve one day!
|
|
||||||
"-Xlint:-this-escape",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
options.errorprone {
|
options.errorprone {
|
||||||
check("InvalidBlockTag", CheckSeverity.OFF) // Broken by @cc.xyz
|
check("InvalidBlockTag", CheckSeverity.OFF) // Broken by @cc.xyz
|
||||||
@@ -133,8 +134,8 @@ tasks.processResources {
|
|||||||
tasks.withType(AbstractArchiveTask::class.java).configureEach {
|
tasks.withType(AbstractArchiveTask::class.java).configureEach {
|
||||||
isPreserveFileTimestamps = false
|
isPreserveFileTimestamps = false
|
||||||
isReproducibleFileOrder = true
|
isReproducibleFileOrder = true
|
||||||
dirMode = Integer.valueOf("755", 8)
|
filePermissions {}
|
||||||
fileMode = Integer.valueOf("664", 8)
|
dirPermissions {}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.jar {
|
tasks.jar {
|
||||||
@@ -154,7 +155,7 @@ tasks.javadoc {
|
|||||||
options {
|
options {
|
||||||
val stdOptions = this as StandardJavadocDocletOptions
|
val stdOptions = this as StandardJavadocDocletOptions
|
||||||
stdOptions.addBooleanOption("Xdoclint:all,-missing", true)
|
stdOptions.addBooleanOption("Xdoclint:all,-missing", true)
|
||||||
stdOptions.links("https://docs.oracle.com/en/java/javase/21/docs/api/")
|
stdOptions.links("https://docs.oracle.com/en/java/javase/17/docs/api/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,11 +2,9 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
import net.darkhax.curseforgegradle.TaskPublishCurseForge
|
|
||||||
import cc.tweaked.gradle.setProvider
|
import cc.tweaked.gradle.setProvider
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("net.darkhax.curseforgegradle")
|
|
||||||
id("com.modrinth.minotaur")
|
id("com.modrinth.minotaur")
|
||||||
id("cc-tweaked.publishing")
|
id("cc-tweaked.publishing")
|
||||||
}
|
}
|
||||||
@@ -25,23 +23,6 @@ val isUnstable = project.properties["isUnstable"] == "true"
|
|||||||
val modVersion: String by extra
|
val modVersion: String by extra
|
||||||
val mcVersion: String by extra
|
val mcVersion: String by extra
|
||||||
|
|
||||||
val publishCurseForge by tasks.registering(TaskPublishCurseForge::class) {
|
|
||||||
group = PublishingPlugin.PUBLISH_TASK_GROUP
|
|
||||||
description = "Upload artifacts to CurseForge"
|
|
||||||
|
|
||||||
apiToken = findProperty("curseForgeApiKey") ?: ""
|
|
||||||
enabled = apiToken != ""
|
|
||||||
|
|
||||||
val mainFile = upload("282001", modPublishing.output)
|
|
||||||
mainFile.changelog =
|
|
||||||
"Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion)."
|
|
||||||
mainFile.changelogType = "markdown"
|
|
||||||
mainFile.releaseType = if (isUnstable) "alpha" else "release"
|
|
||||||
mainFile.gameVersions.add(mcVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.publish { dependsOn(publishCurseForge) }
|
|
||||||
|
|
||||||
modrinth {
|
modrinth {
|
||||||
token.set(findProperty("modrinthApiKey") as String? ?: "")
|
token.set(findProperty("modrinthApiKey") as String? ?: "")
|
||||||
projectId.set("gu7yAYhd")
|
projectId.set("gu7yAYhd")
|
||||||
|
@@ -38,7 +38,7 @@ publishing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://squiddev.cc/maven") {
|
maven("https://maven.squiddev.cc") {
|
||||||
name = "SquidDev"
|
name = "SquidDev"
|
||||||
|
|
||||||
credentials(PasswordCredentials::class)
|
credentials(PasswordCredentials::class)
|
||||||
|
@@ -22,7 +22,6 @@ import org.gradle.api.tasks.SourceSet
|
|||||||
import org.gradle.api.tasks.bundling.Jar
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
import org.gradle.api.tasks.compile.JavaCompile
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
import org.gradle.api.tasks.javadoc.Javadoc
|
import org.gradle.api.tasks.javadoc.Javadoc
|
||||||
import org.gradle.configurationcache.extensions.capitalized
|
|
||||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
import org.gradle.language.jvm.tasks.ProcessResources
|
import org.gradle.language.jvm.tasks.ProcessResources
|
||||||
import org.gradle.process.JavaForkOptions
|
import org.gradle.process.JavaForkOptions
|
||||||
@@ -181,7 +180,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.layout.buildDirectory.dir("jacocoClassDump/${task.name}")
|
val classDump = project.layout.buildDirectory.dir("jacocoClassDump/${task.name}")
|
||||||
val reportTaskName = "jacoco${task.name.capitalized()}Report"
|
val reportTaskName = "jacoco${task.name.capitalise()}Report"
|
||||||
|
|
||||||
val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
|
val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
|
||||||
task.configure {
|
task.configure {
|
||||||
@@ -270,7 +269,7 @@ abstract class CCTweakedExtension(
|
|||||||
companion object {
|
companion object {
|
||||||
private val COMMIT_COUNTS = Pattern.compile("""^\s*[0-9]+\s+(.*)$""")
|
private val COMMIT_COUNTS = Pattern.compile("""^\s*[0-9]+\s+(.*)$""")
|
||||||
private val IGNORED_USERS = setOf(
|
private val IGNORED_USERS = setOf(
|
||||||
"GitHub", "Daniel Ratcliffe", "Weblate",
|
"GitHub", "Daniel Ratcliffe", "NotSquidDev", "Weblate",
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun <T> gitProvider(project: Project, default: T, supplier: () -> T): Provider<T> {
|
private fun <T> gitProvider(project: Project, default: T, supplier: () -> T): Provider<T> {
|
||||||
|
@@ -42,6 +42,6 @@ class CCTweakedPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val JAVA_VERSION = JavaLanguageVersion.of(21)
|
val JAVA_VERSION = JavaLanguageVersion.of(17)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -143,7 +143,7 @@ fun getNextVersion(version: String): String {
|
|||||||
val lastIndex = mainVersion.lastIndexOf('.')
|
val lastIndex = mainVersion.lastIndexOf('.')
|
||||||
if (lastIndex < 0) throw IllegalArgumentException("Cannot parse version format \"$version\"")
|
if (lastIndex < 0) throw IllegalArgumentException("Cannot parse version format \"$version\"")
|
||||||
val lastVersion = try {
|
val lastVersion = try {
|
||||||
version.substring(lastIndex + 1).toInt()
|
mainVersion.substring(lastIndex + 1).toInt()
|
||||||
} catch (e: NumberFormatException) {
|
} catch (e: NumberFormatException) {
|
||||||
throw IllegalArgumentException("Cannot parse version format \"$version\"", e)
|
throw IllegalArgumentException("Cannot parse version format \"$version\"", e)
|
||||||
}
|
}
|
||||||
@@ -155,3 +155,15 @@ fun getNextVersion(version: String): String {
|
|||||||
if (dashIndex >= 0) out.append(version, dashIndex, version.length)
|
if (dashIndex >= 0) out.append(version, dashIndex, version.length)
|
||||||
return out.toString()
|
return out.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capitalise the first letter of the string.
|
||||||
|
*
|
||||||
|
* This is a replacement for the now deprecated [String.capitalize].
|
||||||
|
*/
|
||||||
|
fun String.capitalise(): String {
|
||||||
|
if (isEmpty()) return this
|
||||||
|
val first = this[0]
|
||||||
|
val firstTitle = first.titlecaseChar()
|
||||||
|
return if (first == firstTitle) this else firstTitle + substring(1)
|
||||||
|
}
|
||||||
|
@@ -4,59 +4,23 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
import net.neoforged.gradle.common.runs.run.RunImpl
|
import net.minecraftforge.gradle.common.util.RunConfig
|
||||||
import net.neoforged.gradle.common.runs.tasks.RunExec
|
import net.minecraftforge.gradle.common.util.runs.setRunConfigInternal
|
||||||
import net.neoforged.gradle.dsl.common.extensions.RunnableSourceSet
|
|
||||||
import net.neoforged.gradle.dsl.common.runs.run.Run
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
import org.gradle.api.tasks.JavaExec
|
import org.gradle.api.tasks.JavaExec
|
||||||
import org.gradle.api.tasks.SourceSet
|
|
||||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
import org.gradle.jvm.toolchain.JavaToolchainService
|
||||||
import org.gradle.kotlin.dsl.assign
|
|
||||||
import org.gradle.kotlin.dsl.create
|
|
||||||
import org.gradle.kotlin.dsl.findByType
|
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set [JavaExec] task to run a given [RunConfig].
|
* Set [JavaExec] task to run a given [RunConfig].
|
||||||
*
|
|
||||||
* See also [RunExec].
|
|
||||||
*/
|
*/
|
||||||
fun JavaExec.setRunConfig(config: Run) {
|
fun JavaExec.setRunConfig(config: RunConfig) {
|
||||||
mainClass.set(config.mainClass)
|
dependsOn("prepareRuns")
|
||||||
workingDir = config.workingDirectory.get().asFile
|
setRunConfigInternal(project, this, config)
|
||||||
argumentProviders.add { config.programArguments.get() }
|
doFirst("Create working directory") { Files.createDirectories(workingDir.toPath()) }
|
||||||
jvmArgumentProviders.add { config.jvmArguments.get() }
|
|
||||||
|
|
||||||
environment(config.environmentVariables.get())
|
|
||||||
systemProperties(config.systemProperties.get())
|
|
||||||
|
|
||||||
config.modSources.all().get().values().forEach { classpath(it.runtimeClasspath) }
|
|
||||||
classpath(config.classpath)
|
|
||||||
classpath(config.dependencies.get().runtimeConfiguration)
|
|
||||||
|
|
||||||
(config as RunImpl).taskDependencies.forEach { dependsOn(it) }
|
|
||||||
|
|
||||||
javaLauncher.set(
|
javaLauncher.set(
|
||||||
project.extensions.getByType(JavaToolchainService::class.java)
|
project.extensions.getByType(JavaToolchainService::class.java)
|
||||||
.launcherFor(project.extensions.getByType(JavaPluginExtension::class.java).toolchain),
|
.launcherFor(project.extensions.getByType(JavaPluginExtension::class.java).toolchain),
|
||||||
)
|
)
|
||||||
|
|
||||||
doFirst("Create working directory") { Files.createDirectories(workingDir.toPath()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new [Run.modSource] with a specific mod id.
|
|
||||||
*/
|
|
||||||
fun Run.modSourceAs(sourceSet: SourceSet, mod: String) {
|
|
||||||
// NeoGradle requires a RunnableSourceSet to be present, so we inject it into other project's source sets.
|
|
||||||
val runnable = sourceSet.extensions.findByType<RunnableSourceSet>() ?: run {
|
|
||||||
val extension = sourceSet.extensions.create<RunnableSourceSet>(RunnableSourceSet.NAME, project)
|
|
||||||
extension.modIdentifier = mod
|
|
||||||
extension.modIdentifier.finalizeValueOnRead()
|
|
||||||
extension
|
|
||||||
}
|
|
||||||
if (runnable.modIdentifier.get() != mod) throw IllegalArgumentException("Multiple mod identifiers")
|
|
||||||
|
|
||||||
modSource(sourceSet)
|
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import net.minecraftforge.gradle.common.util.RunConfig
|
||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.file.FileSystemOperations
|
import org.gradle.api.file.FileSystemOperations
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
@@ -64,6 +65,14 @@ abstract class ClientJavaExec : JavaExec() {
|
|||||||
setTestProperties()
|
setTestProperties()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this task to run a given [RunConfig].
|
||||||
|
*/
|
||||||
|
fun setRunConfig(config: RunConfig) {
|
||||||
|
(this as JavaExec).setRunConfig(config)
|
||||||
|
setTestProperties() // setRunConfig may clobber some properties, ensure everything is set.
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy configuration from a task with the given name.
|
* Copy configuration from a task with the given name.
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,51 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package net.minecraftforge.gradle.common.util.runs
|
||||||
|
|
||||||
|
import net.minecraftforge.gradle.common.util.RunConfig
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.process.CommandLineArgumentProvider
|
||||||
|
import org.gradle.process.JavaExecSpec
|
||||||
|
import java.io.File
|
||||||
|
import java.util.function.Supplier
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
import java.util.stream.Stream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up a [JavaExecSpec] to execute a [RunConfig].
|
||||||
|
*
|
||||||
|
* [MinecraftRunTask] sets up all its properties when the task is executed, rather than when configured. As such, it's
|
||||||
|
* not possible to use [cc.tweaked.gradle.copyToFull] like we do for Fabric. Instead, we set up the task manually.
|
||||||
|
*
|
||||||
|
* Unfortunately most of the functionality we need is package-private, and so we have to put our code into the package.
|
||||||
|
*/
|
||||||
|
internal fun setRunConfigInternal(project: Project, spec: JavaExecSpec, config: RunConfig) {
|
||||||
|
spec.workingDir = File(config.workingDirectory)
|
||||||
|
|
||||||
|
spec.mainClass.set(config.main)
|
||||||
|
for (source in config.allSources) spec.classpath(source.runtimeClasspath)
|
||||||
|
|
||||||
|
val originalTask = project.tasks.named(config.taskName, MinecraftRunTask::class.java)
|
||||||
|
|
||||||
|
// Add argument and JVM argument via providers, to be as lazy as possible with fetching artifacts.
|
||||||
|
val lazyTokens = RunConfigGenerator.configureTokensLazy(
|
||||||
|
project, config, RunConfigGenerator.mapModClassesToGradle(project, config),
|
||||||
|
originalTask.get().minecraftArtifacts,
|
||||||
|
originalTask.get().runtimeClasspathArtifacts,
|
||||||
|
)
|
||||||
|
spec.argumentProviders.add(
|
||||||
|
CommandLineArgumentProvider {
|
||||||
|
RunConfigGenerator.getArgsStream(config, lazyTokens, false).toList()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
spec.jvmArgumentProviders.add(
|
||||||
|
CommandLineArgumentProvider {
|
||||||
|
(if (config.isClient) config.jvmArgs + originalTask.get().additionalClientArgs.get() else config.jvmArgs).map { config.replace(lazyTokens, it) } +
|
||||||
|
config.properties.map { (k, v) -> "-D${k}=${config.replace(lazyTokens, v)}" }
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
for ((key, value) in config.environment) spec.environment(key, config.replace(lazyTokens, value))
|
||||||
|
}
|
@@ -22,7 +22,4 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
|
|
||||||
<!-- Allow underscores in our test classes. -->
|
<!-- Allow underscores in our test classes. -->
|
||||||
<suppress checks="MethodName" files=".*(Contract|Test).java" />
|
<suppress checks="MethodName" files=".*(Contract|Test).java" />
|
||||||
|
|
||||||
<!-- Allow underscores in Mixin classes -->
|
|
||||||
<suppress checks="TypeName" files=".*[\\/]mixin[\\/].*.java" />
|
|
||||||
</suppressions>
|
</suppressions>
|
||||||
|
28
crowdin.yml
Normal file
28
crowdin.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2017 The CC: Tweaked Developers
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
files:
|
||||||
|
- source: projects/common/src/generated/resources/assets/computercraft/lang/en_us.json
|
||||||
|
translation: /projects/common/src/main/resources/assets/computercraft/lang/%locale_with_underscore%.json
|
||||||
|
languages_mapping:
|
||||||
|
locale_with_underscore:
|
||||||
|
cs: cs_cz # Czech
|
||||||
|
da: da_dk # Danish
|
||||||
|
de: de_de # German
|
||||||
|
es-ES: es_es # Spanish
|
||||||
|
fr: fr_fr # French
|
||||||
|
it: it_it # Italian
|
||||||
|
ja: ja_jp # Japanese
|
||||||
|
ko: ko_kr # Korean
|
||||||
|
nb: nb_no # Norwegian Bokmal
|
||||||
|
nl: nl_nl # Dutch
|
||||||
|
pl: pl_pl # Polish
|
||||||
|
pt-BR: pt_br # Portuguese, Brazilian
|
||||||
|
ru: ru_ru # Russian
|
||||||
|
sv-SE: sv_se # Sweedish
|
||||||
|
tok: tok # Toki Pona
|
||||||
|
tr: tr_tr # Turkish
|
||||||
|
uk: uk_ua # Ukraine
|
||||||
|
vi: vi_vn # Vietnamese
|
||||||
|
zh-CN: zh_cn # Chinese Simplified
|
@@ -8,7 +8,7 @@ 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 or [relay][`redstone_relay`] change.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. [`string`]: The event name.
|
1. [`string`]: The event name.
|
||||||
@@ -21,3 +21,7 @@ while true do
|
|||||||
print("A redstone input has changed!")
|
print("A redstone input has changed!")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## See also
|
||||||
|
- [The `redstone` API on computers][`module!redstone`]
|
||||||
|
- [The `redstone_relay` peripheral][`redstone_relay`]
|
||||||
|
@@ -191,7 +191,7 @@ end
|
|||||||
|
|
||||||
> [Confused?][!NOTE]
|
> [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 [the community for help][community].
|
||||||
|
|
||||||
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.
|
||||||
@@ -205,5 +205,4 @@ This is, I'm afraid, left as an exercise to the reader.
|
|||||||
[PCM]: https://en.wikipedia.org/wiki/Pulse-code_modulation "Pulse-code Modulation - Wikipedia"
|
[PCM]: https://en.wikipedia.org/wiki/Pulse-code_modulation "Pulse-code Modulation - Wikipedia"
|
||||||
[Ring Buffer]: https://en.wikipedia.org/wiki/Circular_buffer "Circular buffer - Wikipedia"
|
[Ring Buffer]: https://en.wikipedia.org/wiki/Circular_buffer "Circular buffer - Wikipedia"
|
||||||
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
|
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
|
||||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
[Community]: /#community
|
||||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
|
||||||
|
12
doc/index.md
12
doc/index.md
@@ -16,7 +16,7 @@ CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles an
|
|||||||
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
|
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
|
||||||
new features.
|
new features.
|
||||||
|
|
||||||
CC: Tweaked can be installed from [CurseForge] or [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
|
CC: Tweaked can be installed from [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
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
|
||||||
@@ -50,7 +50,11 @@ little daunting getting started. Thankfully, there's several fantastic tutorials
|
|||||||
Once you're a little more familiar with the mod, the sidebar and links below provide more detailed documentation on the
|
Once you're a little more familiar with the mod, the sidebar and links below provide more detailed documentation on the
|
||||||
various APIs and peripherals provided by the mod.
|
various APIs and peripherals provided by the mod.
|
||||||
|
|
||||||
If you get stuck, do [ask a question on GitHub][GitHub Discussions] or pop in to the ComputerCraft's [IRC channel][IRC].
|
<h2 id="community">Community</h2>
|
||||||
|
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
||||||
|
ComputerCraft, do check out our [GitHub discussions page][GitHub discussions]! There's also a fairly populated,
|
||||||
|
albeit quiet IRC channel on [EsperNet], if that's more your cup of tea. You can join `#computercraft` through your
|
||||||
|
desktop client, or online using [KiwiIRC].
|
||||||
|
|
||||||
## Get Involved
|
## Get Involved
|
||||||
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
||||||
@@ -58,11 +62,11 @@ CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please
|
|||||||
[github]: https://github.com/cc-tweaked/CC-Tweaked/ "CC: Tweaked on GitHub"
|
[github]: https://github.com/cc-tweaked/CC-Tweaked/ "CC: Tweaked on GitHub"
|
||||||
[bug]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose
|
[bug]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose
|
||||||
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
||||||
[curseforge]: https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked from CurseForge"
|
|
||||||
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
||||||
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."
|
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."
|
||||||
[lua]: https://www.lua.org/ "Lua's main website"
|
[lua]: https://www.lua.org/ "Lua's main website"
|
||||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
[EsperNet]: https://www.esper.net/
|
||||||
|
[KiwiIRC]: https://kiwiirc.com/nextclient/#irc://irc.esper.net:+6697/#computercraft "#computercraft on EsperNet"
|
||||||
|
@@ -50,7 +50,11 @@ little daunting getting started. Thankfully, there's several fantastic tutorials
|
|||||||
Once you're a little more familiar with the mod, the [wiki](https://tweaked.cc/) provides more detailed documentation on the
|
Once you're a little more familiar with the mod, the [wiki](https://tweaked.cc/) provides more detailed documentation on the
|
||||||
various APIs and peripherals provided by the mod.
|
various APIs and peripherals provided by the mod.
|
||||||
|
|
||||||
If you get stuck, do [ask a question on GitHub][GitHub Discussions] or pop in to the ComputerCraft's [IRC channel][IRC].
|
## Community
|
||||||
|
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
||||||
|
ComputerCraft, do check out our [GitHub discussions page][GitHub discussions]! There's also a fairly populated,
|
||||||
|
albeit quiet IRC channel on [EsperNet], if that's more your cup of tea. You can join `#computercraft` through your
|
||||||
|
desktop client, or online using [KiwiIRC].
|
||||||
|
|
||||||
## Get Involved
|
## Get Involved
|
||||||
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
||||||
@@ -60,4 +64,5 @@ CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please
|
|||||||
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
||||||
[lua]: https://www.lua.org/ "Lua's main website"
|
[lua]: https://www.lua.org/ "Lua's main website"
|
||||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
[IRC]: http://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
[EsperNet]: https://www.esper.net/
|
||||||
|
[KiwiIRC]: https://kiwiirc.com/nextclient/#irc://irc.esper.net:+6697/#computercraft "#computercraft on EsperNet"
|
||||||
|
@@ -25,13 +25,13 @@ as documentation for breaking changes and "gotchas" one should look out for betw
|
|||||||
|
|
||||||
- Update to Lua 5.2:
|
- Update to Lua 5.2:
|
||||||
- Support for Lua 5.0's pseudo-argument `arg` has been removed. You should always use `...` for varargs.
|
- Support for Lua 5.0's pseudo-argument `arg` has been removed. You should always use `...` for varargs.
|
||||||
- Environments are no longer baked into the runtime, and instead use the `_ENV` local or upvalue. `getfenv`/`setfenv`
|
- Environments are no longer baked into the runtime, and instead use the `_ENV` local or upvalue. [`getfenv`]/[`setfenv`]
|
||||||
now only work on Lua functions with an `_ENV` upvalue. `getfenv` will return the global environment when called
|
now only work on Lua functions with an `_ENV` upvalue. [`getfenv`] will return the global environment when called
|
||||||
with other functions, and `setfenv` will have no effect.
|
with other functions, and [`setfenv`] will have no effect.
|
||||||
- `load`/`loadstring` defaults to using the global environment (`_G`) rather than the current coroutine's
|
- [`load`]/[`loadstring`] defaults to using the global environment (`_G`) rather than the current coroutine's
|
||||||
environment.
|
environment.
|
||||||
- Support for dumping functions (`string.dump`) and loading binary chunks has been removed.
|
- Support for dumping functions ([`string.dump`]) and loading binary chunks has been removed.
|
||||||
- `math.random` now uses Lua 5.4's random number generator.
|
- [`math.random`] now uses Lua 5.4's random number generator.
|
||||||
|
|
||||||
- File handles, HTTP requests and websockets now always use the original bytes rather than encoding/decoding to UTF-8.
|
- File handles, HTTP requests and websockets now always use the original bytes rather than encoding/decoding to UTF-8.
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ as documentation for breaking changes and "gotchas" one should look out for betw
|
|||||||
`keys.enter` constant was queued when the key was pressed)
|
`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
|
- 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.
|
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
|
- Block states (`turtle.inspect().state`) should provide all the same information as block metadata, but in a much
|
||||||
more understandable format.
|
more understandable format.
|
||||||
@@ -70,7 +70,7 @@ as documentation for breaking changes and "gotchas" one should look out for betw
|
|||||||
- Unlabelled computers and turtles now keep their ID when broken, meaning that unlabelled computers/items do not stack.
|
- Unlabelled computers and turtles now keep their ID when broken, meaning that unlabelled computers/items do not stack.
|
||||||
|
|
||||||
## ComputerCraft 1.80pr1 {#cc-1.80}
|
## 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
|
- 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.
|
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,
|
- Programs containing `/` are looked up in the current directory and are no longer looked up on the path. For instance,
|
||||||
|
@@ -81,7 +81,7 @@ compatibility for these newer versions.
|
|||||||
| `string.dump` strip argument | ✔ | |
|
| `string.dump` strip argument | ✔ | |
|
||||||
| `string.pack`/`string.unpack`/`string.packsize` | ✔ | |
|
| `string.pack`/`string.unpack`/`string.packsize` | ✔ | |
|
||||||
| `table.move` | ✔ | |
|
| `table.move` | ✔ | |
|
||||||
| `math.atan2` -> `math.atan` | ❌ | |
|
| `math.atan2` -> `math.atan` | 🔶 | `math.atan` supports its two argument form. |
|
||||||
| Removed `math.frexp`, `math.ldexp`, `math.pow`, `math.cosh`, `math.sinh`, `math.tanh` | ❌ | |
|
| Removed `math.frexp`, `math.ldexp`, `math.pow`, `math.cosh`, `math.sinh`, `math.tanh` | ❌ | |
|
||||||
| `math.maxinteger`/`math.mininteger` | ❌ | |
|
| `math.maxinteger`/`math.mininteger` | ❌ | |
|
||||||
| `math.tointeger` | ❌ | |
|
| `math.tointeger` | ❌ | |
|
||||||
|
@@ -8,11 +8,9 @@ org.gradle.parallel=true
|
|||||||
kotlin.stdlib.default.dependency=false
|
kotlin.stdlib.default.dependency=false
|
||||||
kotlin.jvm.target.validation.mode=error
|
kotlin.jvm.target.validation.mode=error
|
||||||
|
|
||||||
neogradle.subsystems.conventions.runs.enabled=false
|
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
isUnstable=true
|
isUnstable=false
|
||||||
modVersion=1.111.0
|
modVersion=1.114.2
|
||||||
|
|
||||||
# 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.21
|
mcVersion=1.20.1
|
||||||
|
2
gradle/gradle-daemon-jvm.properties
Normal file
2
gradle/gradle-daemon-jvm.properties
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#This file is generated by updateDaemonJvm
|
||||||
|
toolchainVersion=17
|
@@ -6,27 +6,27 @@
|
|||||||
|
|
||||||
# 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/neoforge.mods.toml
|
# Remember to update corresponding versions in fabric.mod.json/mods.toml
|
||||||
fabric-api = "0.100.3+1.21"
|
fabric-api = "0.86.1+1.20.1"
|
||||||
fabric-loader = "0.15.11"
|
fabric-loader = "0.14.21"
|
||||||
neoForge = "21.0.21-beta"
|
forge = "47.1.0"
|
||||||
neoForgeSpi = "8.0.1"
|
forgeSpi = "7.0.1"
|
||||||
mixin = "0.8.5"
|
mixin = "0.8.5"
|
||||||
parchment = "2024.06.16"
|
parchment = "2023.08.20"
|
||||||
parchmentMc = "1.20.6"
|
parchmentMc = "1.20.1"
|
||||||
yarn = "1.21+build.1"
|
yarn = "1.20.1+build.10"
|
||||||
|
|
||||||
# Core dependencies (these versions are tied to the version Minecraft uses)
|
# Core dependencies (these versions are tied to the version Minecraft uses)
|
||||||
fastutil = "8.5.12"
|
fastutil = "8.5.9"
|
||||||
guava = "32.1.2-jre"
|
guava = "31.1-jre"
|
||||||
netty = "4.1.97.Final"
|
netty = "4.1.82.Final"
|
||||||
slf4j = "2.0.9"
|
slf4j = "2.0.1"
|
||||||
|
|
||||||
# Core dependencies (independent of Minecraft)
|
# Core dependencies (independent of Minecraft)
|
||||||
asm = "9.6"
|
asm = "9.6"
|
||||||
autoService = "1.1.1"
|
autoService = "1.1.1"
|
||||||
checkerFramework = "3.42.0"
|
checkerFramework = "3.42.0"
|
||||||
cobalt = { strictly = "0.9.3" }
|
cobalt = { strictly = "0.9.5" }
|
||||||
commonsCli = "1.6.0"
|
commonsCli = "1.6.0"
|
||||||
jetbrainsAnnotations = "24.1.0"
|
jetbrainsAnnotations = "24.1.0"
|
||||||
jsr305 = "3.0.2"
|
jsr305 = "3.0.2"
|
||||||
@@ -36,17 +36,18 @@ kotlin-coroutines = "1.7.3"
|
|||||||
nightConfig = "3.6.7"
|
nightConfig = "3.6.7"
|
||||||
|
|
||||||
# Minecraft mods
|
# Minecraft mods
|
||||||
emi = "1.1.7+1.21"
|
emi = "1.0.8+1.20.1"
|
||||||
fabricPermissions = "0.3.1"
|
fabricPermissions = "0.3.20230723"
|
||||||
iris = "1.6.14+1.20.4"
|
iris = "1.6.4+1.20"
|
||||||
jei = "19.0.0.1"
|
jei = "15.2.0.22"
|
||||||
modmenu = "11.0.0-rc.4"
|
modmenu = "7.1.0"
|
||||||
moreRed = "4.0.0.4"
|
moreRed = "4.0.0.4"
|
||||||
oculus = "1.2.5"
|
oculus = "1.2.5"
|
||||||
rei = "16.0.729"
|
rei = "12.0.626"
|
||||||
rubidium = "0.6.1"
|
rubidium = "0.6.1"
|
||||||
sodium = "mc1.20-0.4.10"
|
sodium = "mc1.20-0.4.10"
|
||||||
mixinExtra = "0.3.5"
|
create-forge = "0.5.1.f-33"
|
||||||
|
create-fabric = "0.5.1-f-build.1467+mc1.20.1"
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
hamcrest = "2.2"
|
hamcrest = "2.2"
|
||||||
@@ -55,23 +56,24 @@ junit = "5.10.1"
|
|||||||
jmh = "1.37"
|
jmh = "1.37"
|
||||||
|
|
||||||
# Build tools
|
# Build tools
|
||||||
cctJavadoc = "1.8.2"
|
cctJavadoc = "1.8.3"
|
||||||
checkstyle = "10.14.1"
|
checkstyle = "10.14.1"
|
||||||
curseForgeGradle = "1.1.18"
|
|
||||||
errorProne-core = "2.27.0"
|
errorProne-core = "2.27.0"
|
||||||
errorProne-plugin = "3.1.0"
|
errorProne-plugin = "3.1.0"
|
||||||
fabric-loom = "1.6.7"
|
fabric-loom = "1.7.1"
|
||||||
|
forgeGradle = "6.0.21"
|
||||||
githubRelease = "2.5.2"
|
githubRelease = "2.5.2"
|
||||||
gradleVersions = "0.50.0"
|
gradleVersions = "0.50.0"
|
||||||
ideaExt = "1.1.7"
|
ideaExt = "1.1.7"
|
||||||
illuaminate = "0.1.0-73-g43ee16c"
|
illuaminate = "0.1.0-74-gf1551d5"
|
||||||
|
librarian = "1.+"
|
||||||
lwjgl = "3.3.3"
|
lwjgl = "3.3.3"
|
||||||
minotaur = "2.8.7"
|
minotaur = "2.+"
|
||||||
neoGradle = "7.0.145"
|
|
||||||
nullAway = "0.10.25"
|
nullAway = "0.10.25"
|
||||||
|
shadow = "8.3.1"
|
||||||
spotless = "6.23.3"
|
spotless = "6.23.3"
|
||||||
taskTree = "2.1.1"
|
taskTree = "2.1.1"
|
||||||
teavm = "0.10.0-SQUID.4"
|
teavm = "0.11.0-SQUID.1"
|
||||||
vanillaExtract = "0.1.3"
|
vanillaExtract = "0.1.3"
|
||||||
versionCatalogUpdate = "0.8.1"
|
versionCatalogUpdate = "0.8.1"
|
||||||
|
|
||||||
@@ -84,7 +86,7 @@ checkerFramework = { module = "org.checkerframework:checker-qual", version.ref =
|
|||||||
cobalt = { module = "cc.tweaked:cobalt", version.ref = "cobalt" }
|
cobalt = { module = "cc.tweaked:cobalt", version.ref = "cobalt" }
|
||||||
commonsCli = { module = "commons-cli:commons-cli", version.ref = "commonsCli" }
|
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" }
|
||||||
neoForgeSpi = { module = "net.neoforged:neoforgespi", version.ref = "neoForgeSpi" }
|
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" }
|
||||||
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
||||||
jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" }
|
jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" }
|
||||||
@@ -92,25 +94,27 @@ jzlib = { module = "com.jcraft:jzlib", version.ref = "jzlib" }
|
|||||||
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
|
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
|
||||||
kotlin-platform = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
|
kotlin-platform = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
|
||||||
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
|
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
|
||||||
|
netty-codec = { module = "io.netty:netty-codec", version.ref = "netty" }
|
||||||
netty-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
|
netty-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
|
||||||
netty-socks = { module = "io.netty:netty-codec-socks", version.ref = "netty" }
|
|
||||||
netty-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" }
|
netty-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" }
|
||||||
|
netty-socks = { module = "io.netty:netty-codec-socks", version.ref = "netty" }
|
||||||
nightConfig-core = { module = "com.electronwill.night-config:core", version.ref = "nightConfig" }
|
nightConfig-core = { module = "com.electronwill.night-config:core", version.ref = "nightConfig" }
|
||||||
nightConfig-toml = { module = "com.electronwill.night-config:toml", version.ref = "nightConfig" }
|
nightConfig-toml = { module = "com.electronwill.night-config:toml", version.ref = "nightConfig" }
|
||||||
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
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" }
|
create-fabric = { module = "com.simibubi.create:create-fabric-1.20.1", version.ref = "create-fabric" }
|
||||||
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" }
|
create-forge = { module = "com.simibubi.create:create-1.20.1", version.ref = "create-forge" }
|
||||||
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" }
|
||||||
|
fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" }
|
||||||
|
fabric-junit = { module = "net.fabricmc:fabric-loader-junit", version.ref = "fabric-loader" }
|
||||||
|
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" }
|
||||||
|
fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" }
|
||||||
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
|
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
|
||||||
jei-api = { module = "mezz.jei:jei-1.21-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.21-fabric", version.ref = "jei" }
|
jei-fabric = { module = "mezz.jei:jei-1.20.1-fabric", version.ref = "jei" }
|
||||||
jei-forge = { module = "mezz.jei:jei-1.21-neoforge", 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" }
|
||||||
mixinExtra = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinExtra" }
|
|
||||||
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" }
|
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" }
|
||||||
@@ -140,17 +144,17 @@ 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" }
|
||||||
curseForgeGradle = { module = "net.darkhax.curseforgegradle:CurseForgeGradle", version.ref = "curseForgeGradle" }
|
|
||||||
errorProne-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorProne-core" }
|
errorProne-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorProne-core" }
|
||||||
errorProne-api = { module = "com.google.errorprone:error_prone_check_api", version.ref = "errorProne-core" }
|
errorProne-api = { module = "com.google.errorprone:error_prone_check_api", version.ref = "errorProne-core" }
|
||||||
errorProne-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne-core" }
|
errorProne-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne-core" }
|
||||||
errorProne-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorProne-plugin" }
|
errorProne-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorProne-plugin" }
|
||||||
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" }
|
||||||
ideaExt = { module = "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext", version.ref = "ideaExt" }
|
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" }
|
||||||
minotaur = { module = "com.modrinth.minotaur:Minotaur", version.ref = "minotaur" }
|
minotaur = { module = "com.modrinth.minotaur:Minotaur", version.ref = "minotaur" }
|
||||||
neoGradle-userdev = { module = "net.neoforged.gradle:userdev", version.ref = "neoGradle" }
|
|
||||||
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
|
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
|
||||||
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-classlib = { module = "org.teavm:teavm-classlib", version.ref = "teavm" }
|
||||||
@@ -166,9 +170,12 @@ vanillaExtract = { module = "cc.tweaked.vanilla-extract:plugin", version.ref = "
|
|||||||
yarn = { module = "net.fabricmc:yarn", version.ref = "yarn" }
|
yarn = { module = "net.fabricmc:yarn", version.ref = "yarn" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
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" }
|
||||||
gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradleVersions" }
|
gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradleVersions" }
|
||||||
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" }
|
||||||
|
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
||||||
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
||||||
versionCatalogUpdate = { id = "nl.littlerobots.version-catalog-update", version.ref = "versionCatalogUpdate" }
|
versionCatalogUpdate = { id = "nl.littlerobots.version-catalog-update", version.ref = "versionCatalogUpdate" }
|
||||||
|
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
7
gradlew
vendored
7
gradlew
vendored
@@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -84,7 +86,8 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||||
|
' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
2
gradlew.bat
vendored
2
gradlew.bat
vendored
@@ -13,6 +13,8 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
1277
package-lock.json
generated
1277
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,10 +13,10 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-node-resolve": "^15.2.1",
|
"@rollup/plugin-node-resolve": "^15.2.1",
|
||||||
"@rollup/plugin-typescript": "^11.0.0",
|
"@rollup/plugin-typescript": "^12.0.0",
|
||||||
"@rollup/plugin-url": "^8.0.1",
|
"@rollup/plugin-url": "^8.0.1",
|
||||||
"@swc/core": "^1.3.92",
|
"@swc/core": "^1.3.92",
|
||||||
"@types/node": "^20.8.3",
|
"@types/node": "^22.0.0",
|
||||||
"lightningcss": "^1.22.0",
|
"lightningcss": "^1.22.0",
|
||||||
"preact-render-to-string": "^6.2.1",
|
"preact-render-to-string": "^6.2.1",
|
||||||
"rehype": "^13.0.0",
|
"rehype": "^13.0.0",
|
||||||
|
@@ -8,6 +8,8 @@ plugins {
|
|||||||
id("cc-tweaked.vanilla")
|
id("cc-tweaked.vanilla")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val mcVersion: String by extra
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
}
|
}
|
||||||
@@ -17,13 +19,26 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.javadoc {
|
tasks.javadoc {
|
||||||
|
title = "CC: Tweaked $version Minecraft $mcVersion"
|
||||||
include("dan200/computercraft/api/**/*.java")
|
include("dan200/computercraft/api/**/*.java")
|
||||||
|
|
||||||
// Include the core-api in our javadoc export. This is wrong, but it means we can export a single javadoc dump.
|
|
||||||
source(project(":core-api").sourceSets.main.map { it.allJava })
|
|
||||||
|
|
||||||
options {
|
options {
|
||||||
this as StandardJavadocDocletOptions
|
(this as StandardJavadocDocletOptions)
|
||||||
|
|
||||||
|
groups = mapOf(
|
||||||
|
"Common" to listOf(
|
||||||
|
"dan200.computercraft.api",
|
||||||
|
"dan200.computercraft.api.lua",
|
||||||
|
"dan200.computercraft.api.peripheral",
|
||||||
|
),
|
||||||
|
"Upgrades" to listOf(
|
||||||
|
"dan200.computercraft.api.client.turtle",
|
||||||
|
"dan200.computercraft.api.pocket",
|
||||||
|
"dan200.computercraft.api.turtle",
|
||||||
|
"dan200.computercraft.api.upgrades",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
addBooleanOption("-allow-script-in-comments", true)
|
addBooleanOption("-allow-script-in-comments", true)
|
||||||
bottom(
|
bottom(
|
||||||
"""
|
"""
|
||||||
@@ -33,4 +48,7 @@ tasks.javadoc {
|
|||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Include the core-api in our javadoc export. This is wrong, but it means we can export a single javadoc dump.
|
||||||
|
source(project(":core-api").sourceSets.main.map { it.allJava })
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,43 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
|
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public API for client-only code.
|
||||||
|
*
|
||||||
|
* @see dan200.computercraft.api.ComputerCraftAPI The main API
|
||||||
|
*/
|
||||||
|
public final class ComputerCraftAPIClient {
|
||||||
|
private ComputerCraftAPIClient() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
||||||
|
* <p>
|
||||||
|
* This may be called at any point after registry creation, though it is recommended to call it within your client
|
||||||
|
* setup step.
|
||||||
|
*
|
||||||
|
* @param serialiser The turtle upgrade serialiser.
|
||||||
|
* @param modeller The upgrade modeller.
|
||||||
|
* @param <T> The type of the turtle upgrade.
|
||||||
|
* @deprecated This method can lead to confusing load behaviour on Forge. Use
|
||||||
|
* {@code dan200.computercraft.api.client.FabricComputerCraftAPIClient#registerTurtleUpgradeModeller} on Fabric, or
|
||||||
|
* {@code dan200.computercraft.api.client.turtle.RegisterTurtleModellersEvent} on Forge.
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
|
public static <T extends ITurtleUpgrade> void registerTurtleUpgradeModeller(TurtleUpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller) {
|
||||||
|
// TODO(1.20.4): Remove this
|
||||||
|
getInstance().registerTurtleUpgradeModeller(serialiser, modeller);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ComputerCraftAPIClientService getInstance() {
|
||||||
|
return ComputerCraftAPIClientService.get();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,84 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.api.client;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
|
||||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
|
||||||
import net.minecraft.client.resources.model.ModelManager;
|
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The location of a model to load. This may either be:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>A {@link ModelResourceLocation}, referencing an already baked model (such as {@code minecraft:dirt#inventory}).</li>
|
|
||||||
* <li>
|
|
||||||
* A {@link ResourceLocation}, referencing a path to a model resource (such as {@code minecraft:item/dirt}.
|
|
||||||
* These models will be baked and stored in the {@link ModelManager} in a loader-specific way.
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
*/
|
|
||||||
public final class ModelLocation {
|
|
||||||
/**
|
|
||||||
* The location of the model.
|
|
||||||
* <p>
|
|
||||||
* When {@link #resourceLocation} is null, this is the location of the model to load. When {@link #resourceLocation}
|
|
||||||
* is non-null, this is the "standalone" variant of the model resource — this is used by NeoForge's implementation
|
|
||||||
* of {@link ClientPlatformHelper#getModel(ModelManager, ModelResourceLocation, ResourceLocation)} to fetch the
|
|
||||||
* model from the model manger. It is not used on Fabric.
|
|
||||||
*/
|
|
||||||
private final ModelResourceLocation modelLocation;
|
|
||||||
private final @Nullable ResourceLocation resourceLocation;
|
|
||||||
|
|
||||||
private ModelLocation(ModelResourceLocation modelLocation, @Nullable ResourceLocation resourceLocation) {
|
|
||||||
this.modelLocation = modelLocation;
|
|
||||||
this.resourceLocation = resourceLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link ModelLocation} from model in the model manager.
|
|
||||||
*
|
|
||||||
* @param location The name of the model to load.
|
|
||||||
* @return The new {@link ModelLocation} instance.
|
|
||||||
*/
|
|
||||||
public static ModelLocation ofModel(ModelResourceLocation location) {
|
|
||||||
return new ModelLocation(location, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link ModelLocation} from a resource.
|
|
||||||
*
|
|
||||||
* @param location The location of the model resource, such as {@code minecraft:item/dirt}.
|
|
||||||
* @return The new {@link ModelLocation} instance.
|
|
||||||
*/
|
|
||||||
public static ModelLocation ofResource(ResourceLocation location) {
|
|
||||||
return new ModelLocation(new ModelResourceLocation(location, "standalone"), location);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get this model from the provided model manager.
|
|
||||||
*
|
|
||||||
* @param manager The model manger.
|
|
||||||
* @return This model, or the missing model if it could not be found.
|
|
||||||
*/
|
|
||||||
public BakedModel getModel(ModelManager manager) {
|
|
||||||
return ClientPlatformHelper.get().getModel(manager, modelLocation, resourceLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the models this model location depends on.
|
|
||||||
*
|
|
||||||
* @return A list of models that this model location depends on.
|
|
||||||
* @see TurtleUpgradeModeller#getDependencies()
|
|
||||||
*/
|
|
||||||
public Stream<ResourceLocation> getDependencies() {
|
|
||||||
return resourceLocation == null ? Stream.empty() : Stream.of(resourceLocation);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -13,47 +13,30 @@ import net.minecraft.client.resources.model.ModelResourceLocation;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A model to render, combined with a transformation matrix to apply.
|
* A model to render, combined with a transformation matrix to apply.
|
||||||
*
|
|
||||||
* @param model The model.
|
|
||||||
* @param matrix The transformation matrix.
|
|
||||||
*/
|
*/
|
||||||
public record TransformedModel(BakedModel model, Transformation matrix) {
|
public final class TransformedModel {
|
||||||
|
private final BakedModel model;
|
||||||
|
private final Transformation matrix;
|
||||||
|
|
||||||
|
public TransformedModel(BakedModel model, Transformation matrix) {
|
||||||
|
this.model = Objects.requireNonNull(model);
|
||||||
|
this.matrix = Objects.requireNonNull(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
public TransformedModel(BakedModel model) {
|
public TransformedModel(BakedModel model) {
|
||||||
this(model, Transformation.identity());
|
this.model = Objects.requireNonNull(model);
|
||||||
|
matrix = Transformation.identity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
|
||||||
*
|
|
||||||
* @param location The location of the model to load.
|
|
||||||
* @return The new {@link TransformedModel} instance.
|
|
||||||
*/
|
|
||||||
public static TransformedModel of(ModelLocation location) {
|
|
||||||
var modelManager = Minecraft.getInstance().getModelManager();
|
|
||||||
return new TransformedModel(location.getModel(modelManager));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
|
||||||
*
|
|
||||||
* @param location The location of the model to load.
|
|
||||||
* @return The new {@link TransformedModel} instance.
|
|
||||||
* @see ModelLocation#ofModel(ModelResourceLocation)
|
|
||||||
*/
|
|
||||||
public static TransformedModel of(ModelResourceLocation location) {
|
public static TransformedModel of(ModelResourceLocation location) {
|
||||||
var modelManager = Minecraft.getInstance().getModelManager();
|
var modelManager = Minecraft.getInstance().getModelManager();
|
||||||
return new TransformedModel(modelManager.getModel(location));
|
return new TransformedModel(modelManager.getModel(location));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
|
||||||
*
|
|
||||||
* @param location The location of the model to load.
|
|
||||||
* @return The new {@link TransformedModel} instance.
|
|
||||||
* @see ModelLocation#ofResource(ResourceLocation)
|
|
||||||
*/
|
|
||||||
public static TransformedModel of(ResourceLocation location) {
|
public static TransformedModel of(ResourceLocation location) {
|
||||||
var modelManager = Minecraft.getInstance().getModelManager();
|
var modelManager = Minecraft.getInstance().getModelManager();
|
||||||
return new TransformedModel(ClientPlatformHelper.get().getModel(modelManager, location));
|
return new TransformedModel(ClientPlatformHelper.get().getModel(modelManager, location));
|
||||||
@@ -63,4 +46,12 @@ public record TransformedModel(BakedModel model, Transformation matrix) {
|
|||||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item);
|
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item);
|
||||||
return new TransformedModel(model, transform);
|
return new TransformedModel(model, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BakedModel getModel() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transformation getMatrix() {
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
package dan200.computercraft.api.client.turtle;
|
package dan200.computercraft.api.client.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeType;
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A functional interface to register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
* A functional interface to register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
||||||
@@ -18,9 +18,9 @@ public interface RegisterTurtleUpgradeModeller {
|
|||||||
/**
|
/**
|
||||||
* Register a {@link TurtleUpgradeModeller}.
|
* Register a {@link TurtleUpgradeModeller}.
|
||||||
*
|
*
|
||||||
* @param type The turtle upgrade type.
|
* @param serialiser The turtle upgrade serialiser.
|
||||||
* @param modeller The upgrade modeller.
|
* @param modeller The upgrade modeller.
|
||||||
* @param <T> The type of the turtle upgrade.
|
* @param <T> The type of the turtle upgrade.
|
||||||
*/
|
*/
|
||||||
<T extends ITurtleUpgrade> void register(UpgradeType<T> type, TurtleUpgradeModeller<T> modeller);
|
<T extends ITurtleUpgrade> void register(TurtleUpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller);
|
||||||
}
|
}
|
||||||
|
@@ -4,17 +4,18 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.client.turtle;
|
package dan200.computercraft.api.client.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.api.client.ModelLocation;
|
|
||||||
import dan200.computercraft.api.client.TransformedModel;
|
import dan200.computercraft.api.client.TransformedModel;
|
||||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
import net.minecraft.client.resources.model.UnbakedModel;
|
import net.minecraft.client.resources.model.UnbakedModel;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.stream.Stream;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides models for a {@link ITurtleUpgrade}.
|
* Provides models for a {@link ITurtleUpgrade}.
|
||||||
@@ -30,32 +31,47 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
|||||||
/**
|
/**
|
||||||
* Obtain the model to be used when rendering a turtle peripheral.
|
* Obtain the model to be used when rendering a turtle peripheral.
|
||||||
* <p>
|
* <p>
|
||||||
* When the current turtle is {@literal null}, this function should be constant for a given upgrade, side and data.
|
* When the current turtle is {@literal null}, this function should be constant for a given upgrade and side.
|
||||||
*
|
*
|
||||||
* @param upgrade The upgrade that you're getting the model for.
|
* @param upgrade The upgrade that you're getting the model for.
|
||||||
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models.
|
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models, unless
|
||||||
|
* {@link #getModel(ITurtleUpgrade, CompoundTag, TurtleSide)} is overriden.
|
||||||
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
||||||
* @param data Upgrade data instance for current turtle side.
|
|
||||||
* @return The model that you wish to be used to render your upgrade.
|
* @return The model that you wish to be used to render your upgrade.
|
||||||
*/
|
*/
|
||||||
TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data);
|
TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the models that this turtle modeller depends on.
|
* Obtain the model to be used when rendering a turtle peripheral.
|
||||||
* <p>
|
* <p>
|
||||||
* Models included in this stream will be loaded and baked alongside item and block models, and so may be referenced
|
* This is used when rendering the turtle's item model, and so no {@link ITurtleAccess} is available.
|
||||||
|
*
|
||||||
|
* @param upgrade The upgrade that you're getting the model for.
|
||||||
|
* @param data Upgrade data instance for current turtle side.
|
||||||
|
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
||||||
|
* @return The model that you wish to be used to render your upgrade.
|
||||||
|
*/
|
||||||
|
default TransformedModel getModel(T upgrade, CompoundTag data, TurtleSide side) {
|
||||||
|
return getModel(upgrade, (ITurtleAccess) null, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of models that this turtle modeller depends on.
|
||||||
|
* <p>
|
||||||
|
* Models included in this list will be loaded and baked alongside item and block models, and so may be referenced
|
||||||
* by {@link TransformedModel#of(ResourceLocation)}. You do not need to override this method if you will load models
|
* by {@link TransformedModel#of(ResourceLocation)}. You do not need to override this method if you will load models
|
||||||
* by other means.
|
* by other means.
|
||||||
*
|
*
|
||||||
* @return A list of models that this modeller depends on.
|
* @return A list of models that this modeller depends on.
|
||||||
* @see UnbakedModel#getDependencies()
|
* @see UnbakedModel#getDependencies()
|
||||||
*/
|
*/
|
||||||
default Stream<ResourceLocation> getDependencies() {
|
default Collection<ResourceLocation> getDependencies() {
|
||||||
return Stream.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic {@link TurtleUpgradeModeller} which renders using the upgrade's {@linkplain ITurtleUpgrade#getUpgradeItem(DataComponentPatch)}
|
* A basic {@link TurtleUpgradeModeller} which renders using the upgrade's {@linkplain ITurtleUpgrade#getUpgradeItem(CompoundTag)}
|
||||||
* upgrade item}.
|
* upgrade item}.
|
||||||
* <p>
|
* <p>
|
||||||
* This uses appropriate transformations for "flat" items, namely those extending the {@literal minecraft:item/generated}
|
* This uses appropriate transformations for "flat" items, namely those extending the {@literal minecraft:item/generated}
|
||||||
@@ -77,8 +93,9 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
|||||||
* @param <T> The type of the turtle upgrade.
|
* @param <T> The type of the turtle upgrade.
|
||||||
* @return The constructed modeller.
|
* @return The constructed modeller.
|
||||||
*/
|
*/
|
||||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ModelResourceLocation left, ModelResourceLocation right) {
|
||||||
return sided(ModelLocation.ofResource(left), ModelLocation.ofResource(right));
|
// TODO(1.21.0): Remove this.
|
||||||
|
return sided((ResourceLocation) left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,16 +106,16 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
|||||||
* @param <T> The type of the turtle upgrade.
|
* @param <T> The type of the turtle upgrade.
|
||||||
* @return The constructed modeller.
|
* @return The constructed modeller.
|
||||||
*/
|
*/
|
||||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ModelLocation left, ModelLocation right) {
|
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
||||||
return new TurtleUpgradeModeller<>() {
|
return new TurtleUpgradeModeller<>() {
|
||||||
@Override
|
@Override
|
||||||
public TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data) {
|
public TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
||||||
return TransformedModel.of(side == TurtleSide.LEFT ? left : right);
|
return TransformedModel.of(side == TurtleSide.LEFT ? left : right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<ResourceLocation> getDependencies() {
|
public Collection<ResourceLocation> getDependencies() {
|
||||||
return Stream.of(left, right).flatMap(ModelLocation::getDependencies);
|
return List.of(left, right);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,8 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
|||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -36,8 +37,16 @@ final class TurtleUpgradeModellers {
|
|||||||
|
|
||||||
private static final 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, DataComponentPatch data) {
|
public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
||||||
var stack = upgrade.getUpgradeItem(data);
|
return getModel(turtle == null ? upgrade.getCraftingItem() : upgrade.getUpgradeItem(turtle.getUpgradeNBTData(side)), side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransformedModel getModel(ITurtleUpgrade upgrade, CompoundTag data, TurtleSide side) {
|
||||||
|
return getModel(upgrade.getUpgradeItem(data), side);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransformedModel getModel(ItemStack stack, TurtleSide side) {
|
||||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack);
|
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack);
|
||||||
if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model);
|
if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model);
|
||||||
return new TransformedModel(model, side == TurtleSide.LEFT ? leftTransform : rightTransform);
|
return new TransformedModel(model, side == TurtleSide.LEFT ? leftTransform : rightTransform);
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.impl.client;
|
package dan200.computercraft.impl.client;
|
||||||
|
|
||||||
import dan200.computercraft.api.client.ModelLocation;
|
|
||||||
import dan200.computercraft.impl.Services;
|
import dan200.computercraft.impl.Services;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
@@ -18,28 +17,13 @@ import javax.annotation.Nullable;
|
|||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public interface ClientPlatformHelper {
|
public interface ClientPlatformHelper {
|
||||||
/**
|
/**
|
||||||
* Get a model from a resource.
|
* Equivalent to {@link ModelManager#getModel(ModelResourceLocation)} but for arbitrary {@link ResourceLocation}s.
|
||||||
*
|
*
|
||||||
* @param manager The model manager.
|
* @param manager The model manager.
|
||||||
* @param resourceLocation The model resourceLocation.
|
* @param location The model location.
|
||||||
* @return The baked model.
|
* @return The baked model.
|
||||||
* @see ModelLocation
|
|
||||||
*/
|
*/
|
||||||
BakedModel getModel(ModelManager manager, ResourceLocation resourceLocation);
|
BakedModel getModel(ModelManager manager, ResourceLocation location);
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a model from a {@link ModelResourceLocation} or {@link ResourceLocation}.
|
|
||||||
* <p>
|
|
||||||
* This is largely equivalent to {@code resourceLocation == null ? manager.getModel(modelLocation) : getModel(manager, resourceLocation)},
|
|
||||||
* but allows pre-computing {@code modelLocation} (if needed).
|
|
||||||
*
|
|
||||||
* @param manager The model manager.
|
|
||||||
* @param modelLocation The location of the model to load.
|
|
||||||
* @param resourceLocation The location of the resource, if trying to load from a resource.
|
|
||||||
* @return The baked model.
|
|
||||||
* @see ModelLocation
|
|
||||||
*/
|
|
||||||
BakedModel getModel(ModelManager manager, ModelResourceLocation modelLocation, @Nullable ResourceLocation resourceLocation);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap this model in a version which renders a foil/enchantment glint.
|
* Wrap this model in a version which renders a foil/enchantment glint.
|
||||||
|
@@ -4,34 +4,35 @@
|
|||||||
|
|
||||||
package dan200.computercraft.impl.client;
|
package dan200.computercraft.impl.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.client.ComputerCraftAPIClient;
|
||||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeType;
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
import dan200.computercraft.impl.Services;
|
import dan200.computercraft.impl.Services;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Backing interface for CC's client-side API.
|
* Backing interface for {@link ComputerCraftAPIClient}
|
||||||
* <p>
|
* <p>
|
||||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||||
*/
|
*/
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public interface FabricComputerCraftAPIClientService {
|
public interface ComputerCraftAPIClientService {
|
||||||
static FabricComputerCraftAPIClientService get() {
|
static ComputerCraftAPIClientService get() {
|
||||||
var instance = Instance.INSTANCE;
|
var instance = Instance.INSTANCE;
|
||||||
return instance == null ? Services.raise(FabricComputerCraftAPIClientService.class, Instance.ERROR) : instance;
|
return instance == null ? Services.raise(ComputerCraftAPIClientService.class, Instance.ERROR) : instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
<T extends ITurtleUpgrade> void registerTurtleUpgradeModeller(UpgradeType<T> type, TurtleUpgradeModeller<T> modeller);
|
<T extends ITurtleUpgrade> void registerTurtleUpgradeModeller(TurtleUpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller);
|
||||||
|
|
||||||
final class Instance {
|
final class Instance {
|
||||||
static final @Nullable FabricComputerCraftAPIClientService INSTANCE;
|
static final @Nullable ComputerCraftAPIClientService INSTANCE;
|
||||||
static final @Nullable Throwable ERROR;
|
static final @Nullable Throwable ERROR;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
var helper = Services.tryLoad(FabricComputerCraftAPIClientService.class);
|
var helper = Services.tryLoad(ComputerCraftAPIClientService.class);
|
||||||
INSTANCE = helper.instance();
|
INSTANCE = helper.instance();
|
||||||
ERROR = helper.error();
|
ERROR = helper.error();
|
||||||
}
|
}
|
@@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api;
|
package dan200.computercraft.api;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.component.ComputerComponent;
|
||||||
import dan200.computercraft.api.filesystem.Mount;
|
import dan200.computercraft.api.filesystem.Mount;
|
||||||
import dan200.computercraft.api.filesystem.WritableMount;
|
import dan200.computercraft.api.filesystem.WritableMount;
|
||||||
import dan200.computercraft.api.lua.GenericSource;
|
import dan200.computercraft.api.lua.GenericSource;
|
||||||
|
import dan200.computercraft.api.lua.IComputerSystem;
|
||||||
import dan200.computercraft.api.lua.ILuaAPI;
|
import dan200.computercraft.api.lua.ILuaAPI;
|
||||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||||
import dan200.computercraft.api.media.IMedia;
|
import dan200.computercraft.api.media.IMedia;
|
||||||
@@ -165,7 +167,20 @@ public final class ComputerCraftAPI {
|
|||||||
* Register a custom {@link ILuaAPI}, which may be added onto all computers without requiring a peripheral.
|
* Register a custom {@link ILuaAPI}, which may be added onto all computers without requiring a peripheral.
|
||||||
* <p>
|
* <p>
|
||||||
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
|
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
|
||||||
* to use peripherals to provide functionality to users.
|
* to use peripherals to provide functionality to users. If an API is <em>required</em>, you may want to consider
|
||||||
|
* using {@link ILuaAPI#getModuleName()} to expose this library as a module instead of as a global.
|
||||||
|
* <p>
|
||||||
|
* This may be used with {@link IComputerSystem#getComponent(ComputerComponent)} to only attach APIs to specific
|
||||||
|
* computers. For example, one can add an additional API just to turtles with the following code:
|
||||||
|
*
|
||||||
|
* <pre class="language language-java">{@code
|
||||||
|
* ComputerCraftAPI.registerAPIFactory(computer -> {
|
||||||
|
* // Read the turtle component.
|
||||||
|
* var turtle = computer.getComponent(ComputerComponents.TURTLE);
|
||||||
|
* // If present then add our API.
|
||||||
|
* return turtle == null ? null : new MyCustomTurtleApi(turtle);
|
||||||
|
* });
|
||||||
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @param factory The factory for your API subclass.
|
* @param factory The factory for your API subclass.
|
||||||
* @see ILuaAPIFactory
|
* @see ILuaAPIFactory
|
||||||
|
@@ -6,12 +6,10 @@ package dan200.computercraft.api;
|
|||||||
|
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.ItemTags;
|
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.item.context.UseOnContext;
|
import net.minecraft.world.item.context.UseOnContext;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
@@ -37,16 +35,8 @@ public class ComputerCraftTags {
|
|||||||
*/
|
*/
|
||||||
public static final TagKey<Item> TURTLE_CAN_PLACE = make("turtle_can_place");
|
public static final TagKey<Item> TURTLE_CAN_PLACE = make("turtle_can_place");
|
||||||
|
|
||||||
/**
|
|
||||||
* Items which can be dyed.
|
|
||||||
* <p>
|
|
||||||
* This is similar to {@link ItemTags#DYEABLE}, but allows cleaning the item with a sponge, rather than in a
|
|
||||||
* cauldron.
|
|
||||||
*/
|
|
||||||
public static final TagKey<Item> DYEABLE = make("dyeable");
|
|
||||||
|
|
||||||
private static TagKey<Item> make(String name) {
|
private static TagKey<Item> make(String name) {
|
||||||
return TagKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name));
|
return TagKey.create(Registries.ITEM, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,13 +75,13 @@ public class ComputerCraftTags {
|
|||||||
public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable");
|
public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block which can be {@linkplain BlockState#useItemOn(ItemStack, Level, Player, InteractionHand, BlockHitResult) used}
|
* Block which can be {@linkplain BlockState#use(Level, Player, InteractionHand, BlockHitResult) used} when
|
||||||
* when calling {@code turtle.place()}.
|
* calling {@code turtle.place()}.
|
||||||
*/
|
*/
|
||||||
public static final TagKey<Block> TURTLE_CAN_USE = make("turtle_can_use");
|
public static final TagKey<Block> TURTLE_CAN_USE = make("turtle_can_use");
|
||||||
|
|
||||||
private static TagKey<Block> make(String name) {
|
private static TagKey<Block> make(String name) {
|
||||||
return TagKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name));
|
return TagKey.create(Registries.BLOCK, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,24 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.component;
|
||||||
|
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A computer which has permission to perform administrative/op commands, such as the command computer.
|
||||||
|
*/
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface AdminComputer {
|
||||||
|
/**
|
||||||
|
* The permission level that this computer can operate at.
|
||||||
|
*
|
||||||
|
* @return The permission level for this computer.
|
||||||
|
* @see CommandSourceStack#hasPermission(int)
|
||||||
|
*/
|
||||||
|
default int permissionLevel() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.component;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.IComputerSystem;
|
||||||
|
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A component attached to a computer.
|
||||||
|
* <p>
|
||||||
|
* Components provide a mechanism to attach additional data to a computer, that can then be queried with
|
||||||
|
* {@link IComputerSystem#getComponent(ComputerComponent)}.
|
||||||
|
* <p>
|
||||||
|
* This is largely designed for {@linkplain ILuaAPIFactory custom APIs}, allowing APIs to read additional properties
|
||||||
|
* of the computer, such as its position.
|
||||||
|
*
|
||||||
|
* @param <T> The type of this component.
|
||||||
|
* @see ComputerComponents The built-in components.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("UnusedTypeParameter")
|
||||||
|
public final class ComputerComponent<T> {
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
private ComputerComponent(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new computer component.
|
||||||
|
* <p>
|
||||||
|
* Mods typically will not need to create their own components.
|
||||||
|
*
|
||||||
|
* @param namespace The namespace of this component. This should be the mod id.
|
||||||
|
* @param id The unique id of this component.
|
||||||
|
* @param <T> The component
|
||||||
|
* @return The newly created component.
|
||||||
|
*/
|
||||||
|
public static <T> ComputerComponent<T> create(String namespace, String id) {
|
||||||
|
return new ComputerComponent<>(namespace + ":" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ComputerComponent(" + id + ")";
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.component;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ComputerComponent}s provided by ComputerCraft.
|
||||||
|
*/
|
||||||
|
public class ComputerComponents {
|
||||||
|
/**
|
||||||
|
* The {@link ITurtleAccess} associated with a turtle.
|
||||||
|
*/
|
||||||
|
public static final ComputerComponent<ITurtleAccess> TURTLE = ComputerComponent.create(ComputerCraftAPI.MOD_ID, "turtle");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link IPocketAccess} associated with a pocket computer.
|
||||||
|
*/
|
||||||
|
public static final ComputerComponent<IPocketAccess> POCKET = ComputerComponent.create(ComputerCraftAPI.MOD_ID, "pocket");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component is only present on "command computers", and other computers with admin capabilities.
|
||||||
|
*/
|
||||||
|
public static final ComputerComponent<AdminComputer> ADMIN_COMPUTER = ComputerComponent.create(ComputerCraftAPI.MOD_ID, "admin_computer");
|
||||||
|
}
|
@@ -13,7 +13,7 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An item detail provider for {@link ItemStack}'s whose {@link Item} has a specific type.
|
* An item detail provider for {@link ItemStack}s whose {@link Item} has a specific type.
|
||||||
*
|
*
|
||||||
* @param <T> The type the stack's item must have.
|
* @param <T> The type the stack's item must have.
|
||||||
*/
|
*/
|
||||||
@@ -22,7 +22,7 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
|
|||||||
private final @Nullable String namespace;
|
private final @Nullable String namespace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new item detail provider. Meta will be inserted into a new sub-map named as per {@code namespace}.
|
* Create a new item detail provider. Details will be inserted into a new sub-map named as per {@code namespace}.
|
||||||
*
|
*
|
||||||
* @param itemType The type the stack's item must have.
|
* @param itemType The type the stack's item must have.
|
||||||
* @param namespace The namespace to use for this provider.
|
* @param namespace The namespace to use for this provider.
|
||||||
@@ -34,7 +34,7 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new item detail provider. Meta will be inserted directly into the results.
|
* Create a new item detail provider. Details will be inserted directly into the results.
|
||||||
*
|
*
|
||||||
* @param itemType The type the stack's item must have.
|
* @param itemType The type the stack's item must have.
|
||||||
*/
|
*/
|
||||||
@@ -53,21 +53,18 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
|
|||||||
* @param stack The item stack to provide details for.
|
* @param stack The item stack to provide details for.
|
||||||
* @param item The item to provide details for.
|
* @param item The item to provide details for.
|
||||||
*/
|
*/
|
||||||
public abstract void provideDetails(
|
public abstract void provideDetails(Map<? super String, Object> data, ItemStack stack, T item);
|
||||||
Map<? super String, Object> data, ItemStack stack, T item
|
|
||||||
);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void provideDetails(Map<? super String, Object> data, ItemStack stack) {
|
public final void provideDetails(Map<? super String, Object> data, ItemStack stack) {
|
||||||
var item = stack.getItem();
|
var item = stack.getItem();
|
||||||
if (!itemType.isInstance(item)) return;
|
if (!itemType.isInstance(item)) return;
|
||||||
|
|
||||||
// If `namespace` is specified, insert into a new data map instead of the existing one.
|
if (namespace == null) {
|
||||||
Map<? super String, Object> child = namespace == null ? data : new HashMap<>();
|
provideDetails(data, stack, itemType.cast(item));
|
||||||
|
} else {
|
||||||
provideDetails(child, stack, itemType.cast(item));
|
Map<? super String, Object> child = new HashMap<>();
|
||||||
|
provideDetails(child, stack, itemType.cast(item));
|
||||||
if (namespace != null) {
|
|
||||||
data.put(namespace, child);
|
data.put(namespace, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ public interface DetailRegistry<T> {
|
|||||||
* @param provider The detail provider to register.
|
* @param provider The detail provider to register.
|
||||||
* @see DetailProvider
|
* @see DetailProvider
|
||||||
*/
|
*/
|
||||||
void addProvider(DetailProvider<T> provider);
|
void addProvider(DetailProvider<? super T> provider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute basic details about an object. This is cheaper than computing all details operation, and so is suitable
|
* Compute basic details about an object. This is cheaper than computing all details operation, and so is suitable
|
||||||
|
@@ -0,0 +1,59 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2017 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.component.ComputerComponent;
|
||||||
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface passed to {@link ILuaAPIFactory} in order to provide additional information
|
||||||
|
* about a computer.
|
||||||
|
*/
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface IComputerSystem extends IComputerAccess {
|
||||||
|
/**
|
||||||
|
* Get the level this computer is currently in.
|
||||||
|
* <p>
|
||||||
|
* This method is not guaranteed to remain the same (even for stationary computers).
|
||||||
|
*
|
||||||
|
* @return The computer's current level.
|
||||||
|
*/
|
||||||
|
ServerLevel getLevel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position this computer is currently at.
|
||||||
|
* <p>
|
||||||
|
* This method is not guaranteed to remain the same (even for stationary computers).
|
||||||
|
*
|
||||||
|
* @return The computer's current position.
|
||||||
|
*/
|
||||||
|
BlockPos getPosition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the label for this computer.
|
||||||
|
*
|
||||||
|
* @return This computer's label, or {@code null} if it is not set.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
String getLabel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a component attached to this computer.
|
||||||
|
* <p>
|
||||||
|
* No component is guaranteed to be on a computer, and so this method should always be guarded with a null check.
|
||||||
|
* <p>
|
||||||
|
* This method will always return the same value for a given component, and so may be cached.
|
||||||
|
*
|
||||||
|
* @param component The component to query.
|
||||||
|
* @param <T> The type of the component.
|
||||||
|
* @return The component, if present.
|
||||||
|
*/
|
||||||
|
<T> @Nullable T getComponent(ComputerComponent<T> component);
|
||||||
|
}
|
@@ -4,13 +4,15 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an {@link ILuaAPI} for a specific computer.
|
* Construct an {@link ILuaAPI} for a computer.
|
||||||
*
|
*
|
||||||
* @see ILuaAPI
|
* @see ILuaAPI
|
||||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ILuaAPIFactory {
|
public interface ILuaAPIFactory {
|
@@ -7,13 +7,11 @@ package dan200.computercraft.api.media;
|
|||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.filesystem.Mount;
|
import dan200.computercraft.api.filesystem.Mount;
|
||||||
import dan200.computercraft.api.filesystem.WritableMount;
|
import dan200.computercraft.api.filesystem.WritableMount;
|
||||||
import net.minecraft.core.Holder;
|
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.sounds.SoundEvent;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.JukeboxSong;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@@ -27,12 +25,11 @@ public interface IMedia {
|
|||||||
/**
|
/**
|
||||||
* Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua.
|
* Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua.
|
||||||
*
|
*
|
||||||
* @param registries The currently loaded registries.
|
* @param stack The {@link ItemStack} to inspect.
|
||||||
* @param stack The {@link ItemStack} to inspect.
|
|
||||||
* @return The label. ie: "Dan's Programs".
|
* @return The label. ie: "Dan's Programs".
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
String getLabel(HolderLookup.Provider registries, ItemStack stack);
|
String getLabel(ItemStack stack);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua.
|
* Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua.
|
||||||
@@ -46,15 +43,26 @@ public interface IMedia {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this disk represents an item with audio (like a record), get the corresponding {@link JukeboxSong}.
|
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie:
|
||||||
|
* "Jonathan Coulton - Still Alive"
|
||||||
*
|
*
|
||||||
* @param registries The currently loaded registries.
|
* @param stack The {@link ItemStack} to modify.
|
||||||
* @param stack The {@link ItemStack} to query.
|
* @return The name, or null if this item does not represent an item with audio.
|
||||||
* @return The song, or null if this item does not represent an item with audio.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
default Holder<JukeboxSong> getAudio(HolderLookup.Provider registries, ItemStack stack) {
|
default String getAudioTitle(ItemStack stack) {
|
||||||
return JukeboxSong.fromStack(registries, stack).orElse(null);
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this disk represents an item with audio (like a record), get the resource name of the audio track to play.
|
||||||
|
*
|
||||||
|
* @param stack The {@link ItemStack} to modify.
|
||||||
|
* @return The name, or null if this item does not represent an item with audio.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default SoundEvent getAudio(ItemStack stack) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -14,7 +14,7 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
|||||||
* as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant
|
* as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant
|
||||||
* for its lifespan.
|
* for its lifespan.
|
||||||
* <p>
|
* <p>
|
||||||
* Elements are generally tied to a block or tile entity in world. In such as case, one should provide the
|
* Elements are generally tied to a block or block entity in world. In such as case, one should provide the
|
||||||
* {@link WiredElement} capability for the appropriate sides.
|
* {@link WiredElement} capability for the appropriate sides.
|
||||||
*/
|
*/
|
||||||
public interface WiredElement extends WiredSender {
|
public interface WiredElement extends WiredSender {
|
||||||
|
@@ -0,0 +1,92 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2018 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.network.wired;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wired network is composed of one of more {@link WiredNode}s, a set of connections between them, and a series
|
||||||
|
* of peripherals.
|
||||||
|
* <p>
|
||||||
|
* Networks from a connected graph. This means there is some path between all nodes on the network. Further more, if
|
||||||
|
* there is some path between two nodes then they must be on the same network. {@link WiredNetwork} will automatically
|
||||||
|
* handle the merging and splitting of networks (and thus changing of available nodes and peripherals) as connections
|
||||||
|
* change.
|
||||||
|
* <p>
|
||||||
|
* This does mean one can not rely on the network remaining consistent between subsequent operations. Consequently,
|
||||||
|
* it is generally preferred to use the methods provided by {@link WiredNode}.
|
||||||
|
*
|
||||||
|
* @see WiredNode#getNetwork()
|
||||||
|
*/
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface WiredNetwork {
|
||||||
|
/**
|
||||||
|
* Create a connection between two nodes.
|
||||||
|
* <p>
|
||||||
|
* This should only be used on the server thread.
|
||||||
|
*
|
||||||
|
* @param left The first node to connect
|
||||||
|
* @param right The second node to connect
|
||||||
|
* @return {@code true} if a connection was created or {@code false} if the connection already exists.
|
||||||
|
* @throws IllegalStateException If neither node is on the network.
|
||||||
|
* @throws IllegalArgumentException If {@code left} and {@code right} are equal.
|
||||||
|
* @see WiredNode#connectTo(WiredNode)
|
||||||
|
* @see WiredNetwork#connect(WiredNode, WiredNode)
|
||||||
|
* @deprecated Use {@link WiredNode#connectTo(WiredNode)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
boolean connect(WiredNode left, WiredNode right);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a connection between this node and another.
|
||||||
|
* <p>
|
||||||
|
* This should only be used on the server thread.
|
||||||
|
*
|
||||||
|
* @param left The first node in the connection.
|
||||||
|
* @param right The second node in the connection.
|
||||||
|
* @return {@code true} if a connection was destroyed or {@code false} if no connection exists.
|
||||||
|
* @throws IllegalArgumentException If either node is not on the network.
|
||||||
|
* @throws IllegalArgumentException If {@code left} and {@code right} are equal.
|
||||||
|
* @see WiredNode#disconnectFrom(WiredNode)
|
||||||
|
* @see WiredNetwork#connect(WiredNode, WiredNode)
|
||||||
|
* @deprecated Use {@link WiredNode#disconnectFrom(WiredNode)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
boolean disconnect(WiredNode left, WiredNode right);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sever all connections this node has, removing it from this network.
|
||||||
|
* <p>
|
||||||
|
* This should only be used on the server thread. You should only call this on nodes
|
||||||
|
* that your network element owns.
|
||||||
|
*
|
||||||
|
* @param node The node to remove
|
||||||
|
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the
|
||||||
|
* only element.
|
||||||
|
* @throws IllegalArgumentException If the node is not in the network.
|
||||||
|
* @see WiredNode#remove()
|
||||||
|
* @deprecated Use {@link WiredNode#remove()}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
boolean remove(WiredNode node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the peripherals a node provides.
|
||||||
|
* <p>
|
||||||
|
* This should only be used on the server thread. You should only call this on nodes
|
||||||
|
* that your network element owns.
|
||||||
|
*
|
||||||
|
* @param node The node to attach peripherals for.
|
||||||
|
* @param peripherals The new peripherals for this node.
|
||||||
|
* @throws IllegalArgumentException If the node is not in the network.
|
||||||
|
* @see WiredNode#updatePeripherals(Map)
|
||||||
|
* @deprecated Use {@link WiredNode#updatePeripherals(Map)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
void updatePeripherals(WiredNode node, Map<String, IPeripheral> peripherals);
|
||||||
|
}
|
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.ApiStatus;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single node on a wired network.
|
* Wired nodes act as a layer between {@link WiredElement}s and {@link WiredNetwork}s.
|
||||||
* <p>
|
* <p>
|
||||||
* Firstly, a node acts as a packet network, capable of sending and receiving modem messages to connected nodes. These
|
* Firstly, a node acts as a packet network, capable of sending and receiving modem messages to connected nodes. These
|
||||||
* methods may be safely used on any thread.
|
* methods may be safely used on any thread.
|
||||||
@@ -32,6 +32,18 @@ public interface WiredNode extends PacketNetwork {
|
|||||||
*/
|
*/
|
||||||
WiredElement getElement();
|
WiredElement getElement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The network this node is currently connected to. Note that this may change
|
||||||
|
* after any network operation, so it should not be cached.
|
||||||
|
* <p>
|
||||||
|
* This should only be used on the server thread.
|
||||||
|
*
|
||||||
|
* @return This node's network.
|
||||||
|
* @deprecated Use the connect/disconnect/remove methods on {@link WiredNode}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
WiredNetwork getNetwork();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a connection from this node to another.
|
* Create a connection from this node to another.
|
||||||
* <p>
|
* <p>
|
||||||
|
@@ -8,12 +8,10 @@ import dan200.computercraft.api.network.PacketSender;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object on a wired network capable of sending packets.
|
* An object on a {@link WiredNetwork} capable of sending packets.
|
||||||
* <p>
|
* <p>
|
||||||
* Unlike a regular {@link PacketSender}, this must be associated with the node you are attempting to
|
* Unlike a regular {@link PacketSender}, this must be associated with the node you are attempting to
|
||||||
* to send the packet from.
|
* to send the packet from.
|
||||||
*
|
|
||||||
* @see WiredElement
|
|
||||||
*/
|
*/
|
||||||
public interface WiredSender extends PacketSender {
|
public interface WiredSender extends PacketSender {
|
||||||
/**
|
/**
|
||||||
|
@@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.pocket;
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
import net.minecraft.network.chat.Component;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
|
||||||
@@ -14,20 +15,27 @@ import net.minecraft.world.item.ItemStack;
|
|||||||
* One does not have to use this, but it does provide a convenient template.
|
* One does not have to use this, but it does provide a convenient template.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractPocketUpgrade implements IPocketUpgrade {
|
public abstract class AbstractPocketUpgrade implements IPocketUpgrade {
|
||||||
private final Component adjective;
|
private final ResourceLocation id;
|
||||||
|
private final String adjective;
|
||||||
private final ItemStack stack;
|
private final ItemStack stack;
|
||||||
|
|
||||||
protected AbstractPocketUpgrade(Component adjective, ItemStack stack) {
|
protected AbstractPocketUpgrade(ResourceLocation id, String adjective, ItemStack stack) {
|
||||||
|
this.id = id;
|
||||||
this.adjective = adjective;
|
this.adjective = adjective;
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractPocketUpgrade(String adjective, ItemStack stack) {
|
protected AbstractPocketUpgrade(ResourceLocation id, ItemStack stack) {
|
||||||
this(Component.translatable(adjective), stack);
|
this(id, UpgradeBase.getDefaultAdjective(id), stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Component getAdjective() {
|
public final ResourceLocation getUpgradeID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String getUnlocalisedAdjective() {
|
||||||
return adjective;
|
return adjective;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,17 +4,39 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.pocket;
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class for pocket computers.
|
* Wrapper class for pocket computers.
|
||||||
*/
|
*/
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
public interface IPocketAccess {
|
public interface IPocketAccess {
|
||||||
|
/**
|
||||||
|
* Get the level in which the pocket computer exists.
|
||||||
|
*
|
||||||
|
* @return The pocket computer's level.
|
||||||
|
*/
|
||||||
|
ServerLevel getLevel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position of the pocket computer.
|
||||||
|
*
|
||||||
|
* @return The pocket computer's position.
|
||||||
|
*/
|
||||||
|
Vec3 getPosition();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the entity holding this item.
|
* Gets the entity holding this item.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -61,25 +83,45 @@ public interface IPocketAccess {
|
|||||||
*/
|
*/
|
||||||
void setLight(int colour);
|
void setLight(int colour);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently equipped upgrade.
|
||||||
|
*
|
||||||
|
* @return The currently equipped upgrade.
|
||||||
|
* @see #getUpgradeNBTData()
|
||||||
|
* @see #setUpgrade(UpgradeData)
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
UpgradeData<IPocketUpgrade> getUpgrade();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the upgrade for this pocket computer, also updating the item stack.
|
||||||
|
* <p>
|
||||||
|
* Note this method is not thread safe - it must be called from the server thread.
|
||||||
|
*
|
||||||
|
* @param upgrade The new upgrade to set it to, may be {@code null}.
|
||||||
|
* @see #getUpgrade()
|
||||||
|
*/
|
||||||
|
void setUpgrade(@Nullable UpgradeData<IPocketUpgrade> upgrade);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the upgrade-specific NBT.
|
* Get the upgrade-specific NBT.
|
||||||
* <p>
|
* <p>
|
||||||
* This is persisted between computer reboots and chunk loads.
|
* This is persisted between computer reboots and chunk loads.
|
||||||
*
|
*
|
||||||
* @return The upgrade's NBT.
|
* @return The upgrade's NBT.
|
||||||
* @see #setUpgradeData(DataComponentPatch)
|
* @see #updateUpgradeNBTData()
|
||||||
* @see UpgradeBase#getUpgradeItem(DataComponentPatch)
|
* @see UpgradeBase#getUpgradeItem(CompoundTag)
|
||||||
* @see UpgradeBase#getUpgradeData(ItemStack)
|
* @see UpgradeBase#getUpgradeData(ItemStack)
|
||||||
|
* @see #getUpgrade()
|
||||||
*/
|
*/
|
||||||
DataComponentPatch getUpgradeData();
|
CompoundTag getUpgradeNBTData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the upgrade-specific data.
|
* Mark the upgrade-specific NBT as dirty.
|
||||||
*
|
*
|
||||||
* @param data The new upgrade data.
|
* @see #getUpgradeNBTData()
|
||||||
* @see #getUpgradeData()
|
|
||||||
*/
|
*/
|
||||||
void setUpgradeData(DataComponentPatch data);
|
void updateUpgradeNBTData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the current peripheral and create a new one.
|
* Remove the current peripheral and create a new one.
|
||||||
@@ -88,4 +130,13 @@ public interface IPocketAccess {
|
|||||||
* entity} changes.
|
* entity} changes.
|
||||||
*/
|
*/
|
||||||
void invalidatePeripheral();
|
void invalidatePeripheral();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of all upgrades for the pocket computer.
|
||||||
|
*
|
||||||
|
* @return A collection of all upgrade names.
|
||||||
|
* @deprecated This is a relic of a previous API, which no longer makes sense with newer versions of ComputerCraft.
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
|
Map<ResourceLocation, IPeripheral> getUpgrades();
|
||||||
}
|
}
|
||||||
|
@@ -4,14 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.pocket;
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeType;
|
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.resources.ResourceKey;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -19,54 +13,16 @@ import javax.annotation.Nullable;
|
|||||||
/**
|
/**
|
||||||
* A peripheral which can be equipped to the back side of a pocket computer.
|
* A peripheral which can be equipped to the back side of a pocket computer.
|
||||||
* <p>
|
* <p>
|
||||||
* Pocket upgrades are defined in two stages. First, one creates a {@link IPocketUpgrade} subclass and corresponding
|
* Pocket upgrades are defined in two stages. First, on creates a {@link IPocketUpgrade} subclass and corresponding
|
||||||
* {@link UpgradeType} instance, which are then registered in a registry.
|
* {@link PocketUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
||||||
* <p>
|
* <p>
|
||||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||||
* the upgrade automatically registered. It is recommended this is done via
|
* the upgrade registered internally. See the documentation in {@link PocketUpgradeSerialiser} for details on this process
|
||||||
* <a href="../upgrades/UpgradeType.html#datagen">data generators</a>.
|
* and where files should be located.
|
||||||
*
|
*
|
||||||
* <h2>Example</h2>
|
* @see PocketUpgradeSerialiser For how to register a pocket computer upgrade.
|
||||||
* {@snippet lang="java" :
|
|
||||||
* // We use Forge's DeferredRegister to register our upgrade type. Fabric mods may register their type directly.
|
|
||||||
* static final DeferredRegister<UpgradeType<? extends IPocketUpgrade>> POCKET_UPGRADES = DeferredRegister.create(IPocketUpgrade.typeRegistry(), "my_mod");
|
|
||||||
*
|
|
||||||
* // Register a new upgrade upgrade type called "my_upgrade".
|
|
||||||
* public static final RegistryObject<UpgradeType<MyUpgrade>> MY_UPGRADE =
|
|
||||||
* POCKET_UPGRADES.register("my_upgrade", () -> UpgradeType.simple(new MyUpgrade()));
|
|
||||||
*
|
|
||||||
* // Then in your constructor
|
|
||||||
* POCKET_UPGRADES.register(bus);
|
|
||||||
* }
|
|
||||||
* <p>
|
|
||||||
* We can then define a new upgrade using JSON by placing the following in
|
|
||||||
* {@code data/<my_mod>/computercraft/pocket_upgrade/<my_upgrade_id>.json}.
|
|
||||||
* {@snippet lang="json" :
|
|
||||||
* {
|
|
||||||
* "type": "my_mod:my_upgrade"
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
*/
|
||||||
public interface IPocketUpgrade extends UpgradeBase {
|
public interface IPocketUpgrade extends UpgradeBase {
|
||||||
ResourceKey<Registry<IPocketUpgrade>> REGISTRY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "pocket_upgrade"));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The registry key for pocket upgrade types.
|
|
||||||
*
|
|
||||||
* @return The registry key.
|
|
||||||
*/
|
|
||||||
static ResourceKey<Registry<UpgradeType<? extends IPocketUpgrade>>> typeRegistry() {
|
|
||||||
return ComputerCraftAPIService.get().pocketUpgradeRegistryId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the type of this upgrade.
|
|
||||||
*
|
|
||||||
* @return The type of this upgrade.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
UpgradeType<? extends IPocketUpgrade> getType();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a peripheral for the pocket computer.
|
* Creates a peripheral for the pocket computer.
|
||||||
* <p>
|
* <p>
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||||
|
import net.minecraft.data.DataGenerator;
|
||||||
|
import net.minecraft.data.PackOutput;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data provider to generate pocket computer upgrades.
|
||||||
|
* <p>
|
||||||
|
* This should be subclassed and registered to a {@link DataGenerator.PackGenerator}. Override the
|
||||||
|
* {@link #addUpgrades(Consumer)} function, construct each upgrade, and pass them off to the provided consumer to
|
||||||
|
* generate them.
|
||||||
|
*
|
||||||
|
* @see PocketUpgradeSerialiser
|
||||||
|
*/
|
||||||
|
public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider<IPocketUpgrade, PocketUpgradeSerialiser<?>> {
|
||||||
|
public PocketUpgradeDataProvider(PackOutput output) {
|
||||||
|
super(output, "Pocket Computer Upgrades", "computercraft/pocket_upgrades", PocketUpgradeSerialiser.registryId());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,79 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
|
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||||
|
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||||
|
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a {@link IPocketUpgrade} from disk and reads/writes it to a network packet.
|
||||||
|
* <p>
|
||||||
|
* This follows the same format as {@link dan200.computercraft.api.turtle.TurtleUpgradeSerialiser} - consult the
|
||||||
|
* documentation there for more information.
|
||||||
|
*
|
||||||
|
* @param <T> The type of pocket computer upgrade this is responsible for serialising.
|
||||||
|
* @see IPocketUpgrade
|
||||||
|
* @see PocketUpgradeDataProvider
|
||||||
|
*/
|
||||||
|
public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends UpgradeSerialiser<T> {
|
||||||
|
/**
|
||||||
|
* The ID for the associated registry.
|
||||||
|
*
|
||||||
|
* @return The registry key.
|
||||||
|
*/
|
||||||
|
static ResourceKey<Registry<PocketUpgradeSerialiser<?>>> registryId() {
|
||||||
|
return ComputerCraftAPIService.get().pocketUpgradeRegistryId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleCraftingRecipeSerializer},
|
||||||
|
* but for upgrades.
|
||||||
|
* <p>
|
||||||
|
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||||
|
*
|
||||||
|
* @param factory Generate a new upgrade with a specific ID.
|
||||||
|
* @param <T> The type of the generated upgrade.
|
||||||
|
* @return The serialiser for this upgrade
|
||||||
|
*/
|
||||||
|
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simple(Function<ResourceLocation, T> factory) {
|
||||||
|
final class Impl extends SimpleSerialiser<T> implements PocketUpgradeSerialiser<T> {
|
||||||
|
private Impl(Function<ResourceLocation, T> constructor) {
|
||||||
|
super(constructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Impl(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
||||||
|
*
|
||||||
|
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
||||||
|
* {@link UpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
||||||
|
* @param <T> The type of the generated upgrade.
|
||||||
|
* @return The serialiser for this upgrade.
|
||||||
|
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
||||||
|
*/
|
||||||
|
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simpleWithCustomItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||||
|
final class Impl extends SerialiserWithCraftingItem<T> implements PocketUpgradeSerialiser<T> {
|
||||||
|
private Impl(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||||
|
super(factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Impl(factory);
|
||||||
|
}
|
||||||
|
}
|
@@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.turtle;
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
import net.minecraft.network.chat.Component;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
|
||||||
@@ -14,27 +15,34 @@ import net.minecraft.world.item.ItemStack;
|
|||||||
* One does not have to use this, but it does provide a convenient template.
|
* One does not have to use this, but it does provide a convenient template.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade {
|
public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade {
|
||||||
|
private final ResourceLocation id;
|
||||||
private final TurtleUpgradeType type;
|
private final TurtleUpgradeType type;
|
||||||
private final Component adjective;
|
private final String adjective;
|
||||||
private final ItemStack stack;
|
private final ItemStack stack;
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade(TurtleUpgradeType type, Component adjective, ItemStack stack) {
|
protected AbstractTurtleUpgrade(ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack) {
|
||||||
|
this.id = id;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.adjective = adjective;
|
this.adjective = adjective;
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade(TurtleUpgradeType type, String adjective, ItemStack stack) {
|
protected AbstractTurtleUpgrade(ResourceLocation id, TurtleUpgradeType type, ItemStack stack) {
|
||||||
this(type, Component.translatable(adjective), stack);
|
this(id, type, UpgradeBase.getDefaultAdjective(id), stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Component getAdjective() {
|
public final ResourceLocation getUpgradeID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String getUnlocalisedAdjective() {
|
||||||
return adjective;
|
return adjective;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final TurtleUpgradeType getUpgradeType() {
|
public final TurtleUpgradeType getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ import dan200.computercraft.api.upgrades.UpgradeBase;
|
|||||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
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;
|
||||||
@@ -229,22 +229,37 @@ public interface ITurtleAccess {
|
|||||||
* @param side The side to get the upgrade from.
|
* @param side The side to get the upgrade from.
|
||||||
* @return The upgrade on the specified side of the turtle, if there is one.
|
* @return The upgrade on the specified side of the turtle, if there is one.
|
||||||
* @see #getUpgradeWithData(TurtleSide)
|
* @see #getUpgradeWithData(TurtleSide)
|
||||||
* @see #setUpgrade(TurtleSide, UpgradeData)
|
* @see #setUpgradeWithData(TurtleSide, UpgradeData)
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
ITurtleUpgrade getUpgrade(TurtleSide side);
|
ITurtleUpgrade getUpgrade(TurtleSide side);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the upgrade on the specified side of the turtle, along with its {@linkplain #getUpgradeData(TurtleSide)
|
* Returns the upgrade on the specified side of the turtle, along with its {@linkplain #getUpgradeNBTData(TurtleSide)
|
||||||
* update data}.
|
* update data}.
|
||||||
*
|
*
|
||||||
* @param side The side to get the upgrade from.
|
* @param side The side to get the upgrade from.
|
||||||
* @return The upgrade on the specified side of the turtle, along with its upgrade data, if there is one.
|
* @return The upgrade on the specified side of the turtle, along with its upgrade data, if there is one.
|
||||||
* @see #getUpgradeWithData(TurtleSide)
|
* @see #getUpgradeWithData(TurtleSide)
|
||||||
* @see #setUpgrade(TurtleSide, UpgradeData)
|
* @see #setUpgradeWithData(TurtleSide, UpgradeData)
|
||||||
*/
|
*/
|
||||||
@Nullable
|
default @Nullable UpgradeData<ITurtleUpgrade> getUpgradeWithData(TurtleSide side) {
|
||||||
UpgradeData<ITurtleUpgrade> getUpgradeWithData(TurtleSide side);
|
var upgrade = getUpgrade(side);
|
||||||
|
return upgrade == null ? null : UpgradeData.of(upgrade, getUpgradeNBTData(side));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the upgrade for a given side, resetting peripherals and clearing upgrade specific data.
|
||||||
|
*
|
||||||
|
* @param side The side to set the upgrade on.
|
||||||
|
* @param upgrade The upgrade to set, may be {@code null} to clear.
|
||||||
|
* @see #getUpgrade(TurtleSide)
|
||||||
|
* @deprecated Use {@link #setUpgradeWithData(TurtleSide, UpgradeData)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default void setUpgrade(TurtleSide side, @Nullable ITurtleUpgrade upgrade) {
|
||||||
|
setUpgradeWithData(side, upgrade == null ? null : UpgradeData.ofDefault(upgrade));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the upgrade for a given side and its upgrade data.
|
* Set the upgrade for a given side and its upgrade data.
|
||||||
@@ -253,7 +268,7 @@ public interface ITurtleAccess {
|
|||||||
* @param upgrade The upgrade to set, may be {@code null} to clear.
|
* @param upgrade The upgrade to set, may be {@code null} to clear.
|
||||||
* @see #getUpgradeWithData(TurtleSide)
|
* @see #getUpgradeWithData(TurtleSide)
|
||||||
*/
|
*/
|
||||||
void setUpgrade(TurtleSide side, @Nullable UpgradeData<ITurtleUpgrade> upgrade);
|
void setUpgradeWithData(TurtleSide side, @Nullable UpgradeData<ITurtleUpgrade> upgrade);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the peripheral created by the upgrade on the specified side of the turtle, if there is one.
|
* Returns the peripheral created by the upgrade on the specified side of the turtle, if there is one.
|
||||||
@@ -267,23 +282,23 @@ public interface ITurtleAccess {
|
|||||||
/**
|
/**
|
||||||
* Get an upgrade-specific NBT compound, which can be used to store arbitrary data.
|
* Get an upgrade-specific NBT compound, which can be used to store arbitrary data.
|
||||||
* <p>
|
* <p>
|
||||||
* This will be persisted across turtle restarts and chunk loads, as well as being synced to the client. You can
|
* This will be persisted across turtle restarts and chunk loads, as well as being synced to the client. You must
|
||||||
* call {@link #setUpgrade(TurtleSide, UpgradeData)} to modify it.
|
* call {@link #updateUpgradeNBTData(TurtleSide)} after modifying it.
|
||||||
*
|
*
|
||||||
* @param side The side to get the upgrade data for.
|
* @param side The side to get the upgrade data for.
|
||||||
* @return The upgrade-specific data.
|
* @return The upgrade-specific data.
|
||||||
* @see #setUpgradeData(TurtleSide, DataComponentPatch)
|
* @see #updateUpgradeNBTData(TurtleSide)
|
||||||
* @see UpgradeBase#getUpgradeItem(DataComponentPatch)
|
* @see UpgradeBase#getUpgradeItem(CompoundTag)
|
||||||
* @see UpgradeBase#getUpgradeData(ItemStack)
|
* @see UpgradeBase#getUpgradeData(ItemStack)
|
||||||
*/
|
*/
|
||||||
DataComponentPatch getUpgradeData(TurtleSide side);
|
CompoundTag getUpgradeNBTData(TurtleSide side);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the upgrade-specific data.
|
* Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the
|
||||||
|
* client and persisted.
|
||||||
*
|
*
|
||||||
* @param side The side to set the upgrade data for.
|
* @param side The side to mark dirty.
|
||||||
* @param data The new upgrade data.
|
* @see #updateUpgradeNBTData(TurtleSide)
|
||||||
* @see #getUpgradeData(TurtleSide)
|
|
||||||
*/
|
*/
|
||||||
void setUpgradeData(TurtleSide side, DataComponentPatch data);
|
void updateUpgradeNBTData(TurtleSide side);
|
||||||
}
|
}
|
||||||
|
@@ -4,16 +4,10 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.turtle;
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeType;
|
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
|
||||||
import net.minecraft.resources.ResourceKey;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@@ -22,79 +16,22 @@ import javax.annotation.Nullable;
|
|||||||
* peripheral.
|
* peripheral.
|
||||||
* <p>
|
* <p>
|
||||||
* Turtle upgrades are defined in two stages. First, one creates a {@link ITurtleUpgrade} subclass and corresponding
|
* Turtle upgrades are defined in two stages. First, one creates a {@link ITurtleUpgrade} subclass and corresponding
|
||||||
* {@link UpgradeType} instance, which are then registered in a registry.
|
* {@link TurtleUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
||||||
* <p>
|
* <p>
|
||||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||||
* the upgrade automatically registered. It is recommended this is done via
|
* the upgrade registered internally. See the documentation in {@link TurtleUpgradeSerialiser} for details on this process
|
||||||
* <a href="../upgrades/UpgradeType.html#datagen">data generators</a>.
|
* and where files should be located.
|
||||||
*
|
*
|
||||||
* <h2>Example</h2>
|
* @see TurtleUpgradeSerialiser For how to register a turtle upgrade.
|
||||||
* {@snippet lang="java" :
|
|
||||||
* // We use Forge's DeferredRegister to register our upgrade type. Fabric mods may register their type directly.
|
|
||||||
* static final DeferredRegister<UpgradeType<? extends ITurtleUpgrade>> TURTLE_UPGRADES = DeferredRegister.create(ITurtleUpgrade.typeRegistry(), "my_mod");
|
|
||||||
*
|
|
||||||
* // Register a new upgrade type called "my_upgrade".
|
|
||||||
* public static final RegistryObject<UpgradeType<MyUpgrade>> MY_UPGRADE =
|
|
||||||
* TURTLE_UPGRADES.register("my_upgrade", () -> UpgradeType.simple(MyUpgrade::new));
|
|
||||||
*
|
|
||||||
* // Then in your constructor
|
|
||||||
* TURTLE_UPGRADES.register(bus);
|
|
||||||
* }
|
|
||||||
* <p>
|
|
||||||
* We can then define a new upgrade using JSON by placing the following in
|
|
||||||
* {@code data/<my_mod>/computercraft/turtle_upgrade/<my_upgrade_id>.json}.
|
|
||||||
* <p>
|
|
||||||
* {@snippet lang="json" :
|
|
||||||
* {
|
|
||||||
* "type": "my_mod:my_upgrade"
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* <p>
|
|
||||||
* Finally, we need to register a model for our upgrade, see
|
|
||||||
* {@link dan200.computercraft.api.client.turtle.TurtleUpgradeModeller} for more information.
|
|
||||||
*/
|
*/
|
||||||
public interface ITurtleUpgrade extends UpgradeBase {
|
public interface ITurtleUpgrade extends UpgradeBase {
|
||||||
/**
|
|
||||||
* The registry in which turtle upgrades are stored.
|
|
||||||
*/
|
|
||||||
ResourceKey<Registry<ITurtleUpgrade>> REGISTRY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_upgrade"));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link ResourceKey} for a turtle upgrade given a {@link ResourceLocation}.
|
|
||||||
* <p>
|
|
||||||
* This should only be called from within data generation code. Do not hard code references to your upgrades!
|
|
||||||
*
|
|
||||||
* @param id The id of the turtle upgrade.
|
|
||||||
* @return The upgrade registry key.
|
|
||||||
*/
|
|
||||||
static ResourceKey<ITurtleUpgrade> createKey(ResourceLocation id) {
|
|
||||||
return ResourceKey.create(REGISTRY, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The registry key for turtle upgrade types.
|
|
||||||
*
|
|
||||||
* @return The registry key.
|
|
||||||
*/
|
|
||||||
static ResourceKey<Registry<UpgradeType<? extends ITurtleUpgrade>>> typeRegistry() {
|
|
||||||
return ComputerCraftAPIService.get().turtleUpgradeRegistryId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the type of this upgrade.
|
|
||||||
*
|
|
||||||
* @return The type of this upgrade.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
UpgradeType<? extends ITurtleUpgrade> getType();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether this turtle adds a tool or a peripheral to the turtle.
|
* Return whether this turtle adds a tool or a peripheral to the turtle.
|
||||||
*
|
*
|
||||||
* @return The type of upgrade this is.
|
* @return The type of upgrade this is.
|
||||||
* @see TurtleUpgradeType for the differences between them.
|
* @see TurtleUpgradeType for the differences between them.
|
||||||
*/
|
*/
|
||||||
TurtleUpgradeType getUpgradeType();
|
TurtleUpgradeType getType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will only be called for peripheral upgrades. Creates a peripheral for a turtle being placed using this upgrade.
|
* Will only be called for peripheral upgrades. Creates a peripheral for a turtle being placed using this upgrade.
|
||||||
@@ -153,7 +90,7 @@ public interface ITurtleUpgrade extends UpgradeBase {
|
|||||||
* @param upgradeData Data that currently stored for this upgrade
|
* @param upgradeData Data that currently stored for this upgrade
|
||||||
* @return Filtered version of this data.
|
* @return Filtered version of this data.
|
||||||
*/
|
*/
|
||||||
default DataComponentPatch getPersistedData(DataComponentPatch upgradeData) {
|
default CompoundTag getPersistedData(CompoundTag upgradeData) {
|
||||||
return upgradeData;
|
return upgradeData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
package dan200.computercraft.api.turtle;
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enum representing the two sides of the turtle that a turtle turtle might reside.
|
* An enum representing the two sides of the turtle that a turtle upgrade might reside.
|
||||||
*/
|
*/
|
||||||
public enum TurtleSide {
|
public enum TurtleSide {
|
||||||
/**
|
/**
|
||||||
|
@@ -1,157 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.api.turtle;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftTags;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
|
||||||
import dan200.computercraft.impl.upgrades.TurtleToolSpec;
|
|
||||||
import net.minecraft.core.component.DataComponents;
|
|
||||||
import net.minecraft.data.worldgen.BootstrapContext;
|
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.resources.ResourceKey;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.tags.TagKey;
|
|
||||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder for custom turtle tool upgrades.
|
|
||||||
* <p>
|
|
||||||
* This can be used from your <a href="../upgrades/UpgradeType.html#datagen">data generator</a> code in order to
|
|
||||||
* register turtle tools for your mod's tools.
|
|
||||||
*
|
|
||||||
* <h2>Example:</h2>
|
|
||||||
* {@snippet lang = "java":
|
|
||||||
* import net.minecraft.data.worldgen.BootstrapContext;
|
|
||||||
* import net.minecraft.resources.ResourceLocation;
|
|
||||||
* import net.minecraft.world.item.Items;
|
|
||||||
*
|
|
||||||
* public void registerTool(BootstrapContext<ITurtleUpgrade> upgrades) {
|
|
||||||
* TurtleToolBuilder.tool(ResourceLocation.fromNamespaceAndPath("my_mod", "wooden_pickaxe"), Items.WOODEN_PICKAXE).register(upgrades);
|
|
||||||
* }
|
|
||||||
*}
|
|
||||||
*/
|
|
||||||
public final class TurtleToolBuilder {
|
|
||||||
private final ResourceKey<ITurtleUpgrade> id;
|
|
||||||
private final Item item;
|
|
||||||
private Component adjective;
|
|
||||||
private float damageMultiplier = TurtleToolSpec.DEFAULT_DAMAGE_MULTIPLIER;
|
|
||||||
private @Nullable TagKey<Block> breakable;
|
|
||||||
private boolean allowEnchantments = false;
|
|
||||||
private TurtleToolDurability consumeDurability = TurtleToolDurability.NEVER;
|
|
||||||
|
|
||||||
private TurtleToolBuilder(ResourceKey<ITurtleUpgrade> id, Item item) {
|
|
||||||
this.id = id;
|
|
||||||
adjective = Component.translatable(UpgradeBase.getDefaultAdjective(id.location()));
|
|
||||||
this.item = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TurtleToolBuilder tool(ResourceLocation id, Item item) {
|
|
||||||
return new TurtleToolBuilder(ITurtleUpgrade.createKey(id), item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TurtleToolBuilder tool(ResourceKey<ITurtleUpgrade> id, Item item) {
|
|
||||||
return new TurtleToolBuilder(id, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the id for this turtle tool.
|
|
||||||
*
|
|
||||||
* @return The upgrade id.
|
|
||||||
*/
|
|
||||||
public ResourceKey<ITurtleUpgrade> id() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify a custom adjective for this tool. By default this takes its adjective from the upgrade id.
|
|
||||||
*
|
|
||||||
* @param adjective The new adjective to use.
|
|
||||||
* @return The tool builder, for further use.
|
|
||||||
*/
|
|
||||||
public TurtleToolBuilder adjective(Component adjective) {
|
|
||||||
this.adjective = adjective;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The amount of damage a swing of this tool will do. This is multiplied by {@link Attributes#ATTACK_DAMAGE} to
|
|
||||||
* get the final damage.
|
|
||||||
*
|
|
||||||
* @param damageMultiplier The damage multiplier.
|
|
||||||
* @return The tool builder, for further use.
|
|
||||||
*/
|
|
||||||
public TurtleToolBuilder damageMultiplier(float damageMultiplier) {
|
|
||||||
this.damageMultiplier = damageMultiplier;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicate that this upgrade allows items which have been {@linkplain ItemStack#isEnchanted() enchanted} or have
|
|
||||||
* {@linkplain DataComponents#ATTRIBUTE_MODIFIERS custom attribute modifiers}.
|
|
||||||
*
|
|
||||||
* @return The tool builder, for further use.
|
|
||||||
*/
|
|
||||||
public TurtleToolBuilder allowEnchantments() {
|
|
||||||
allowEnchantments = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set when the tool will consume durability.
|
|
||||||
*
|
|
||||||
* @param durability The durability predicate.
|
|
||||||
* @return The tool builder, for further use.
|
|
||||||
*/
|
|
||||||
public TurtleToolBuilder consumeDurability(TurtleToolDurability durability) {
|
|
||||||
consumeDurability = durability;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide a list of breakable blocks. If not given, the tool can break all blocks. If given, only blocks
|
|
||||||
* in this tag, those in {@link ComputerCraftTags.Blocks#TURTLE_ALWAYS_BREAKABLE} and "insta-mine" ones can
|
|
||||||
* be broken.
|
|
||||||
*
|
|
||||||
* @param breakable The tag containing all blocks breakable by this item.
|
|
||||||
* @return The tool builder, for further use.
|
|
||||||
* @see ComputerCraftTags.Blocks
|
|
||||||
*/
|
|
||||||
public TurtleToolBuilder breakable(TagKey<Block> breakable) {
|
|
||||||
this.breakable = breakable;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the turtle tool upgrade.
|
|
||||||
*
|
|
||||||
* @return The constructed upgrade.
|
|
||||||
*/
|
|
||||||
public ITurtleUpgrade build() {
|
|
||||||
return ComputerCraftAPIService.get().createTurtleTool(new TurtleToolSpec(
|
|
||||||
adjective,
|
|
||||||
item,
|
|
||||||
damageMultiplier,
|
|
||||||
allowEnchantments,
|
|
||||||
consumeDurability,
|
|
||||||
Optional.ofNullable(breakable)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build this upgrade and register it for datagen.
|
|
||||||
*
|
|
||||||
* @param upgrades The registry this upgrade should be added to.
|
|
||||||
*/
|
|
||||||
public void register(BootstrapContext<ITurtleUpgrade> upgrades) {
|
|
||||||
upgrades.register(id(), build());
|
|
||||||
}
|
|
||||||
}
|
|
@@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.turtle;
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
import net.minecraft.core.component.DataComponents;
|
|
||||||
import net.minecraft.util.StringRepresentable;
|
import net.minecraft.util.StringRepresentable;
|
||||||
|
import net.minecraft.world.entity.EquipmentSlot;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if an equipped turtle item will consume durability.
|
* Indicates if an equipped turtle item will consume durability.
|
||||||
*
|
*
|
||||||
* @see TurtleToolBuilder#consumeDurability(TurtleToolDurability)
|
* @see TurtleUpgradeDataProvider.ToolBuilder#consumeDurability(TurtleToolDurability)
|
||||||
*/
|
*/
|
||||||
public enum TurtleToolDurability implements StringRepresentable {
|
public enum TurtleToolDurability implements StringRepresentable {
|
||||||
/**
|
/**
|
||||||
@@ -21,7 +21,7 @@ public enum TurtleToolDurability implements StringRepresentable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The equipped tool consumes durability if it is {@linkplain ItemStack#isEnchanted() enchanted} or has
|
* The equipped tool consumes durability if it is {@linkplain ItemStack#isEnchanted() enchanted} or has
|
||||||
* {@linkplain DataComponents#ATTRIBUTE_MODIFIERS custom attribute modifiers}.
|
* {@linkplain ItemStack#getAttributeModifiers(EquipmentSlot) custom attribute modifiers}.
|
||||||
*/
|
*/
|
||||||
WHEN_ENCHANTED("when_enchanted"),
|
WHEN_ENCHANTED("when_enchanted"),
|
||||||
|
|
||||||
|
@@ -0,0 +1,168 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.ComputerCraftTags;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||||
|
import dan200.computercraft.impl.PlatformHelper;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.data.DataGenerator;
|
||||||
|
import net.minecraft.data.PackOutput;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.tags.TagKey;
|
||||||
|
import net.minecraft.world.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data provider to generate turtle upgrades.
|
||||||
|
* <p>
|
||||||
|
* This should be subclassed and registered to a {@link DataGenerator.PackGenerator}. Override the
|
||||||
|
* {@link #addUpgrades(Consumer)} function, construct each upgrade, and pass them off to the provided consumer to
|
||||||
|
* generate them.
|
||||||
|
*
|
||||||
|
* @see TurtleUpgradeSerialiser
|
||||||
|
*/
|
||||||
|
public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITurtleUpgrade, TurtleUpgradeSerialiser<?>> {
|
||||||
|
private static final ResourceLocation TOOL_ID = new ResourceLocation(ComputerCraftAPI.MOD_ID, "tool");
|
||||||
|
|
||||||
|
public TurtleUpgradeDataProvider(PackOutput output) {
|
||||||
|
super(output, "Turtle Upgrades", "computercraft/turtle_upgrades", TurtleUpgradeSerialiser.registryId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new turtle tool upgrade, such as a pickaxe or shovel.
|
||||||
|
*
|
||||||
|
* @param id The ID of this tool.
|
||||||
|
* @param item The item used for tool actions. Note, this doesn't inherit all properties of the tool, you may need
|
||||||
|
* to specify {@link ToolBuilder#damageMultiplier(float)} and {@link ToolBuilder#breakable(TagKey)}.
|
||||||
|
* @return A tool builder,
|
||||||
|
*/
|
||||||
|
public final ToolBuilder tool(ResourceLocation id, Item item) {
|
||||||
|
return new ToolBuilder(id, existingSerialiser(TOOL_ID), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for custom turtle tool upgrades.
|
||||||
|
*
|
||||||
|
* @see #tool(ResourceLocation, Item)
|
||||||
|
*/
|
||||||
|
public static class ToolBuilder {
|
||||||
|
private final ResourceLocation id;
|
||||||
|
private final TurtleUpgradeSerialiser<?> serialiser;
|
||||||
|
private final Item toolItem;
|
||||||
|
private @Nullable String adjective;
|
||||||
|
private @Nullable Item craftingItem;
|
||||||
|
private @Nullable Float damageMultiplier = null;
|
||||||
|
private @Nullable TagKey<Block> breakable;
|
||||||
|
private boolean allowEnchantments = false;
|
||||||
|
private TurtleToolDurability consumeDurability = TurtleToolDurability.NEVER;
|
||||||
|
|
||||||
|
ToolBuilder(ResourceLocation id, TurtleUpgradeSerialiser<?> serialiser, Item toolItem) {
|
||||||
|
this.id = id;
|
||||||
|
this.serialiser = serialiser;
|
||||||
|
this.toolItem = toolItem;
|
||||||
|
craftingItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify a custom adjective for this tool. By default this takes its adjective from the tool item.
|
||||||
|
*
|
||||||
|
* @param adjective The new adjective to use.
|
||||||
|
* @return The tool builder, for further use.
|
||||||
|
*/
|
||||||
|
public ToolBuilder adjective(String adjective) {
|
||||||
|
this.adjective = adjective;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify a custom item which is used to craft this upgrade. By default this is the same as the provided tool
|
||||||
|
* item, but you may wish to override it.
|
||||||
|
*
|
||||||
|
* @param craftingItem The item used to craft this upgrade.
|
||||||
|
* @return The tool builder, for further use.
|
||||||
|
*/
|
||||||
|
public ToolBuilder craftingItem(Item craftingItem) {
|
||||||
|
this.craftingItem = craftingItem;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of damage a swing of this tool will do. This is multiplied by {@link Attributes#ATTACK_DAMAGE} to
|
||||||
|
* get the final damage.
|
||||||
|
*
|
||||||
|
* @param damageMultiplier The damage multiplier.
|
||||||
|
* @return The tool builder, for further use.
|
||||||
|
*/
|
||||||
|
public ToolBuilder damageMultiplier(float damageMultiplier) {
|
||||||
|
this.damageMultiplier = damageMultiplier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that this upgrade allows items which have been {@linkplain ItemStack#isEnchanted() enchanted} or have
|
||||||
|
* {@linkplain ItemStack#getAttributeModifiers(EquipmentSlot) custom attribute modifiers}.
|
||||||
|
*
|
||||||
|
* @return The tool builder, for further use.
|
||||||
|
*/
|
||||||
|
public ToolBuilder allowEnchantments() {
|
||||||
|
allowEnchantments = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when the tool will consume durability.
|
||||||
|
*
|
||||||
|
* @param durability The durability predicate.
|
||||||
|
* @return The tool builder, for further use.
|
||||||
|
*/
|
||||||
|
public ToolBuilder consumeDurability(TurtleToolDurability durability) {
|
||||||
|
consumeDurability = durability;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a list of breakable blocks. If not given, the tool can break all blocks. If given, only blocks
|
||||||
|
* in this tag, those in {@link ComputerCraftTags.Blocks#TURTLE_ALWAYS_BREAKABLE} and "insta-mine" ones can
|
||||||
|
* be broken.
|
||||||
|
*
|
||||||
|
* @param breakable The tag containing all blocks breakable by this item.
|
||||||
|
* @return The tool builder, for further use.
|
||||||
|
* @see ComputerCraftTags.Blocks
|
||||||
|
*/
|
||||||
|
public ToolBuilder breakable(TagKey<Block> breakable) {
|
||||||
|
this.breakable = breakable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register this as an upgrade.
|
||||||
|
*
|
||||||
|
* @param add The callback given to {@link #addUpgrades(Consumer)}.
|
||||||
|
*/
|
||||||
|
public void add(Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> add) {
|
||||||
|
add.accept(new Upgrade<>(id, serialiser, s -> {
|
||||||
|
s.addProperty("item", PlatformHelper.get().getRegistryKey(Registries.ITEM, toolItem).toString());
|
||||||
|
if (adjective != null) s.addProperty("adjective", adjective);
|
||||||
|
if (craftingItem != null) {
|
||||||
|
s.addProperty("craftItem", PlatformHelper.get().getRegistryKey(Registries.ITEM, craftingItem).toString());
|
||||||
|
}
|
||||||
|
if (damageMultiplier != null) s.addProperty("damageMultiplier", damageMultiplier);
|
||||||
|
if (breakable != null) s.addProperty("breakable", breakable.location().toString());
|
||||||
|
if (allowEnchantments) s.addProperty("allowEnchantments", true);
|
||||||
|
if (consumeDurability != TurtleToolDurability.NEVER) {
|
||||||
|
s.addProperty("consumeDurability", consumeDurability.getSerializedName());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,109 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
|
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||||
|
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||||
|
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||||
|
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a {@link ITurtleUpgrade} from disk and reads/writes it to a network packet.
|
||||||
|
* <p>
|
||||||
|
* These should be registered in a {@link Registry} while the game is loading, much like {@link RecipeSerializer}s.
|
||||||
|
* <p>
|
||||||
|
* If your turtle upgrade doesn't have any associated configurable parameters (like most upgrades), you can use
|
||||||
|
* {@link #simple(Function)} or {@link #simpleWithCustomItem(BiFunction)} to create a basic upgrade serialiser.
|
||||||
|
*
|
||||||
|
* <h2>Example (Forge)</h2>
|
||||||
|
* <pre class="language language-java">{@code
|
||||||
|
* static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
|
||||||
|
*
|
||||||
|
* // Register a new upgrade serialiser called "my_upgrade".
|
||||||
|
* public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
|
||||||
|
* SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
|
||||||
|
*
|
||||||
|
* // Then in your constructor
|
||||||
|
* SERIALISERS.register( bus );
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* We can then define a new upgrade using JSON by placing the following in
|
||||||
|
* {@literal data/<my_mod>/computercraft/turtle_upgrades/<my_upgrade_id>.json}}.
|
||||||
|
*
|
||||||
|
* <pre class="language language-json">{@code
|
||||||
|
* {
|
||||||
|
* "type": "my_mod:my_upgrade",
|
||||||
|
* }
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* Finally, we need to register a model for our upgrade. The way to do this varies on mod loader, see
|
||||||
|
* {@link dan200.computercraft.api.client.turtle.TurtleUpgradeModeller} for more information.
|
||||||
|
* <p>
|
||||||
|
* {@link TurtleUpgradeDataProvider} provides a data provider to aid with generating these JSON files.
|
||||||
|
*
|
||||||
|
* @param <T> The type of turtle upgrade this is responsible for serialising.
|
||||||
|
* @see ITurtleUpgrade
|
||||||
|
* @see TurtleUpgradeDataProvider
|
||||||
|
* @see dan200.computercraft.api.client.turtle.TurtleUpgradeModeller
|
||||||
|
*/
|
||||||
|
public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends UpgradeSerialiser<T> {
|
||||||
|
/**
|
||||||
|
* The ID for the associated registry.
|
||||||
|
*
|
||||||
|
* @return The registry key.
|
||||||
|
*/
|
||||||
|
static ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> registryId() {
|
||||||
|
return ComputerCraftAPIService.get().turtleUpgradeRegistryId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleCraftingRecipeSerializer},
|
||||||
|
* but for upgrades.
|
||||||
|
* <p>
|
||||||
|
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||||
|
*
|
||||||
|
* @param factory Generate a new upgrade with a specific ID.
|
||||||
|
* @param <T> The type of the generated upgrade.
|
||||||
|
* @return The serialiser for this upgrade
|
||||||
|
*/
|
||||||
|
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simple(Function<ResourceLocation, T> factory) {
|
||||||
|
final class Impl extends SimpleSerialiser<T> implements TurtleUpgradeSerialiser<T> {
|
||||||
|
private Impl(Function<ResourceLocation, T> constructor) {
|
||||||
|
super(constructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Impl(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
||||||
|
*
|
||||||
|
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
||||||
|
* {@link UpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
||||||
|
* @param <T> The type of the generated upgrade.
|
||||||
|
* @return The serialiser for this upgrade.
|
||||||
|
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
||||||
|
*/
|
||||||
|
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simpleWithCustomItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||||
|
final class Impl extends SerialiserWithCraftingItem<T> implements TurtleUpgradeSerialiser<T> {
|
||||||
|
private Impl(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||||
|
super(factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Impl(factory);
|
||||||
|
}
|
||||||
|
}
|
@@ -9,34 +9,37 @@ import dan200.computercraft.api.pocket.IPocketUpgrade;
|
|||||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
|
import dan200.computercraft.impl.PlatformHelper;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common functionality between {@link ITurtleUpgrade} and {@link IPocketUpgrade}.
|
* Common functionality between {@link ITurtleUpgrade} and {@link IPocketUpgrade}.
|
||||||
*/
|
*/
|
||||||
public interface UpgradeBase {
|
public interface UpgradeBase {
|
||||||
/**
|
/**
|
||||||
* Get the type of this upgrade.
|
* Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem"
|
||||||
|
* or "my_mod:my_upgrade".
|
||||||
|
* <p>
|
||||||
|
* You should use a unique resource domain to ensure this upgrade is uniquely identified.
|
||||||
|
* The upgrade will fail registration if an already used ID is specified.
|
||||||
*
|
*
|
||||||
* @return The type of this upgrade.
|
* @return The unique ID for this upgrade.
|
||||||
*/
|
*/
|
||||||
UpgradeType<?> getType();
|
ResourceLocation getUpgradeID();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A description of this upgrade for use in item names.
|
* Return an unlocalised string to describe this type of computer in item names.
|
||||||
* <p>
|
|
||||||
* This should typically be a {@linkplain Component#translatable(String) translation key}, rather than a hard coded
|
|
||||||
* string.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Examples of built-in adjectives are "Wireless", "Mining" and "Crafty".
|
* Examples of built-in adjectives are "Wireless", "Mining" and "Crafty".
|
||||||
*
|
*
|
||||||
* @return The text component for this upgrade's adjective.
|
* @return The localisation key for this upgrade's adjective.
|
||||||
*/
|
*/
|
||||||
Component getAdjective();
|
String getUnlocalisedAdjective();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an item stack representing the type of item that a computer must be crafted
|
* Return an item stack representing the type of item that a computer must be crafted
|
||||||
@@ -54,8 +57,8 @@ public interface UpgradeBase {
|
|||||||
/**
|
/**
|
||||||
* Returns the item stack representing a currently equipped turtle upgrade.
|
* Returns the item stack representing a currently equipped turtle upgrade.
|
||||||
* <p>
|
* <p>
|
||||||
* While upgrades can store upgrade data ({@link ITurtleAccess#getUpgradeData(TurtleSide)} and
|
* While upgrades can store upgrade data ({@link ITurtleAccess#getUpgradeNBTData(TurtleSide)} and
|
||||||
* {@link IPocketAccess#getUpgradeData()}}, by default this data is discarded when an upgrade is unequipped,
|
* {@link IPocketAccess#getUpgradeNBTData()}}, by default this data is discarded when an upgrade is unequipped,
|
||||||
* and the original item stack is returned.
|
* and the original item stack is returned.
|
||||||
* <p>
|
* <p>
|
||||||
* By overriding this method, you can create a new {@link ItemStack} which contains enough data to
|
* By overriding this method, you can create a new {@link ItemStack} which contains enough data to
|
||||||
@@ -67,24 +70,24 @@ public interface UpgradeBase {
|
|||||||
* @param upgradeData The current upgrade data. This should <strong>NOT</strong> be mutated.
|
* @param upgradeData The current upgrade data. This should <strong>NOT</strong> be mutated.
|
||||||
* @return The item stack returned when unequipping.
|
* @return The item stack returned when unequipping.
|
||||||
*/
|
*/
|
||||||
default ItemStack getUpgradeItem(DataComponentPatch upgradeData) {
|
default ItemStack getUpgradeItem(CompoundTag upgradeData) {
|
||||||
return getCraftingItem();
|
return getCraftingItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract upgrade data from an {@link ItemStack}.
|
* Extract upgrade data from an {@link ItemStack}.
|
||||||
* <p>
|
* <p>
|
||||||
* This upgrade data will be available with {@link ITurtleAccess#getUpgradeData(TurtleSide)} or
|
* This upgrade data will be available with {@link ITurtleAccess#getUpgradeNBTData(TurtleSide)} or
|
||||||
* {@link IPocketAccess#getUpgradeData()}.
|
* {@link IPocketAccess#getUpgradeNBTData()}.
|
||||||
* <p>
|
* <p>
|
||||||
* This should be an inverse to {@link #getUpgradeItem(DataComponentPatch)}.
|
* This should be an inverse to {@link #getUpgradeItem(CompoundTag)}.
|
||||||
*
|
*
|
||||||
* @param stack The stack that was equipped by the turtle or pocket computer. This will have the same item as
|
* @param stack The stack that was equipped by the turtle or pocket computer. This will have the same item as
|
||||||
* {@link #getCraftingItem()}.
|
* {@link #getCraftingItem()}.
|
||||||
* @return The upgrade data that should be set on the turtle or pocket computer.
|
* @return The upgrade data that should be set on the turtle or pocket computer.
|
||||||
*/
|
*/
|
||||||
default DataComponentPatch getUpgradeData(ItemStack stack) {
|
default CompoundTag getUpgradeData(ItemStack stack) {
|
||||||
return DataComponentPatch.EMPTY;
|
return new CompoundTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,15 +97,26 @@ public interface UpgradeBase {
|
|||||||
* the original stack. In order to prevent people losing items with enchantments (or
|
* the original stack. In order to prevent people losing items with enchantments (or
|
||||||
* repairing items with non-0 damage), we impose additional checks on the item.
|
* repairing items with non-0 damage), we impose additional checks on the item.
|
||||||
* <p>
|
* <p>
|
||||||
* The default check requires that any NBT is exactly the same as the crafting item,
|
* The default check requires that any non-capability NBT is exactly the same as the
|
||||||
* but this may be relaxed for your upgrade.
|
* crafting item, but this may be relaxed for your upgrade.
|
||||||
|
* <p>
|
||||||
|
* This is based on {@code net.minecraftforge.common.crafting.StrictNBTIngredient}'s check.
|
||||||
*
|
*
|
||||||
* @param stack The stack to check. This is guaranteed to be non-empty and have the same item as
|
* @param stack The stack to check. This is guaranteed to be non-empty and have the same item as
|
||||||
* {@link #getCraftingItem()}.
|
* {@link #getCraftingItem()}.
|
||||||
* @return If this stack may be used to equip this upgrade.
|
* @return If this stack may be used to equip this upgrade.
|
||||||
*/
|
*/
|
||||||
default boolean isItemSuitable(ItemStack stack) {
|
default boolean isItemSuitable(ItemStack stack) {
|
||||||
return ItemStack.isSameItemSameComponents(getCraftingItem(), stack);
|
var crafting = getCraftingItem();
|
||||||
|
|
||||||
|
// A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a
|
||||||
|
// null one.
|
||||||
|
var shareTag = PlatformHelper.get().getShareTag(stack);
|
||||||
|
var craftingShareTag = PlatformHelper.get().getShareTag(crafting);
|
||||||
|
if (shareTag == craftingShareTag) return true;
|
||||||
|
if (shareTag == null) return Objects.requireNonNull(craftingShareTag).isEmpty();
|
||||||
|
if (craftingShareTag == null) return shareTag.isEmpty();
|
||||||
|
return shareTag.equals(craftingShareTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,7 +125,7 @@ public interface UpgradeBase {
|
|||||||
*
|
*
|
||||||
* @param id The upgrade ID.
|
* @param id The upgrade ID.
|
||||||
* @return The generated adjective.
|
* @return The generated adjective.
|
||||||
* @see #getAdjective()
|
* @see #getUnlocalisedAdjective()
|
||||||
*/
|
*/
|
||||||
static String getDefaultAdjective(ResourceLocation id) {
|
static String getDefaultAdjective(ResourceLocation id) {
|
||||||
return Util.makeDescriptionId("upgrade", id) + ".adjective";
|
return Util.makeDescriptionId("upgrade", id) + ".adjective";
|
||||||
|
@@ -6,57 +6,60 @@ package dan200.computercraft.api.upgrades;
|
|||||||
|
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An upgrade (i.e. a {@link ITurtleUpgrade}) and its current upgrade data.
|
* An upgrade (i.e. a {@link ITurtleUpgrade}) and its current upgrade data.
|
||||||
|
* <p>
|
||||||
|
* <strong>IMPORTANT:</strong> The {@link #data()} in an upgrade data is often a reference to the original upgrade data.
|
||||||
|
* Be careful to take a {@linkplain #copy() defensive copy} if you plan to use the data in this upgrade.
|
||||||
*
|
*
|
||||||
* @param holder The current upgrade holder.
|
* @param upgrade The current upgrade.
|
||||||
* @param data The upgrade's data.
|
* @param data The upgrade's data.
|
||||||
* @param <T> The type of upgrade, either {@link ITurtleUpgrade} or {@link IPocketUpgrade}.
|
* @param <T> The type of upgrade, either {@link ITurtleUpgrade} or {@link IPocketUpgrade}.
|
||||||
*/
|
*/
|
||||||
public record UpgradeData<T extends UpgradeBase>(Holder.Reference<T> holder, DataComponentPatch data) {
|
public record UpgradeData<T extends UpgradeBase>(T upgrade, CompoundTag data) {
|
||||||
/**
|
/**
|
||||||
* A utility method to construct a new {@link UpgradeData} instance.
|
* A utility method to construct a new {@link UpgradeData} instance.
|
||||||
*
|
*
|
||||||
* @param holder An upgrade.
|
* @param upgrade An upgrade.
|
||||||
* @param data The upgrade's data.
|
* @param data The upgrade's data.
|
||||||
* @param <T> The type of upgrade.
|
* @param <T> The type of upgrade.
|
||||||
* @return The new {@link UpgradeData} instance.
|
* @return The new {@link UpgradeData} instance.
|
||||||
*/
|
*/
|
||||||
public static <T extends UpgradeBase> UpgradeData<T> of(Holder.Reference<T> holder, DataComponentPatch data) {
|
public static <T extends UpgradeBase> UpgradeData<T> of(T upgrade, CompoundTag data) {
|
||||||
return new UpgradeData<>(holder, data);
|
return new UpgradeData<>(upgrade, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an {@link UpgradeData} containing the default {@linkplain #data() data} for an upgrade.
|
* Create an {@link UpgradeData} containing the default {@linkplain #data() data} for an upgrade.
|
||||||
*
|
*
|
||||||
* @param holder The upgrade instance.
|
* @param upgrade The upgrade instance.
|
||||||
* @param <T> The type of upgrade.
|
* @param <T> The type of upgrade.
|
||||||
* @return The default upgrade data.
|
* @return The default upgrade data.
|
||||||
*/
|
*/
|
||||||
public static <T extends UpgradeBase> UpgradeData<T> ofDefault(Holder.Reference<T> holder) {
|
public static <T extends UpgradeBase> UpgradeData<T> ofDefault(T upgrade) {
|
||||||
var upgrade = holder.value();
|
return of(upgrade, upgrade.getUpgradeData(upgrade.getCraftingItem()));
|
||||||
return of(holder, upgrade.getUpgradeData(upgrade.getCraftingItem()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public UpgradeData {
|
|
||||||
if (!holder.isBound()) throw new IllegalArgumentException("Holder is not bound");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current upgrade.
|
* Take a copy of a (possibly {@code null}) {@link UpgradeData} instance.
|
||||||
*
|
*
|
||||||
* @return The current upgrade.
|
* @param upgrade The copied upgrade data.
|
||||||
|
* @param <T> The type of upgrade.
|
||||||
|
* @return The newly created upgrade data.
|
||||||
*/
|
*/
|
||||||
public T upgrade() {
|
@Contract("!null -> !null; null -> null")
|
||||||
return holder().value();
|
public static <T extends UpgradeBase> @Nullable UpgradeData<T> copyOf(@Nullable UpgradeData<T> upgrade) {
|
||||||
|
return upgrade == null ? null : upgrade.copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@linkplain UpgradeBase#getUpgradeItem(DataComponentPatch) upgrade item} for this upgrade.
|
* Get the {@linkplain UpgradeBase#getUpgradeItem(CompoundTag) upgrade item} for this upgrade.
|
||||||
* <p>
|
* <p>
|
||||||
* This returns a defensive copy of the item, to prevent accidental mutation of the upgrade data or original
|
* This returns a defensive copy of the item, to prevent accidental mutation of the upgrade data or original
|
||||||
* {@linkplain UpgradeBase#getCraftingItem() upgrade stack}.
|
* {@linkplain UpgradeBase#getCraftingItem() upgrade stack}.
|
||||||
@@ -64,6 +67,16 @@ public record UpgradeData<T extends UpgradeBase>(Holder.Reference<T> holder, Dat
|
|||||||
* @return This upgrade's item.
|
* @return This upgrade's item.
|
||||||
*/
|
*/
|
||||||
public ItemStack getUpgradeItem() {
|
public ItemStack getUpgradeItem() {
|
||||||
return upgrade().getUpgradeItem(data).copy();
|
return upgrade.getUpgradeItem(data).copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take a copy of this {@link UpgradeData}. This returns a new instance with the same upgrade and a fresh copy of
|
||||||
|
* the upgrade data.
|
||||||
|
*
|
||||||
|
* @return A copy of the current instance.
|
||||||
|
*/
|
||||||
|
public UpgradeData<T> copy() {
|
||||||
|
return new UpgradeData<>(upgrade(), data().copy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,179 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.upgrades;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
|
import dan200.computercraft.impl.PlatformHelper;
|
||||||
|
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||||
|
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.data.CachedOutput;
|
||||||
|
import net.minecraft.data.DataProvider;
|
||||||
|
import net.minecraft.data.PackOutput;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data generator/provider for turtle and pocket computer upgrades. This should not be extended directly, instead see
|
||||||
|
* the other subclasses.
|
||||||
|
*
|
||||||
|
* @param <T> The base class of upgrades.
|
||||||
|
* @param <R> The upgrade serialiser to register for.
|
||||||
|
*/
|
||||||
|
public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends UpgradeSerialiser<? extends T>> implements DataProvider {
|
||||||
|
private final PackOutput output;
|
||||||
|
private final String name;
|
||||||
|
private final String folder;
|
||||||
|
private final ResourceKey<Registry<R>> registry;
|
||||||
|
|
||||||
|
private @Nullable List<T> upgrades;
|
||||||
|
|
||||||
|
protected UpgradeDataProvider(PackOutput output, String name, String folder, ResourceKey<Registry<R>> registry) {
|
||||||
|
this.output = output;
|
||||||
|
this.name = name;
|
||||||
|
this.folder = folder;
|
||||||
|
this.registry = registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an upgrade using a "simple" serialiser (e.g. {@link TurtleUpgradeSerialiser#simple(Function)}).
|
||||||
|
*
|
||||||
|
* @param id The ID of the upgrade to create.
|
||||||
|
* @param serialiser The simple serialiser.
|
||||||
|
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||||
|
*/
|
||||||
|
public final Upgrade<R> simple(ResourceLocation id, R serialiser) {
|
||||||
|
if (!(serialiser instanceof SimpleSerialiser)) {
|
||||||
|
throw new IllegalStateException(serialiser + " must be a simple() seriaiser.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Upgrade<>(id, serialiser, s -> {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an upgrade using a "simple" serialiser (e.g. {@link TurtleUpgradeSerialiser#simple(Function)}).
|
||||||
|
*
|
||||||
|
* @param id The ID of the upgrade to create.
|
||||||
|
* @param serialiser The simple serialiser.
|
||||||
|
* @param item The crafting upgrade for this item.
|
||||||
|
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||||
|
*/
|
||||||
|
public final Upgrade<R> simpleWithCustomItem(ResourceLocation id, R serialiser, Item item) {
|
||||||
|
if (!(serialiser instanceof SerialiserWithCraftingItem)) {
|
||||||
|
throw new IllegalStateException(serialiser + " must be a simpleWithCustomItem() serialiser.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Upgrade<>(id, serialiser, s ->
|
||||||
|
s.addProperty("item", PlatformHelper.get().getRegistryKey(Registries.ITEM, item).toString())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all turtle or pocket computer upgrades.
|
||||||
|
* <p>
|
||||||
|
* <strong>Example usage:</strong>
|
||||||
|
* <pre class="language language-java">{@code
|
||||||
|
* protected void addUpgrades(Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade) {
|
||||||
|
* simple(new ResourceLocation("mymod", "speaker"), SPEAKER_SERIALISER.get()).add(addUpgrade);
|
||||||
|
* }
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @param addUpgrade A callback used to register an upgrade.
|
||||||
|
*/
|
||||||
|
protected abstract void addUpgrades(Consumer<Upgrade<R>> addUpgrade);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<?> run(CachedOutput cache) {
|
||||||
|
var base = output.getOutputFolder().resolve("data");
|
||||||
|
|
||||||
|
Set<ResourceLocation> seen = new HashSet<>();
|
||||||
|
List<T> upgrades = new ArrayList<>();
|
||||||
|
List<CompletableFuture<?>> futures = new ArrayList<>();
|
||||||
|
addUpgrades(upgrade -> {
|
||||||
|
if (!seen.add(upgrade.id())) throw new IllegalStateException("Duplicate upgrade " + upgrade.id());
|
||||||
|
|
||||||
|
var json = new JsonObject();
|
||||||
|
json.addProperty("type", PlatformHelper.get().getRegistryKey(registry, upgrade.serialiser()).toString());
|
||||||
|
upgrade.serialise().accept(json);
|
||||||
|
|
||||||
|
futures.add(DataProvider.saveStable(cache, json, base.resolve(upgrade.id().getNamespace() + "/" + folder + "/" + upgrade.id().getPath() + ".json")));
|
||||||
|
|
||||||
|
try {
|
||||||
|
var result = upgrade.serialiser().fromJson(upgrade.id(), json);
|
||||||
|
upgrades.add(result);
|
||||||
|
} catch (IllegalArgumentException | JsonParseException e) {
|
||||||
|
LOGGER.error("Failed to parse {} {}", name, upgrade.id(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.upgrades = Collections.unmodifiableList(upgrades);
|
||||||
|
return Util.sequenceFailFast(futures);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final R existingSerialiser(ResourceLocation id) {
|
||||||
|
var result = PlatformHelper.get().getRegistryObject(registry, id);
|
||||||
|
if (result == null) throw new IllegalArgumentException("No such serialiser " + registry);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> getGeneratedUpgrades() {
|
||||||
|
if (upgrades == null) throw new IllegalStateException("Upgrades have not been generated yet");
|
||||||
|
return upgrades;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A constructed upgrade instance, produced {@link #addUpgrades(Consumer)}.
|
||||||
|
*
|
||||||
|
* @param id The ID for this upgrade.
|
||||||
|
* @param serialiser The serialiser which reads and writes this upgrade.
|
||||||
|
* @param serialise Augment the generated JSON with additional fields.
|
||||||
|
* @param <R> The type of upgrade serialiser.
|
||||||
|
*/
|
||||||
|
public record Upgrade<R extends UpgradeSerialiser<?>>(
|
||||||
|
ResourceLocation id, R serialiser, Consumer<JsonObject> serialise
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Convenience method for registering an upgrade.
|
||||||
|
*
|
||||||
|
* @param add The callback given to {@link #addUpgrades(Consumer)}
|
||||||
|
*/
|
||||||
|
public void add(Consumer<Upgrade<R>> add) {
|
||||||
|
add.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new {@link Upgrade} which requires the given mod to be present.
|
||||||
|
* <p>
|
||||||
|
* This uses mod-loader-specific hooks (Forge's crafting conditions and Fabric's resource conditions). If using
|
||||||
|
* this in a multi-loader setup, you must generate resources separately for the two loaders.
|
||||||
|
*
|
||||||
|
* @param modId The id of the mod.
|
||||||
|
* @return A new upgrade instance.
|
||||||
|
*/
|
||||||
|
public Upgrade<R> requireMod(String modId) {
|
||||||
|
return new Upgrade<>(id, serialiser, json -> {
|
||||||
|
PlatformHelper.get().addRequiredModCondition(json, modId);
|
||||||
|
serialise.accept(json);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.upgrades;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base interface for upgrade serialisers. This should generally not be implemented directly, instead implementing one
|
||||||
|
* of {@link TurtleUpgradeSerialiser} or {@link PocketUpgradeSerialiser}.
|
||||||
|
* <p>
|
||||||
|
* However, it may sometimes be useful to implement this if you have some shared logic between upgrade types.
|
||||||
|
*
|
||||||
|
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||||
|
* @see TurtleUpgradeSerialiser
|
||||||
|
* @see PocketUpgradeSerialiser
|
||||||
|
*/
|
||||||
|
public interface UpgradeSerialiser<T extends UpgradeBase> {
|
||||||
|
/**
|
||||||
|
* Read this upgrade from a JSON file in a datapack.
|
||||||
|
*
|
||||||
|
* @param id The ID of this upgrade.
|
||||||
|
* @param object The JSON object to load this upgrade from.
|
||||||
|
* @return The constructed upgrade, with a {@link UpgradeBase#getUpgradeID()} equal to {@code id}.
|
||||||
|
* @see net.minecraft.util.GsonHelper For additional JSON helper methods.
|
||||||
|
*/
|
||||||
|
T fromJson(ResourceLocation id, JsonObject object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this upgrade from a network packet, sent from the server.
|
||||||
|
*
|
||||||
|
* @param id The ID of this upgrade.
|
||||||
|
* @param buffer The buffer object to read this upgrade from.
|
||||||
|
* @return The constructed upgrade, with a {@link UpgradeBase#getUpgradeID()} equal to {@code id}.
|
||||||
|
*/
|
||||||
|
T fromNetwork(ResourceLocation id, FriendlyByteBuf buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write this upgrade to a network packet, to be sent to the client.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer object to write this upgrade to
|
||||||
|
* @param upgrade The upgrade to write.
|
||||||
|
*/
|
||||||
|
void toNetwork(FriendlyByteBuf buffer, T upgrade);
|
||||||
|
|
||||||
|
}
|
@@ -1,115 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.api.upgrades;
|
|
||||||
|
|
||||||
import com.mojang.serialization.MapCodec;
|
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
|
||||||
import dan200.computercraft.impl.upgrades.UpgradeTypeImpl;
|
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
|
||||||
import net.minecraft.data.registries.RegistryPatchGenerator;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.item.crafting.Recipe;
|
|
||||||
import net.minecraft.world.level.storage.loot.functions.LootItemFunction;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of a {@linkplain ITurtleUpgrade turtle} or {@linkplain IPocketUpgrade pocket} upgrade.
|
|
||||||
* <p>
|
|
||||||
* Turtle and pocket computer upgrades are registered using Minecraft's dynamic registry system. As a result, they
|
|
||||||
* follow a similar design to other dynamic content, such as {@linkplain Recipe recipes} or {@link LootItemFunction
|
|
||||||
* loot functions}.
|
|
||||||
* <p>
|
|
||||||
* First, one adds a new class implementing {@link ITurtleUpgrade} or {@link IPocketUpgrade}). This is responsible for
|
|
||||||
* handling all the logic of your upgrade.
|
|
||||||
* <p>
|
|
||||||
* However, the upgrades are not registered directly. Instead, each upgrade class should have a corresponding
|
|
||||||
* {@link UpgradeType}, which is responsible for loading the upgrade from a datapack. The upgrade type should then be
|
|
||||||
* registered in its appropriate registry ({@link ITurtleUpgrade#typeRegistry()},
|
|
||||||
* {@link IPocketUpgrade#typeRegistry()}).
|
|
||||||
* <p>
|
|
||||||
* In order to register the actual upgrade, a JSON file referencing your upgrade type should be added to a datapack. It
|
|
||||||
* is recommended to do this via the data generators.
|
|
||||||
*
|
|
||||||
* <h2 id="datagen">Data Generation</h2>
|
|
||||||
* As turtle and pocket upgrades are just loaded using vanilla's dynamic loaders, one may use the same data generation
|
|
||||||
* tools as you would for any other dynamic registry.
|
|
||||||
* <p>
|
|
||||||
* This can typically be done by extending vanilla's built-in registries using {@link RegistryPatchGenerator}, and then
|
|
||||||
* writing out the new registries using {@code net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider}
|
|
||||||
* on Fabric or {@code net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider} on Forge.
|
|
||||||
* <p>
|
|
||||||
* {@snippet lang="java" :
|
|
||||||
* import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
|
||||||
* import net.minecraft.Util;
|
|
||||||
* import net.minecraft.core.HolderLookup;
|
|
||||||
* import net.minecraft.core.RegistrySetBuilder;
|
|
||||||
* import net.minecraft.data.DataGenerator;
|
|
||||||
* import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider;
|
|
||||||
*
|
|
||||||
* import java.util.concurrent.CompletableFuture;
|
|
||||||
*
|
|
||||||
* public void generate(DataGenerator.PackGenerator output, CompletableFuture<HolderLookup.Provider> registries) {
|
|
||||||
* var newRegistries = RegistryPatchGenerator.createLookup(registries, Util.make(new RegistrySetBuilder(), builder -> {
|
|
||||||
* builder.add(ITurtleUpgrade.REGISTRY, upgrades -> {
|
|
||||||
* upgrades.register(ITurtleUpgrade.createKey(ResourceLocation.fromNamespaceAndPath("my_mod", "my_upgrade")), new MyUpgrade());
|
|
||||||
* });
|
|
||||||
* }));
|
|
||||||
* output.addProvider(o -> new DatapackBuiltinEntriesProvider(o, newRegistries, Set.of("my_mod")));
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @param <T> The upgrade subclass that this upgrade type represents.
|
|
||||||
* @see ITurtleUpgrade
|
|
||||||
* @see IPocketUpgrade
|
|
||||||
*/
|
|
||||||
public interface UpgradeType<T extends UpgradeBase> {
|
|
||||||
/**
|
|
||||||
* The codec to read and write this upgrade from a datapack.
|
|
||||||
*
|
|
||||||
* @return The codec for this upgrade.
|
|
||||||
*/
|
|
||||||
MapCodec<T> codec();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new upgrade type.
|
|
||||||
*
|
|
||||||
* @param codec The codec
|
|
||||||
* @param <T> The type of the generated upgrade.
|
|
||||||
* @return The newly created upgrade type.
|
|
||||||
*/
|
|
||||||
static <T extends UpgradeBase> UpgradeType<T> create(MapCodec<T> codec) {
|
|
||||||
return new UpgradeTypeImpl<>(codec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an upgrade type for an upgrade that takes no arguments.
|
|
||||||
* <p>
|
|
||||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(Function)} instead.
|
|
||||||
*
|
|
||||||
* @param instance Generate a new upgrade with a specific ID.
|
|
||||||
* @param <T> The type of the generated upgrade.
|
|
||||||
* @return A new upgrade type.
|
|
||||||
*/
|
|
||||||
static <T extends UpgradeBase> UpgradeType<T> simple(T instance) {
|
|
||||||
return create(MapCodec.unit(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an upgrade type for a simple upgrade whose crafting item can be specified.
|
|
||||||
*
|
|
||||||
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
|
||||||
* {@link UpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
|
||||||
* @param <T> The type of the generated upgrade.
|
|
||||||
* @return A new upgrade type.
|
|
||||||
* @see #simple(UpgradeBase) For upgrades whose crafting stack should not vary.
|
|
||||||
*/
|
|
||||||
static <T extends UpgradeBase> UpgradeType<T> simpleWithCustomItem(Function<ItemStack, T> factory) {
|
|
||||||
return create(BuiltInRegistries.ITEM.byNameCodec()
|
|
||||||
.xmap(x -> factory.apply(new ItemStack(x)), x -> x.getCraftingItem().getItem())
|
|
||||||
.fieldOf("item"));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.impl;
|
package dan200.computercraft.impl;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.detail.BlockReference;
|
import dan200.computercraft.api.detail.BlockReference;
|
||||||
import dan200.computercraft.api.detail.DetailRegistry;
|
import dan200.computercraft.api.detail.DetailRegistry;
|
||||||
@@ -16,12 +15,10 @@ import dan200.computercraft.api.media.MediaProvider;
|
|||||||
import dan200.computercraft.api.network.PacketNetwork;
|
import dan200.computercraft.api.network.PacketNetwork;
|
||||||
import dan200.computercraft.api.network.wired.WiredElement;
|
import dan200.computercraft.api.network.wired.WiredElement;
|
||||||
import dan200.computercraft.api.network.wired.WiredNode;
|
import dan200.computercraft.api.network.wired.WiredNode;
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||||
import dan200.computercraft.api.redstone.BundledRedstoneProvider;
|
import dan200.computercraft.api.redstone.BundledRedstoneProvider;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
|
||||||
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeType;
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
import dan200.computercraft.impl.upgrades.TurtleToolSpec;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
@@ -70,15 +67,9 @@ public interface ComputerCraftAPIService {
|
|||||||
|
|
||||||
void registerRefuelHandler(TurtleRefuelHandler handler);
|
void registerRefuelHandler(TurtleRefuelHandler handler);
|
||||||
|
|
||||||
ResourceKey<Registry<UpgradeType<? extends ITurtleUpgrade>>> turtleUpgradeRegistryId();
|
ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> turtleUpgradeRegistryId();
|
||||||
|
|
||||||
Codec<ITurtleUpgrade> turtleUpgradeCodec();
|
ResourceKey<Registry<PocketUpgradeSerialiser<?>>> pocketUpgradeRegistryId();
|
||||||
|
|
||||||
ResourceKey<Registry<UpgradeType<? extends IPocketUpgrade>>> pocketUpgradeRegistryId();
|
|
||||||
|
|
||||||
ITurtleUpgrade createTurtleTool(TurtleToolSpec spec);
|
|
||||||
|
|
||||||
Codec<IPocketUpgrade> pocketUpgradeCodec();
|
|
||||||
|
|
||||||
DetailRegistry<ItemStack> getItemStackDetailRegistry();
|
DetailRegistry<ItemStack> getItemStackDetailRegistry();
|
||||||
|
|
||||||
|
@@ -0,0 +1,92 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.impl;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction layer for Forge and Fabric. See implementations for more details.
|
||||||
|
* <p>
|
||||||
|
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public interface PlatformHelper {
|
||||||
|
/**
|
||||||
|
* Get the current {@link PlatformHelper} instance.
|
||||||
|
*
|
||||||
|
* @return The current instance.
|
||||||
|
*/
|
||||||
|
static PlatformHelper get() {
|
||||||
|
var instance = Instance.INSTANCE;
|
||||||
|
return instance == null ? Services.raise(PlatformHelper.class, Instance.ERROR) : instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the unique ID for a registered object.
|
||||||
|
*
|
||||||
|
* @param registry The registry to look up this object in.
|
||||||
|
* @param object The object to look up.
|
||||||
|
* @param <T> The type of object the registry stores.
|
||||||
|
* @return The registered object's ID.
|
||||||
|
* @throws IllegalArgumentException If the registry or object are not registered.
|
||||||
|
*/
|
||||||
|
<T> ResourceLocation getRegistryKey(ResourceKey<Registry<T>> registry, T object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up an ID in a registry, returning the registered object.
|
||||||
|
*
|
||||||
|
* @param registry The registry to look up this object in.
|
||||||
|
* @param id The ID to look up.
|
||||||
|
* @param <T> The type of object the registry stores.
|
||||||
|
* @return The resolved registry object.
|
||||||
|
* @throws IllegalArgumentException If the registry or object are not registered.
|
||||||
|
*/
|
||||||
|
<T> T getRegistryObject(ResourceKey<Registry<T>> registry, ResourceLocation id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the subset of an {@link ItemStack}'s {@linkplain ItemStack#getTag() tag} which is synced to the client.
|
||||||
|
*
|
||||||
|
* @param item The stack.
|
||||||
|
* @return The item's tag.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default CompoundTag getShareTag(ItemStack item) {
|
||||||
|
return item.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a resource condition which requires a mod to be loaded. This should be used by data providers such as
|
||||||
|
* {@link UpgradeDataProvider}.
|
||||||
|
*
|
||||||
|
* @param object The JSON object we're generating.
|
||||||
|
* @param modId The mod ID that we require.
|
||||||
|
*/
|
||||||
|
void addRequiredModCondition(JsonObject object, String modId);
|
||||||
|
|
||||||
|
final class Instance {
|
||||||
|
static final @Nullable PlatformHelper INSTANCE;
|
||||||
|
static final @Nullable Throwable ERROR;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// We don't want class initialisation to fail here (as that results in confusing errors). Instead, capture
|
||||||
|
// the error and rethrow it when accessing. This should be JITted away in the common case.
|
||||||
|
var helper = Services.tryLoad(PlatformHelper.class);
|
||||||
|
INSTANCE = helper.instance();
|
||||||
|
ERROR = helper.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Instance() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,49 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.impl.upgrades;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.util.GsonHelper;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple serialiser which returns a constant upgrade with a custom crafting item.
|
||||||
|
* <p>
|
||||||
|
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||||
|
*
|
||||||
|
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public abstract class SerialiserWithCraftingItem<T extends UpgradeBase> implements UpgradeSerialiser<T> {
|
||||||
|
private final BiFunction<ResourceLocation, ItemStack, T> factory;
|
||||||
|
|
||||||
|
protected SerialiserWithCraftingItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final T fromJson(ResourceLocation id, JsonObject object) {
|
||||||
|
var item = GsonHelper.getAsItem(object, "item");
|
||||||
|
return factory.apply(id, new ItemStack(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final T fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||||
|
var item = buffer.readItem();
|
||||||
|
return factory.apply(id, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void toNetwork(FriendlyByteBuf buffer, T upgrade) {
|
||||||
|
buffer.writeItem(upgrade.getCraftingItem());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.impl.upgrades;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple serialiser which returns a constant upgrade.
|
||||||
|
* <p>
|
||||||
|
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||||
|
*
|
||||||
|
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public abstract class SimpleSerialiser<T extends UpgradeBase> implements UpgradeSerialiser<T> {
|
||||||
|
private final Function<ResourceLocation, T> constructor;
|
||||||
|
|
||||||
|
public SimpleSerialiser(Function<ResourceLocation, T> constructor) {
|
||||||
|
this.constructor = constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final T fromJson(ResourceLocation id, JsonObject object) {
|
||||||
|
return constructor.apply(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final T fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||||
|
return constructor.apply(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void toNetwork(FriendlyByteBuf buffer, T upgrade) {
|
||||||
|
}
|
||||||
|
}
|
@@ -1,49 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.impl.upgrades;
|
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
|
||||||
import com.mojang.serialization.MapCodec;
|
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|
||||||
import dan200.computercraft.api.turtle.TurtleToolDurability;
|
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
|
||||||
import net.minecraft.core.registries.Registries;
|
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.network.chat.ComponentSerialization;
|
|
||||||
import net.minecraft.tags.TagKey;
|
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The template for a turtle tool.
|
|
||||||
*
|
|
||||||
* @param adjective The adjective for this tool.
|
|
||||||
* @param item The tool used.
|
|
||||||
* @param damageMultiplier The damage multiplier for this tool.
|
|
||||||
* @param allowEnchantments Whether to allow enchantments.
|
|
||||||
* @param consumeDurability When to consume durability.
|
|
||||||
* @param breakable The items breakable by this tool.
|
|
||||||
*/
|
|
||||||
public record TurtleToolSpec(
|
|
||||||
Component adjective,
|
|
||||||
Item item,
|
|
||||||
float damageMultiplier,
|
|
||||||
boolean allowEnchantments,
|
|
||||||
TurtleToolDurability consumeDurability,
|
|
||||||
Optional<TagKey<Block>> breakable
|
|
||||||
) {
|
|
||||||
public static final float DEFAULT_DAMAGE_MULTIPLIER = 3.0f;
|
|
||||||
|
|
||||||
public static final MapCodec<TurtleToolSpec> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
|
||||||
ComponentSerialization.CODEC.fieldOf("adjective").forGetter(TurtleToolSpec::adjective),
|
|
||||||
BuiltInRegistries.ITEM.byNameCodec().fieldOf("item").forGetter(TurtleToolSpec::item),
|
|
||||||
Codec.FLOAT.optionalFieldOf("damageMultiplier", DEFAULT_DAMAGE_MULTIPLIER).forGetter(TurtleToolSpec::damageMultiplier),
|
|
||||||
Codec.BOOL.optionalFieldOf("allowEnchantments", false).forGetter(TurtleToolSpec::allowEnchantments),
|
|
||||||
TurtleToolDurability.CODEC.optionalFieldOf("consumeDurability", TurtleToolDurability.NEVER).forGetter(TurtleToolSpec::consumeDurability),
|
|
||||||
TagKey.codec(Registries.BLOCK).optionalFieldOf("breakable").forGetter(TurtleToolSpec::breakable)
|
|
||||||
).apply(instance, TurtleToolSpec::new));
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.impl.upgrades;
|
|
||||||
|
|
||||||
import com.mojang.serialization.MapCodec;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeType;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple implementation of {@link UpgradeType}.
|
|
||||||
*
|
|
||||||
* @param codec The codec to read/write upgrades with.
|
|
||||||
* @param <T> The upgrade subclass that this upgrade type represents.
|
|
||||||
*/
|
|
||||||
@ApiStatus.Internal
|
|
||||||
public record UpgradeTypeImpl<T extends UpgradeBase>(MapCodec<T> codec) implements UpgradeType<T> {
|
|
||||||
}
|
|
@@ -29,7 +29,7 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://maven.neoforged.net/") {
|
maven("https://maven.minecraftforge.net/") {
|
||||||
content {
|
content {
|
||||||
includeModule("org.spongepowered", "mixin")
|
includeModule("org.spongepowered", "mixin")
|
||||||
}
|
}
|
||||||
@@ -38,13 +38,12 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Pull in our other projects. See comments in MinecraftConfigurations on this nastiness.
|
// Pull in our other projects. See comments in MinecraftConfigurations on this nastiness.
|
||||||
implementation(project(":core"))
|
api(project(":core"))
|
||||||
implementation(commonClasses(project(":common-api")))
|
api(commonClasses(project(":common-api")))
|
||||||
clientImplementation(clientClasses(project(":common-api")))
|
clientApi(clientClasses(project(":common-api")))
|
||||||
|
|
||||||
compileOnly(libs.mixin)
|
|
||||||
compileOnly(libs.mixinExtra)
|
|
||||||
compileOnly(libs.bundles.externalMods.common)
|
compileOnly(libs.bundles.externalMods.common)
|
||||||
|
compileOnly(variantOf(libs.create.forge) { classifier("slim") }) { isTransitive = false }
|
||||||
clientCompileOnly(variantOf(libs.emi) { classifier("api") })
|
clientCompileOnly(variantOf(libs.emi) { classifier("api") })
|
||||||
|
|
||||||
annotationProcessorEverywhere(libs.autoService)
|
annotationProcessorEverywhere(libs.autoService)
|
||||||
|
@@ -64,6 +64,9 @@ public final class ClientHooks {
|
|||||||
public static void onWorldUnload() {
|
public static void onWorldUnload() {
|
||||||
MonitorRenderState.destroyAll();
|
MonitorRenderState.destroyAll();
|
||||||
SpeakerManager.reset();
|
SpeakerManager.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onDisconnect() {
|
||||||
ClientPocketComputers.reset();
|
ClientPocketComputers.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +111,7 @@ public final class ClientHooks {
|
|||||||
*/
|
*/
|
||||||
public static void addBlockDebugInfo(Consumer<String> addText) {
|
public static void addBlockDebugInfo(Consumer<String> addText) {
|
||||||
var minecraft = Minecraft.getInstance();
|
var minecraft = Minecraft.getInstance();
|
||||||
if (!minecraft.getDebugOverlay().showDebugScreen() || minecraft.level == null) return;
|
if (!minecraft.options.renderDebug || minecraft.level == null) return;
|
||||||
if (minecraft.hitResult == null || minecraft.hitResult.getType() != HitResult.Type.BLOCK) return;
|
if (minecraft.hitResult == null || minecraft.hitResult.getType() != HitResult.Type.BLOCK) return;
|
||||||
|
|
||||||
var tile = minecraft.level.getBlockEntity(((BlockHitResult) minecraft.hitResult).getBlockPos());
|
var tile = minecraft.level.getBlockEntity(((BlockHitResult) minecraft.hitResult).getBlockPos());
|
||||||
@@ -128,8 +131,8 @@ public final class ClientHooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void addTurtleUpgrade(Consumer<String> out, TurtleBlockEntity turtle, TurtleSide side) {
|
private static void addTurtleUpgrade(Consumer<String> out, TurtleBlockEntity turtle, TurtleSide side) {
|
||||||
var upgrade = turtle.getAccess().getUpgradeWithData(side);
|
var upgrade = turtle.getUpgrade(side);
|
||||||
if (upgrade != null) out.accept(String.format("Upgrade[%s]: %s", side, upgrade.holder().key().location()));
|
if (upgrade != null) out.accept(String.format("Upgrade[%s]: %s", side, upgrade.getUpgradeID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -138,7 +141,7 @@ public final class ClientHooks {
|
|||||||
* @param addText A callback which adds a single line of text.
|
* @param addText A callback which adds a single line of text.
|
||||||
*/
|
*/
|
||||||
public static void addGameDebugInfo(Consumer<String> addText) {
|
public static void addGameDebugInfo(Consumer<String> addText) {
|
||||||
if (MonitorBlockEntityRenderer.hasRenderedThisFrame() && Minecraft.getInstance().getDebugOverlay().showDebugScreen()) {
|
if (MonitorBlockEntityRenderer.hasRenderedThisFrame() && Minecraft.getInstance().options.renderDebug) {
|
||||||
addText.accept("[CC:T] Monitor renderer: " + MonitorBlockEntityRenderer.currentRenderer());
|
addText.accept("[CC:T] Monitor renderer: " + MonitorBlockEntityRenderer.currentRenderer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ import dan200.computercraft.api.client.turtle.RegisterTurtleUpgradeModeller;
|
|||||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||||
import dan200.computercraft.client.gui.*;
|
import dan200.computercraft.client.gui.*;
|
||||||
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
||||||
|
import dan200.computercraft.client.render.CustomLecternRenderer;
|
||||||
import dan200.computercraft.client.render.RenderTypes;
|
import dan200.computercraft.client.render.RenderTypes;
|
||||||
import dan200.computercraft.client.render.TurtleBlockEntityRenderer;
|
import dan200.computercraft.client.render.TurtleBlockEntityRenderer;
|
||||||
import dan200.computercraft.client.render.monitor.MonitorBlockEntityRenderer;
|
import dan200.computercraft.client.render.monitor.MonitorBlockEntityRenderer;
|
||||||
@@ -21,16 +22,16 @@ import dan200.computercraft.client.turtle.TurtleUpgradeModellers;
|
|||||||
import dan200.computercraft.core.util.Colour;
|
import dan200.computercraft.core.util.Colour;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||||
|
import dan200.computercraft.shared.common.IColouredItem;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||||
import dan200.computercraft.shared.media.items.DiskItem;
|
import dan200.computercraft.shared.media.items.DiskItem;
|
||||||
|
import dan200.computercraft.shared.media.items.TreasureDiskItem;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.client.Minecraft;
|
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.gui.screens.Screen;
|
|
||||||
import net.minecraft.client.gui.screens.inventory.MenuAccess;
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.renderer.ShaderInstance;
|
import net.minecraft.client.renderer.ShaderInstance;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||||
@@ -41,13 +42,9 @@ import net.minecraft.network.chat.Component;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
||||||
import net.minecraft.server.packs.resources.ResourceProvider;
|
import net.minecraft.server.packs.resources.ResourceProvider;
|
||||||
import net.minecraft.util.FastColor;
|
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
|
||||||
import net.minecraft.world.inventory.MenuType;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.component.DyedItemColor;
|
|
||||||
import net.minecraft.world.level.ItemLike;
|
import net.minecraft.world.level.ItemLike;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -77,6 +74,7 @@ public final class ClientRegistry {
|
|||||||
BlockEntityRenderers.register(ModRegistry.BlockEntities.MONITOR_ADVANCED.get(), MonitorBlockEntityRenderer::new);
|
BlockEntityRenderers.register(ModRegistry.BlockEntities.MONITOR_ADVANCED.get(), MonitorBlockEntityRenderer::new);
|
||||||
BlockEntityRenderers.register(ModRegistry.BlockEntities.TURTLE_NORMAL.get(), TurtleBlockEntityRenderer::new);
|
BlockEntityRenderers.register(ModRegistry.BlockEntities.TURTLE_NORMAL.get(), TurtleBlockEntityRenderer::new);
|
||||||
BlockEntityRenderers.register(ModRegistry.BlockEntities.TURTLE_ADVANCED.get(), TurtleBlockEntityRenderer::new);
|
BlockEntityRenderers.register(ModRegistry.BlockEntities.TURTLE_ADVANCED.get(), TurtleBlockEntityRenderer::new);
|
||||||
|
BlockEntityRenderers.register(ModRegistry.BlockEntities.LECTERN.get(), CustomLecternRenderer::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,6 +83,14 @@ public final class ClientRegistry {
|
|||||||
* @param itemProperties Callback to register item properties.
|
* @param itemProperties Callback to register item properties.
|
||||||
*/
|
*/
|
||||||
public static void registerMainThread(RegisterItemProperty itemProperties) {
|
public static void registerMainThread(RegisterItemProperty itemProperties) {
|
||||||
|
MenuScreens.<AbstractComputerMenu, ComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.COMPUTER.get(), ComputerScreen::new);
|
||||||
|
MenuScreens.<AbstractComputerMenu, NoTermComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.POCKET_COMPUTER_NO_TERM.get(), NoTermComputerScreen::new);
|
||||||
|
MenuScreens.register(ModRegistry.Menus.TURTLE.get(), TurtleScreen::new);
|
||||||
|
|
||||||
|
MenuScreens.register(ModRegistry.Menus.PRINTER.get(), PrinterScreen::new);
|
||||||
|
MenuScreens.register(ModRegistry.Menus.DISK_DRIVE.get(), DiskDriveScreen::new);
|
||||||
|
MenuScreens.register(ModRegistry.Menus.PRINTOUT.get(), PrintoutScreen::new);
|
||||||
|
|
||||||
registerItemProperty(itemProperties, "state",
|
registerItemProperty(itemProperties, "state",
|
||||||
new UnclampedPropertyFunction((stack, world, player, random) -> {
|
new UnclampedPropertyFunction((stack, world, player, random) -> {
|
||||||
var computer = ClientPocketComputers.get(stack);
|
var computer = ClientPocketComputers.get(stack);
|
||||||
@@ -93,41 +99,28 @@ public final class ClientRegistry {
|
|||||||
ModRegistry.Items.POCKET_COMPUTER_NORMAL, ModRegistry.Items.POCKET_COMPUTER_ADVANCED
|
ModRegistry.Items.POCKET_COMPUTER_NORMAL, ModRegistry.Items.POCKET_COMPUTER_ADVANCED
|
||||||
);
|
);
|
||||||
registerItemProperty(itemProperties, "coloured",
|
registerItemProperty(itemProperties, "coloured",
|
||||||
(stack, world, player, random) -> DyedItemColor.getOrDefault(stack, -1) != -1 ? 1 : 0,
|
(stack, world, player, random) -> IColouredItem.getColourBasic(stack) != -1 ? 1 : 0,
|
||||||
ModRegistry.Items.POCKET_COMPUTER_NORMAL, ModRegistry.Items.POCKET_COMPUTER_ADVANCED
|
ModRegistry.Items.POCKET_COMPUTER_NORMAL, ModRegistry.Items.POCKET_COMPUTER_ADVANCED
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerMenuScreens(RegisterMenuScreen register) {
|
|
||||||
register.<AbstractComputerMenu, ComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.COMPUTER.get(), ComputerScreen::new);
|
|
||||||
register.<AbstractComputerMenu, NoTermComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.POCKET_COMPUTER_NO_TERM.get(), NoTermComputerScreen::new);
|
|
||||||
register.register(ModRegistry.Menus.TURTLE.get(), TurtleScreen::new);
|
|
||||||
|
|
||||||
register.register(ModRegistry.Menus.PRINTER.get(), PrinterScreen::new);
|
|
||||||
register.register(ModRegistry.Menus.DISK_DRIVE.get(), DiskDriveScreen::new);
|
|
||||||
register.register(ModRegistry.Menus.PRINTOUT.get(), PrintoutScreen::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface RegisterMenuScreen {
|
|
||||||
<M extends AbstractContainerMenu, U extends Screen & MenuAccess<M>> void register(MenuType<? extends M> type, MenuScreens.ScreenConstructor<M, U> factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void registerTurtleModellers(RegisterTurtleUpgradeModeller register) {
|
public static void registerTurtleModellers(RegisterTurtleUpgradeModeller register) {
|
||||||
register.register(ModRegistry.TurtleUpgradeTypes.SPEAKER.get(), TurtleUpgradeModeller.sided(
|
register.register(ModRegistry.TurtleSerialisers.SPEAKER.get(), TurtleUpgradeModeller.sided(
|
||||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_left"),
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_left"),
|
||||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_right")
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_right")
|
||||||
));
|
));
|
||||||
register.register(ModRegistry.TurtleUpgradeTypes.WORKBENCH.get(), TurtleUpgradeModeller.sided(
|
register.register(ModRegistry.TurtleSerialisers.WORKBENCH.get(), TurtleUpgradeModeller.sided(
|
||||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_crafting_table_left"),
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_crafting_table_left"),
|
||||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_crafting_table_right")
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_crafting_table_right")
|
||||||
));
|
));
|
||||||
register.register(ModRegistry.TurtleUpgradeTypes.WIRELESS_MODEM.get(), new TurtleModemModeller());
|
register.register(ModRegistry.TurtleSerialisers.WIRELESS_MODEM_NORMAL.get(), new TurtleModemModeller(false));
|
||||||
register.register(ModRegistry.TurtleUpgradeTypes.TOOL.get(), TurtleUpgradeModeller.flatItem());
|
register.register(ModRegistry.TurtleSerialisers.WIRELESS_MODEM_ADVANCED.get(), new TurtleModemModeller(true));
|
||||||
|
register.register(ModRegistry.TurtleSerialisers.TOOL.get(), TurtleUpgradeModeller.flatItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
private static void registerItemProperty(RegisterItemProperty itemProperties, String name, ClampedItemPropertyFunction getter, Supplier<? extends Item>... items) {
|
private static void registerItemProperty(RegisterItemProperty itemProperties, String name, ClampedItemPropertyFunction getter, Supplier<? extends Item>... items) {
|
||||||
var id = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name);
|
var id = new ResourceLocation(ComputerCraftAPI.MOD_ID, name);
|
||||||
for (var item : items) itemProperties.register(item.get(), id, getter);
|
for (var item : items) itemProperties.register(item.get(), id, getter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,18 +144,18 @@ public final class ClientRegistry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static void registerExtraModels(Consumer<ResourceLocation> register) {
|
public static void registerExtraModels(Consumer<ResourceLocation> register) {
|
||||||
for (var model : EXTRA_MODELS) register.accept(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, model));
|
for (var model : EXTRA_MODELS) register.accept(new ResourceLocation(ComputerCraftAPI.MOD_ID, model));
|
||||||
TurtleUpgradeModellers.getDependencies().forEach(register);
|
TurtleUpgradeModellers.getDependencies().forEach(register);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerItemColours(BiConsumer<ItemColor, ItemLike> register) {
|
public static void registerItemColours(BiConsumer<ItemColor, ItemLike> register) {
|
||||||
register.accept(
|
register.accept(
|
||||||
(stack, layer) -> layer == 1 ? DiskItem.getColour(stack) : -1,
|
(stack, layer) -> layer == 1 ? ((DiskItem) stack.getItem()).getColour(stack) : 0xFFFFFF,
|
||||||
ModRegistry.Items.DISK.get()
|
ModRegistry.Items.DISK.get()
|
||||||
);
|
);
|
||||||
|
|
||||||
register.accept(
|
register.accept(
|
||||||
(stack, layer) -> layer == 1 ? DyedItemColor.getOrDefault(stack, Colour.BLUE.getARGB()) : -1,
|
(stack, layer) -> layer == 1 ? TreasureDiskItem.getColour(stack) : 0xFFFFFF,
|
||||||
ModRegistry.Items.TREASURE_DISK.get()
|
ModRegistry.Items.TREASURE_DISK.get()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -175,17 +168,17 @@ public final class ClientRegistry {
|
|||||||
|
|
||||||
private static int getPocketColour(ItemStack stack, int layer) {
|
private static int getPocketColour(ItemStack stack, int layer) {
|
||||||
return switch (layer) {
|
return switch (layer) {
|
||||||
default -> -1;
|
default -> 0xFFFFFF;
|
||||||
case 1 -> DyedItemColor.getOrDefault(stack, -1); // Frame colour
|
case 1 -> IColouredItem.getColourBasic(stack); // Frame colour
|
||||||
case 2 -> { // Light colour
|
case 2 -> { // Light colour
|
||||||
var computer = ClientPocketComputers.get(stack);
|
var computer = ClientPocketComputers.get(stack);
|
||||||
yield computer == null || computer.getLightState() == -1 ? Colour.BLACK.getARGB() : FastColor.ARGB32.opaque(computer.getLightState());
|
yield computer == null || computer.getLightState() == -1 ? Colour.BLACK.getHex() : computer.getLightState();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getTurtleColour(ItemStack stack, int layer) {
|
private static int getTurtleColour(ItemStack stack, int layer) {
|
||||||
return layer == 0 ? DyedItemColor.getOrDefault(stack, -1) : -1;
|
return layer == 0 ? ((IColouredItem) stack.getItem()).getColour(stack) : 0xFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerShaders(ResourceProvider resources, BiConsumer<ShaderInstance, Consumer<ShaderInstance>> load) throws IOException {
|
public static void registerShaders(ResourceProvider resources, BiConsumer<ShaderInstance, Consumer<ShaderInstance>> load) throws IOException {
|
||||||
|
@@ -75,7 +75,7 @@ public class ClientTableFormatter implements TableFormatter {
|
|||||||
|
|
||||||
var tag = createTag(table.getId());
|
var tag = createTag(table.getId());
|
||||||
if (chat.allMessages.removeIf(guiMessage -> guiMessage.tag() != null && Objects.equals(guiMessage.tag().logTag(), tag.logTag()))) {
|
if (chat.allMessages.removeIf(guiMessage -> guiMessage.tag() != null && Objects.equals(guiMessage.tag().logTag(), tag.logTag()))) {
|
||||||
chat.rescaleChat();
|
chat.refreshTrimmedMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
TableFormatter.super.display(table);
|
TableFormatter.super.display(table);
|
||||||
|
@@ -0,0 +1,20 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.client;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
|
import dan200.computercraft.client.turtle.TurtleUpgradeModellers;
|
||||||
|
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
||||||
|
|
||||||
|
@AutoService(ComputerCraftAPIClientService.class)
|
||||||
|
public final class ComputerCraftAPIClientImpl implements ComputerCraftAPIClientService {
|
||||||
|
@Override
|
||||||
|
public <T extends ITurtleUpgrade> void registerTurtleUpgradeModeller(TurtleUpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller) {
|
||||||
|
TurtleUpgradeModellers.register(serialiser, modeller);
|
||||||
|
}
|
||||||
|
}
|
@@ -127,6 +127,7 @@ public abstract class AbstractComputerScreen<T extends AbstractComputerMenu> ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
renderBackground(graphics);
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(graphics, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@ import net.minecraft.world.entity.player.Inventory;
|
|||||||
* The GUI for disk drives.
|
* The GUI for disk drives.
|
||||||
*/
|
*/
|
||||||
public class DiskDriveScreen extends AbstractContainerScreen<DiskDriveMenu> {
|
public class DiskDriveScreen extends AbstractContainerScreen<DiskDriveMenu> {
|
||||||
private static final ResourceLocation BACKGROUND = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/disk_drive.png");
|
private static final ResourceLocation BACKGROUND = new ResourceLocation("computercraft", "textures/gui/disk_drive.png");
|
||||||
|
|
||||||
public DiskDriveScreen(DiskDriveMenu container, Inventory player, Component title) {
|
public DiskDriveScreen(DiskDriveMenu container, Inventory player, Component title) {
|
||||||
super(container, player, title);
|
super(container, player, title);
|
||||||
@@ -28,6 +28,7 @@ public class DiskDriveScreen extends AbstractContainerScreen<DiskDriveMenu> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
renderBackground(graphics);
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(graphics, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ import java.util.stream.Stream;
|
|||||||
* Sprite sheet for all GUI texutres in the mod.
|
* Sprite sheet for all GUI texutres in the mod.
|
||||||
*/
|
*/
|
||||||
public final class GuiSprites extends TextureAtlasHolder {
|
public final class GuiSprites extends TextureAtlasHolder {
|
||||||
public static final ResourceLocation SPRITE_SHEET = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui");
|
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 ResourceLocation TEXTURE = SPRITE_SHEET.withPath(x -> "textures/atlas/" + x + ".png");
|
||||||
|
|
||||||
public static final ButtonTextures TURNED_OFF = button("turned_off");
|
public static final ButtonTextures TURNED_OFF = button("turned_off");
|
||||||
@@ -35,16 +35,16 @@ public final class GuiSprites extends TextureAtlasHolder {
|
|||||||
|
|
||||||
private static ButtonTextures button(String name) {
|
private static ButtonTextures button(String name) {
|
||||||
return new ButtonTextures(
|
return new ButtonTextures(
|
||||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name),
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name),
|
||||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name + "_hover")
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name + "_hover")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ComputerTextures computer(String name, boolean pocket, boolean sidebar) {
|
private static ComputerTextures computer(String name, boolean pocket, boolean sidebar) {
|
||||||
return new ComputerTextures(
|
return new ComputerTextures(
|
||||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/border_" + name),
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/border_" + name),
|
||||||
pocket ? ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/pocket_bottom_" + name) : null,
|
pocket ? new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/pocket_bottom_" + name) : null,
|
||||||
sidebar ? ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/sidebar_" + name) : null
|
sidebar ? new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/sidebar_" + name) : null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,7 +9,6 @@ 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;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.util.FormattedCharSequence;
|
import net.minecraft.util.FormattedCharSequence;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
@@ -19,7 +18,6 @@ import java.util.List;
|
|||||||
* A {@link Toast} implementation which displays an arbitrary message along with an optional {@link ItemStack}.
|
* A {@link Toast} implementation which displays an arbitrary message along with an optional {@link ItemStack}.
|
||||||
*/
|
*/
|
||||||
public class ItemToast implements Toast {
|
public class ItemToast implements Toast {
|
||||||
private static final ResourceLocation TEXTURE = ResourceLocation.withDefaultNamespace("toast/recipe");
|
|
||||||
public static final Object TRANSFER_NO_RESPONSE_TOKEN = new Object();
|
public static final Object TRANSFER_NO_RESPONSE_TOKEN = new Object();
|
||||||
|
|
||||||
private static final long DISPLAY_TIME = 7000L;
|
private static final long DISPLAY_TIME = 7000L;
|
||||||
@@ -81,7 +79,7 @@ public class ItemToast implements Toast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (width == 160 && message.size() <= 1) {
|
if (width == 160 && message.size() <= 1) {
|
||||||
graphics.blitSprite(TEXTURE, 0, 0, width, height());
|
graphics.blit(TEXTURE, 0, 0, 0, 64, width, height());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
var height = height();
|
var height = height();
|
||||||
@@ -111,14 +109,14 @@ public class ItemToast implements Toast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void renderBackgroundRow(GuiGraphics graphics, int x, int u, int y, int height) {
|
private static void renderBackgroundRow(GuiGraphics graphics, int x, int u, int y, int height) {
|
||||||
var leftOffset = u == 0 ? 20 : 5;
|
var leftOffset = 5;
|
||||||
var rightOffset = Math.min(60, x - leftOffset);
|
var rightOffset = Math.min(60, x - leftOffset);
|
||||||
|
|
||||||
graphics.blitSprite(TEXTURE, 160, 32, 0, u, 0, y, 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) {
|
||||||
graphics.blitSprite(TEXTURE, 160, 32, 32, u, k, y, Math.min(64, x - k - rightOffset), height);
|
graphics.blit(TEXTURE, k, y, 32, 32 + u, Math.min(64, x - k - rightOffset), height);
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics.blitSprite(TEXTURE, 160, 32, 160 - rightOffset, u, x - rightOffset, y, rightOffset, height);
|
graphics.blit(TEXTURE, x - rightOffset, y, 160 - rightOffset, 32 + u, rightOffset, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -66,9 +66,9 @@ public class NoTermComputerScreen<T extends AbstractComputerMenu> extends Screen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
|
public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) {
|
||||||
Objects.requireNonNull(minecraft().player).getInventory().swapPaint(scrollY);
|
Objects.requireNonNull(minecraft().player).getInventory().swapPaint(pDelta);
|
||||||
return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY);
|
return super.mouseScrolled(pMouseX, pMouseY, pDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -105,11 +105,6 @@ public class NoTermComputerScreen<T extends AbstractComputerMenu> extends Screen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
|
||||||
// Skip rendering the background.
|
|
||||||
}
|
|
||||||
|
|
||||||
private Minecraft minecraft() {
|
private Minecraft minecraft() {
|
||||||
return Nullability.assertNonNull(minecraft);
|
return Nullability.assertNonNull(minecraft);
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@ import static dan200.computercraft.core.util.Nullability.assertNonNull;
|
|||||||
* When closed, it returns to the previous screen.
|
* When closed, it returns to the previous screen.
|
||||||
*/
|
*/
|
||||||
public final class OptionScreen extends Screen {
|
public final class OptionScreen extends Screen {
|
||||||
private static final ResourceLocation BACKGROUND = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/blank_screen.png");
|
private static final ResourceLocation BACKGROUND = new ResourceLocation("computercraft", "textures/gui/blank_screen.png");
|
||||||
|
|
||||||
public static final int BUTTON_WIDTH = 100;
|
public static final int BUTTON_WIDTH = 100;
|
||||||
public static final int BUTTON_HEIGHT = 20;
|
public static final int BUTTON_HEIGHT = 20;
|
||||||
@@ -86,6 +86,8 @@ public final class OptionScreen extends Screen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
renderBackground(graphics);
|
||||||
|
|
||||||
// Render the actual texture.
|
// Render the actual texture.
|
||||||
graphics.blit(BACKGROUND, x, y, 0, 0, innerWidth, PADDING);
|
graphics.blit(BACKGROUND, x, y, 0, 0, innerWidth, PADDING);
|
||||||
graphics.blit(BACKGROUND,
|
graphics.blit(BACKGROUND,
|
||||||
|
@@ -15,7 +15,7 @@ import net.minecraft.world.entity.player.Inventory;
|
|||||||
* The GUI for printers.
|
* The GUI for printers.
|
||||||
*/
|
*/
|
||||||
public class PrinterScreen extends AbstractContainerScreen<PrinterMenu> {
|
public class PrinterScreen extends AbstractContainerScreen<PrinterMenu> {
|
||||||
private static final ResourceLocation BACKGROUND = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/printer.png");
|
private static final ResourceLocation BACKGROUND = new ResourceLocation("computercraft", "textures/gui/printer.png");
|
||||||
|
|
||||||
public PrinterScreen(PrinterMenu container, Inventory player, Component title) {
|
public PrinterScreen(PrinterMenu container, Inventory player, Component title) {
|
||||||
super(container, player, title);
|
super(container, player, title);
|
||||||
@@ -30,6 +30,7 @@ public class PrinterScreen extends AbstractContainerScreen<PrinterMenu> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
renderBackground(graphics);
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(graphics, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
@@ -4,17 +4,24 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.Tesselator;
|
||||||
import dan200.computercraft.core.terminal.TextBuffer;
|
import dan200.computercraft.core.terminal.TextBuffer;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.common.HeldItemMenu;
|
import dan200.computercraft.shared.media.PrintoutMenu;
|
||||||
import dan200.computercraft.shared.media.items.PrintoutData;
|
|
||||||
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.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.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
import net.minecraft.world.inventory.ContainerListener;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import static dan200.computercraft.client.render.PrintoutRenderer.*;
|
import static dan200.computercraft.client.render.PrintoutRenderer.*;
|
||||||
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
|
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
|
||||||
|
|
||||||
@@ -23,41 +30,75 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA
|
|||||||
*
|
*
|
||||||
* @see dan200.computercraft.client.render.PrintoutRenderer
|
* @see dan200.computercraft.client.render.PrintoutRenderer
|
||||||
*/
|
*/
|
||||||
public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
|
public final class PrintoutScreen extends AbstractContainerScreen<PrintoutMenu> implements ContainerListener {
|
||||||
private final boolean book;
|
private PrintoutInfo printout = PrintoutInfo.DEFAULT;
|
||||||
private final int pages;
|
private int page = 0;
|
||||||
private final TextBuffer[] text;
|
|
||||||
private final TextBuffer[] colours;
|
|
||||||
private int page;
|
|
||||||
|
|
||||||
public PrintoutScreen(HeldItemMenu container, Inventory player, Component title) {
|
public PrintoutScreen(PrintoutMenu container, Inventory player, Component title) {
|
||||||
super(container, player, title);
|
super(container, player, title);
|
||||||
|
|
||||||
imageHeight = Y_SIZE;
|
imageHeight = Y_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
var printout = container.getStack().getOrDefault(ModRegistry.DataComponents.PRINTOUT.get(), PrintoutData.EMPTY);
|
private void setPrintout(ItemStack stack) {
|
||||||
this.text = new TextBuffer[printout.lines().size()];
|
var text = PrintoutItem.getText(stack);
|
||||||
this.colours = new TextBuffer[printout.lines().size()];
|
var textBuffers = new TextBuffer[text.length];
|
||||||
for (var i = 0; i < this.text.length; i++) {
|
for (var i = 0; i < textBuffers.length; i++) textBuffers[i] = new TextBuffer(text[i]);
|
||||||
var line = printout.lines().get(i);
|
|
||||||
this.text[i] = new TextBuffer(line.text());
|
|
||||||
this.colours[i] = new TextBuffer(line.foreground());
|
|
||||||
}
|
|
||||||
|
|
||||||
page = 0;
|
var colours = PrintoutItem.getColours(stack);
|
||||||
pages = Math.max(this.text.length / PrintoutData.LINES_PER_PAGE, 1);
|
var colourBuffers = new TextBuffer[colours.length];
|
||||||
book = ((PrintoutItem) container.getStack().getItem()).getType() == PrintoutItem.Type.BOOK;
|
for (var i = 0; i < colours.length; i++) colourBuffers[i] = new TextBuffer(colours[i]);
|
||||||
|
|
||||||
|
var pages = Math.max(text.length / PrintoutItem.LINES_PER_PAGE, 1);
|
||||||
|
var book = stack.is(ModRegistry.Items.PRINTED_BOOK.get());
|
||||||
|
|
||||||
|
printout = new PrintoutInfo(pages, book, textBuffers, colourBuffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
menu.addSlotListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed() {
|
||||||
|
menu.removeSlotListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void slotChanged(AbstractContainerMenu menu, int slot, ItemStack stack) {
|
||||||
|
if (slot == 0) setPrintout(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dataChanged(AbstractContainerMenu menu, int slot, int data) {
|
||||||
|
if (slot == PrintoutMenu.DATA_CURRENT_PAGE) page = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPage(int page) {
|
||||||
|
this.page = page;
|
||||||
|
|
||||||
|
var gameMode = Objects.requireNonNull(Objects.requireNonNull(minecraft).gameMode);
|
||||||
|
gameMode.handleInventoryButtonClick(menu.containerId, PrintoutMenu.PAGE_BUTTON_OFFSET + page);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void previousPage() {
|
||||||
|
if (page > 0) setPage(page - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void nextPage() {
|
||||||
|
if (page < printout.pages() - 1) setPage(page + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean keyPressed(int key, int scancode, int modifiers) {
|
public boolean keyPressed(int key, int scancode, int modifiers) {
|
||||||
if (key == GLFW.GLFW_KEY_RIGHT) {
|
if (key == GLFW.GLFW_KEY_RIGHT) {
|
||||||
if (page < pages - 1) page++;
|
nextPage();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW.GLFW_KEY_LEFT) {
|
if (key == GLFW.GLFW_KEY_LEFT) {
|
||||||
if (page > 0) page--;
|
previousPage();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,17 +106,17 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled(double x, double y, double deltaX, double deltaY) {
|
public boolean mouseScrolled(double x, double y, double delta) {
|
||||||
if (super.mouseScrolled(x, y, deltaX, deltaY)) return true;
|
if (super.mouseScrolled(x, y, delta)) return true;
|
||||||
if (deltaY < 0) {
|
if (delta < 0) {
|
||||||
// Scroll up goes to the next page
|
// Scroll up goes to the next page
|
||||||
if (page < pages - 1) page++;
|
nextPage();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deltaY > 0) {
|
if (delta > 0) {
|
||||||
// Scroll down goes to the previous page
|
// Scroll down goes to the previous page
|
||||||
if (page > 0) page--;
|
previousPage();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,18 +125,41 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
||||||
// Push the printout slightly forward, to avoid clipping into the background.
|
// Draw the printout
|
||||||
|
var renderer = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
||||||
|
|
||||||
|
drawBorder(graphics.pose(), renderer, leftPos, topPos, 0, page, printout.pages(), printout.book(), FULL_BRIGHT_LIGHTMAP);
|
||||||
|
drawText(graphics.pose(), renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutItem.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, printout.text(), printout.colour());
|
||||||
|
renderer.endBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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.
|
||||||
graphics.pose().pushPose();
|
graphics.pose().pushPose();
|
||||||
graphics.pose().translate(0, 0, 1);
|
graphics.pose().translate(0, 0, -1);
|
||||||
|
renderBackground(graphics);
|
||||||
drawBorder(graphics.pose(), graphics.bufferSource(), leftPos, topPos, 0, page, pages, book, FULL_BRIGHT_LIGHTMAP);
|
|
||||||
drawText(graphics.pose(), graphics.bufferSource(), leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutData.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours);
|
|
||||||
|
|
||||||
graphics.pose().popPose();
|
graphics.pose().popPose();
|
||||||
|
|
||||||
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
|
protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
|
||||||
// Skip rendering labels.
|
// Skip rendering labels.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record PrintoutInfo(int pages, boolean book, TextBuffer[] text, TextBuffer[] colour) {
|
||||||
|
public static final PrintoutInfo DEFAULT;
|
||||||
|
|
||||||
|
static {
|
||||||
|
var textLines = new TextBuffer[PrintoutItem.LINES_PER_PAGE];
|
||||||
|
Arrays.fill(textLines, new TextBuffer(" ".repeat(PrintoutItem.LINE_MAX_LENGTH)));
|
||||||
|
|
||||||
|
var colourLines = new TextBuffer[PrintoutItem.LINES_PER_PAGE];
|
||||||
|
Arrays.fill(colourLines, new TextBuffer("f".repeat(PrintoutItem.LINE_MAX_LENGTH)));
|
||||||
|
|
||||||
|
DEFAULT = new PrintoutInfo(1, false, textLines, colourLines);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,8 +23,8 @@ import static dan200.computercraft.shared.turtle.inventory.TurtleMenu.*;
|
|||||||
* The GUI for turtles.
|
* The GUI for turtles.
|
||||||
*/
|
*/
|
||||||
public class TurtleScreen extends AbstractComputerScreen<TurtleMenu> {
|
public class TurtleScreen extends AbstractComputerScreen<TurtleMenu> {
|
||||||
private static final ResourceLocation BACKGROUND_NORMAL = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_normal.png");
|
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_normal.png");
|
||||||
private static final ResourceLocation BACKGROUND_ADVANCED = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_advanced.png");
|
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_advanced.png");
|
||||||
|
|
||||||
private static final int TEX_WIDTH = 278;
|
private static final int TEX_WIDTH = 278;
|
||||||
private static final int TEX_HEIGHT = 217;
|
private static final int TEX_HEIGHT = 217;
|
||||||
|
@@ -43,10 +43,6 @@ public class DynamicImageButton extends Button {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
var message = this.message.get();
|
|
||||||
setMessage(message.message());
|
|
||||||
setTooltip(message.tooltip());
|
|
||||||
|
|
||||||
var texture = this.texture.get(isHoveredOrFocused());
|
var texture = this.texture.get(isHoveredOrFocused());
|
||||||
|
|
||||||
RenderSystem.disableDepthTest();
|
RenderSystem.disableDepthTest();
|
||||||
@@ -54,6 +50,14 @@ public class DynamicImageButton extends Button {
|
|||||||
RenderSystem.enableDepthTest();
|
RenderSystem.enableDepthTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
var message = this.message.get();
|
||||||
|
setMessage(message.message());
|
||||||
|
setTooltip(message.tooltip());
|
||||||
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
|
}
|
||||||
|
|
||||||
public record HintedMessage(Component message, Tooltip tooltip) {
|
public record HintedMessage(Component message, Tooltip tooltip) {
|
||||||
public HintedMessage(Component message, @Nullable Component hint) {
|
public HintedMessage(Component message, @Nullable Component hint) {
|
||||||
this(
|
this(
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui.widgets;
|
package dan200.computercraft.client.gui.widgets;
|
||||||
|
|
||||||
|
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;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
@@ -15,6 +16,7 @@ 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;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
@@ -193,16 +195,16 @@ public class TerminalWidget extends AbstractWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled(double mouseX, double mouseY, double deltaX, double deltaY) {
|
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
||||||
if (!inTermRegion(mouseX, mouseY)) return false;
|
if (!inTermRegion(mouseX, mouseY)) return false;
|
||||||
if (!hasMouseSupport() || deltaY == 0) return false;
|
if (!hasMouseSupport() || delta == 0) return false;
|
||||||
|
|
||||||
var charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
var charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||||
var charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
var charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||||
charX = Math.min(Math.max(charX, 0), terminal.getWidth() - 1);
|
charX = Math.min(Math.max(charX, 0), terminal.getWidth() - 1);
|
||||||
charY = Math.min(Math.max(charY, 0), terminal.getHeight() - 1);
|
charY = Math.min(Math.max(charY, 0), terminal.getHeight() - 1);
|
||||||
|
|
||||||
computer.mouseScroll(deltaY < 0 ? 1 : -1, charX + 1, charY + 1);
|
computer.mouseScroll(delta < 0 ? 1 : -1, charX + 1, charY + 1);
|
||||||
|
|
||||||
lastMouseX = charX;
|
lastMouseX = charX;
|
||||||
lastMouseY = charY;
|
lastMouseY = charY;
|
||||||
@@ -257,12 +259,15 @@ public class TerminalWidget extends AbstractWidget {
|
|||||||
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
if (!visible) return;
|
if (!visible) return;
|
||||||
|
|
||||||
var emitter = FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), graphics.bufferSource().getBuffer(RenderTypes.TERMINAL));
|
var bufferSource = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
||||||
|
var emitter = FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), bufferSource.getBuffer(RenderTypes.TERMINAL));
|
||||||
|
|
||||||
FixedWidthFontRenderer.drawTerminal(
|
FixedWidthFontRenderer.drawTerminal(
|
||||||
emitter,
|
emitter,
|
||||||
(float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN
|
(float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bufferSource.endBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -6,15 +6,12 @@ package dan200.computercraft.client.integration.emi;
|
|||||||
|
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.integration.RecipeModHelpers;
|
|
||||||
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
||||||
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
||||||
import dev.emi.emi.api.EmiEntrypoint;
|
import dev.emi.emi.api.EmiEntrypoint;
|
||||||
import dev.emi.emi.api.EmiPlugin;
|
import dev.emi.emi.api.EmiPlugin;
|
||||||
import dev.emi.emi.api.EmiRegistry;
|
import dev.emi.emi.api.EmiRegistry;
|
||||||
import dev.emi.emi.api.stack.Comparison;
|
import dev.emi.emi.api.stack.Comparison;
|
||||||
import dev.emi.emi.api.stack.EmiStack;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
@@ -28,17 +25,15 @@ public class EMIComputerCraft implements EmiPlugin {
|
|||||||
|
|
||||||
registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), pocketComparison);
|
registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), pocketComparison);
|
||||||
registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get(), pocketComparison);
|
registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get(), pocketComparison);
|
||||||
|
|
||||||
for (var stack : RecipeModHelpers.getExtraStacks(Minecraft.getInstance().level.registryAccess())) {
|
|
||||||
registry.addEmiStack(EmiStack.of(stack));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Comparison turtleComparison = compareStacks((left, right)
|
private static final Comparison turtleComparison = compareStacks((left, right) ->
|
||||||
-> TurtleItem.getUpgrade(left, TurtleSide.LEFT) == TurtleItem.getUpgrade(right, TurtleSide.LEFT)
|
left.getItem() instanceof TurtleItem turtle
|
||||||
&& TurtleItem.getUpgrade(left, TurtleSide.RIGHT) == TurtleItem.getUpgrade(right, TurtleSide.RIGHT));
|
&& turtle.getUpgrade(left, TurtleSide.LEFT) == turtle.getUpgrade(right, TurtleSide.LEFT)
|
||||||
|
&& turtle.getUpgrade(left, TurtleSide.RIGHT) == turtle.getUpgrade(right, TurtleSide.RIGHT));
|
||||||
|
|
||||||
private static final Comparison pocketComparison = compareStacks((left, right) -> PocketComputerItem.getUpgrade(left) == PocketComputerItem.getUpgrade(right));
|
private static final Comparison pocketComparison = compareStacks((left, right) ->
|
||||||
|
left.getItem() instanceof PocketComputerItem && PocketComputerItem.getUpgrade(left) == PocketComputerItem.getUpgrade(right));
|
||||||
|
|
||||||
private static Comparison compareStacks(BiPredicate<ItemStack, ItemStack> test) {
|
private static Comparison compareStacks(BiPredicate<ItemStack, ItemStack> test) {
|
||||||
return Comparison.of((left, right) -> {
|
return Comparison.of((left, right) -> {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user