1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 04:00:30 +00:00

Fabric lol

- Add support for Fabric. This is mostly pretty simple, though does
   require a lot more mixins than Forge.

   Half this diff is due to data generators: we run them separately as
   some aspects (recipes mostly) are different between the loaders.

 - Add integration with Iris (same as our Oculus support) and REI
   (mostly the same as our JEI support).

 - Generic peripherals only support inventories (or rather
   InventoryStorage) right now. Supporting more of the Fabric storage
   API is going to be tricky due to the slotted nature of the API: maybe
   something to revisit after Transfer API V3 (V4?, I've lost track).

Note, this does /not/ mean I will be publishing a Fabric version of
CC:T. My plan is to rebase CC:R on top of this, hopefully simplifying
the maintenance work on their end and making the two mods a little more
consistent.
This commit is contained in:
Jonathan Coates 2022-11-10 19:32:13 +00:00
parent b2b58892e3
commit 8152f19b6e
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
363 changed files with 7264 additions and 75 deletions

View File

@ -4,96 +4,96 @@ provides an introduction as to how to get started in helping out.
If you've any other questions, [just ask the community][community] or [open an issue][new-issue].
## Table of Contents
- [Reporting issues](#reporting-issues)
- [Translations](#translations)
- [Setting up a development environment](#setting-up-a-development-environment)
- [Developing CC: Tweaked](#developing-cc-tweaked)
- [Writing documentation](#writing-documentation)
## Reporting issues
If you have a bug, suggestion, or other feedback, the best thing to do is [file an issue][new-issue]. When doing so,
do use the issue templates - they provide a useful hint on what information to provide.
If you have a bug, suggestion, or other feedback, the best thing to do is [file an issue][new-issue]. When doing so, do
use the issue templates - they provide a useful hint on what information to provide.
## Translations
Translations are managed through [Weblate], an online interface for managing language strings. This is synced
automatically with GitHub, so please don't submit PRs adding/changing translations!
## Developing
In order to develop CC: Tweaked, you'll need to download the source code and then run it. This is a pretty simple
process. When building on Windows, Use `gradlew.bat` instead of `./gradlew`.
## Setting up a development environment
In order to develop CC: Tweaked, you'll need to download the source code and then run it.
- **Clone the repository:** `git clone https://github.com/cc-tweaked/CC-Tweaked.git && cd CC-Tweaked`
- **Setup Forge:** `./gradlew build`
- **Run Minecraft:** `./gradlew runClient` (or run the `GradleStart` class from your IDE).
- **Optionally:** For small PRs (especially those only touching Lua code), it may be easier to use GitPod, which
provides a pre-configured environment: [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-2b2b2b?logo=gitpod)](https://gitpod.io/#https://github.com/cc-tweaked/CC-Tweaked/)
- Make sure you've got the following software instealled:
- Java Development Kit (JDK) installed. This can be downloaded from [Adoptium].
- [Git](https://git-scm.com/).
- If you want to work on documentation, [NodeJS][node].
Do note you will need to download the mod after compiling to test.
- Download CC: Tweaked's source code:
```
git clone https://github.com/cc-tweaked/CC-Tweaked.git
cd CC-Tweaked
```
If you want to run CC:T in a normal Minecraft instance, run `./gradlew build` and copy the `.jar` from `build/libs`.
These commands may take a few minutes to run the first time, as the environment is set up, but should be much faster
afterwards.
- Build CC: Tweaked with `./gradlew build`. This will be very slow the first time it runs, as it needs to download a
lot of dependencies (and decompile Minecraft several times). Subsequent runs should be much faster!
The following sections describe the more niche sections of CC: Tweaked's build system. Some bits of these are
quite-complex, and (dare I say) over-engineered, so you may wish to ignore them. Well tested/documented PRs are always
preferred (and I'd definitely recommend setting up the tooling if you're doing serious development work), but for
small changes it can be a lot.
- You're now ready to start developing CC: Tweaked. Running `./gradlew :forge:runClient` or
`./gradle :fabric:runClient` will start Minecraft under Forge and Fabric respectively.
### Code linters
CC: Tweaked uses a couple of "linters" on its source code, to enforce a consistent style across the project. While these
are run whenever you submit a PR, it's often useful to run this before committing.
If you want to run CC:T in a normal Minecraft instance, run `./gradlew assemble` and copy the `.jar` from
`projects/forge/build/libs` (for Forge) or `projects/fabric/build/libs` (for Fabric).
- **[Checkstyle]:** Checks Java code to ensure it is consistently formatted. This can be run with `./gradlew build` or
`./gradle check`.
- **[illuaminate]:** Checks Lua code for semantic and styleistic issues. This can be run with `./gradlew lintLua`.
## Developing CC: Tweaked
Before making any major changes to CC: Tweaked, I'd recommend you have a read of the [the architecture
document][architecture] first. While it's not a comprehensive document, it gives a good hint of where you should start
looking to make your changes. As always, if you're not sure [do ask the community][community]!
### Documentation
### Testing
When making larger changes, it's may be useful to write a test to make sure your code works as expected.
CC: Tweaked has several test suites, each designed to test something different:
- In order to test CraftOS and its builtin APIs, we have a test suite written in Lua located at
`projects/core/src/test/resources/test-rom/`. These don't rely on any Minecraft code, which means they can run on
emulators, acting as a sort of compliance test.
These tests are written using a test system called "mcfly", heavily inspired by [busted]. Groups of tests go inside
`describe` blocks, and a single test goes inside `it`. Assertions are generally written using `expect` (inspired by
Hamcrest and the like). For instance, `expect(foo):eq("bar")` asserts that your variable `foo` is equal to the
expected value `"bar"`.
These tests can be run with `./gradlew :core:test`.
- In-game functionality, such as the behaviour of blocks and items, is tested using [Minecraft's gametest
system][mc-test] (`projects/common/src/testMod`). These tests spin up a server, spawn a structure for each test, and
then run some code on the blocks defined in that structure.
These tests can be run with `./gradlew runGametest` (or `./gradle :forge:runGametest`/`./gradlew :fabric:runGametest`
for a single loader).
For more information, [see the architecture document][architecture].
## Writing documentation
When writing documentation for [CC: Tweaked's documentation website][docs], it may be useful to build the documentation
and preview it yourself before submitting a PR.
Our documentation generation pipeline is rather complex, and involves invoking several external tools. Most of this
complexity is hidden by Gradle, but you will need to perform some initial setup:
You'll first need to [set up a development environment as above](#setting-up-a-development-environment).
- Install [Node/npm][node].
- Run `npm ci` to install our Node dependencies.
Once this is set up, you can now run `./gradlew :web:site`. This generates documentation from our Lua and Java code,
writing the resulting HTML into `./projects/web/build/site`, which can then be opened in a browser. When iterating on
documentation, you can instead run `./gradlew :web:site -t`, which will rebuild documentation every time you change a
file.
You can now run `./gradlew docWebsite`. This generates documentation from our Lua and Java code, writing the resulting
HTML into `./projects/web/build/site`.
Documentation is built using [illuaminate] which, while not currently documented (somewhat ironic), is largely the same
as [ldoc][ldoc]. Documentation comments are written in Markdown, though note that we do not support many GitHub-specific
markdown features - if you can, do check what the documentation looks like locally!
#### Writing documentation
illuaminate's documentation system is not currently documented (somewhat ironic), but is _largely_ the same as
[ldoc][ldoc]. Documentation comments are written in Markdown,
Our markdown engine does _not_ support GitHub flavoured markdown, and so does not support all the features one might
expect. It is recommended that you build and preview the docs locally first.
When iterating on documentation, you can get Gradle to rebuild the website every time a file changes by running
`./gradlew docWebsite -t`. This will take a couple of seconds to run, but definitely beats running it manually!
### Testing
Thankfully running tests is much simpler than running the documentation generator! `./gradlew check` will run the
entire test suite (and some additional bits of verification).
Before we get into writing tests, it's worth mentioning the various test suites that CC: Tweaked has:
- "Core" Java (`./src/test/java`): These test core bits of the mod which don't require any Minecraft interaction.
This includes the `@LuaFunction` system, file system code, etc...
These tests are run by `./gradlew test`.
- CraftOS (`./src/test/resources/test-rom/`): These tests are written in Lua, and ensure the Lua environment, libraries
and programs work as expected. These are (generally) written to be able to be run on emulators too, to provide some
sort of compliance test.
These tests are run by the '"Core" Java' test suite, and so are also run with `./gradlew test`.
- In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
These tests are run with `./gradlew runGametest`.
## CraftOS tests
CraftOS's tests are written using a test system called "mcfly", heavily inspired by [busted] (and thus RSpec). Groups of
tests go inside `describe` blocks, and a single test goes inside `it`.
Assertions are generally written using `expect` (inspired by Hamcrest and the like). For instance, `expect(foo):eq("bar")`
asserts that your variable `foo` is equal to the expected value `"bar"`.
When writing long-form documentation (such as the guides in [doc/guides](doc/guides)), I find it useful to tell a
narrative. Think of what you want the user to learn or achieve, then start introducing a simple concept and then talk
about how you can build on that, until you've covered everything!
[new-issue]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose "Create a new issue"
[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"
[checkstyle]: https://checkstyle.org/
[illuaminate]: https://github.com/SquidDev/illuaminate/ "Illuaminate on GitHub"
[weblate]: https://i18n.tweaked.cc/projects/cc-tweaked/minecraft/ "CC: Tweaked weblate instance"
@ -102,3 +102,4 @@ asserts that your variable `foo` is equal to the expected value `"bar"`.
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
[node]: https://nodejs.org/en/ "Node.js"
[architecture]: projects/ARCHITECTURE.md

View File

@ -34,6 +34,13 @@ repositories {
includeGroup("org.spongepowered")
}
}
maven("https://maven.fabricmc.net/") {
name = "Fabric"
content {
includeGroup("net.fabricmc")
}
}
}
dependencies {
@ -41,9 +48,11 @@ dependencies {
implementation(libs.kotlin.plugin)
implementation(libs.spotless)
implementation(libs.vanillaGradle)
implementation(libs.fabric.loom)
implementation(libs.forgeGradle)
implementation(libs.librarian)
implementation(libs.quiltflower)
implementation(libs.vanillaGradle)
}
gradlePlugin {

View File

@ -0,0 +1,66 @@
/** Default configuration for Fabric projects. */
import cc.tweaked.gradle.CCTweakedExtension
import cc.tweaked.gradle.CCTweakedPlugin
import cc.tweaked.gradle.IdeaRunConfigurations
import cc.tweaked.gradle.MinecraftConfigurations
plugins {
`java-library`
id("fabric-loom")
id("io.github.juuxel.loom-quiltflower")
id("cc-tweaked.java-convention")
}
plugins.apply(CCTweakedPlugin::class.java)
val mcVersion: String by extra
repositories {
maven("https://maven.parchmentmc.org/") {
name = "Parchment"
content {
includeGroup("org.parchmentmc.data")
}
}
}
loom {
splitEnvironmentSourceSets()
splitModDependencies.set(true)
}
MinecraftConfigurations.setup(project)
extensions.configure(CCTweakedExtension::class.java) {
linters(minecraft = true, loader = "fabric")
}
dependencies {
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
minecraft("com.mojang:minecraft:$mcVersion")
mappings(
loom.layered {
officialMojangMappings()
parchment(
project.dependencies.create(
group = "org.parchmentmc.data",
name = "parchment-${libs.findVersion("parchmentMc").get()}",
version = libs.findVersion("parchment").get().toString(),
ext = "zip",
),
)
},
)
modImplementation(libs.findLibrary("fabric-loader").get())
modImplementation(libs.findLibrary("fabric-api").get())
// Depend on error prone annotations to silence a lot of compile warnings.
compileOnlyApi(libs.findLibrary("errorProne.annotations").get())
}
tasks.ideaSyncTask {
doLast { IdeaRunConfigurations(project).patch() }
}

View File

@ -42,6 +42,7 @@ repositories {
includeGroup("org.squiddev")
includeGroup("cc.tweaked")
// Things we mirror
includeGroup("dev.architectury")
includeGroup("maven.modrinth")
includeGroup("me.shedaniel")
includeGroup("me.shedaniel.cloth")

View File

@ -2,11 +2,13 @@
# Minecraft
# MC version is specified in gradle.properties, as we need that in settings.gradle.
fabric-api = "0.66.0+1.19.2"
fabric-loader = "0.14.10"
forge = "43.1.1"
forgeSpi = "6.0.0"
mixin = "0.8.5"
parchment = "2022.10.16"
parchmentMc = "1.19.2"
mixin = "0.8.5"
# Normal dependencies
asm = "9.3"
@ -32,6 +34,7 @@ oculus = "1.2.5"
rei = "9.1.550"
# Testing
byteBuddy = "1.12.18"
hamcrest = "2.2"
jqwik = "1.7.0"
junit = "5.9.1"
@ -42,6 +45,7 @@ checkstyle = "10.3.4"
curseForgeGradle = "1.0.11"
errorProne-core = "2.14.0"
errorProne-plugin = "2.0.2"
fabric-loom = "1.0-SNAPSHOT"
forgeGradle = "5.1.+"
githubRelease = "2.2.12"
ideaExt = "1.1.6"
@ -50,6 +54,7 @@ librarian = "1.+"
minotaur = "2.+"
mixinGradle = "0.7.+"
nullAway = "0.9.9"
quiltflower = "1.7.3"
shadow = "7.1.2"
spotless = "6.8.0"
taskTree = "2.1.0"
@ -74,14 +79,21 @@ nightConfig-toml = { module = "com.electronwill.night-config:toml", version.ref
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
# Minecraft mods
fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" }
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" }
forgeConfig = { module = "net.minecraftforge:forgeconfigapiport-fabric", version.ref = "forgeConfig" }
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
jei-api = { module = "mezz.jei:jei-1.19.2-common-api", version.ref = "jei" }
jei-fabric = { module = "mezz.jei:jei-1.19.2-fabric", version.ref = "jei" }
jei-forge = { module = "mezz.jei:jei-1.19.2-forge", version.ref = "jei" }
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
oculus = { module = "maven.modrinth:oculus", version.ref = "oculus" }
rei-api = { module = "me.shedaniel:RoughlyEnoughItems-api", version.ref = "rei" }
rei-builtin = { module = "me.shedaniel:RoughlyEnoughItems-default-plugin", version.ref = "rei" }
rei-fabric = { module = "me.shedaniel:RoughlyEnoughItems-fabric", version.ref = "rei" }
# Testing
byteBuddyAgent = { module ="net.bytebuddy:byte-buddy-agent", version.ref = "byteBuddy" }
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
jqwik-api = { module = "net.jqwik:jqwik-api", version.ref = "jqwik" }
jqwik-engine = { module = "net.jqwik:jqwik-engine", version.ref = "jqwik" }
@ -97,10 +109,12 @@ errorProne-api = { module = "com.google.errorprone:error_prone_check_api", versi
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-testHelpers = { module = "com.google.errorprone:error_prone_test_helpers", version.ref = "errorProne-core" }
fabric-loom = { module = "net.fabricmc:fabric-loom", version.ref = "fabric-loom" }
forgeGradle = { module = "net.minecraftforge.gradle:ForgeGradle", version.ref = "forgeGradle" }
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
librarian = { module = "org.parchmentmc:librarian", version.ref = "librarian" }
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
quiltflower = { module = "io.github.juuxel:loom-quiltflower", version.ref = "quiltflower" }
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
vanillaGradle = { module = "org.spongepowered:vanillagradle", version.ref = "vanillaGradle" }
@ -123,6 +137,9 @@ kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
externalMods-common = ["jei-api", "forgeConfig", "nightConfig-core", "nightConfig-toml"]
externalMods-forge-compile = ["oculus", "jei-api"]
externalMods-forge-runtime = ["jei-forge"]
externalMods-fabric = ["fabric-loader", "fabric-api", "forgeConfig", "nightConfig-core", "nightConfig-toml"]
externalMods-fabric-compile = ["iris", "jei-api", "rei-api", "rei-builtin"]
externalMods-fabric-runtime = ["jei-fabric"]
# Testing
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]

159
projects/ARCHITECTURE.md Normal file
View File

@ -0,0 +1,159 @@
# Architecture
CC: Tweaked has a rather complex project layout, as there's several use-cases we want to support (multiple mod loaders,
usable outside of Minecraft). As such, it can be tricky to understand how the code is structured and how the various
sub-projects interact. This document provides a high-level overview of the entire mod.
## Project Outline
CC: Tweaked is split into 4 primary modules (`core`, `common`, `fabric`, `forge`). These themselves are then split into
a public API (i.e `core-api`) and the actual implementation (i.e. `core`).
- `core`: This contains the core "computer" part of ComputerCraft, such as the Lua VM, filesystem and builtin APIs.
This is also where the Lua ROM is located (`projects/core/src/main/resources/data/computercraft/lua`). Notably this
project does _not_ depend on Minecraft, making it possible to use it emulators and other tooling.
- `common`: This contains all non mod-loader-specific Minecraft code. This is where computers, turtles and peripherals
are defined (and everything else Minecraft-related!).
This project is separates client code into its own separate source set (suitably named `client`). This helps us
ensure that server code can never reference client-only code (such as LWJGL).
- `forge` and `fabric`: These contain any mod-loader specific code.
When we need to call loader-specific code from our own code (for instance, sending network messages or firing
loader-specific events), we use a `PlatformHelper` interface (defined in
`projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java`). This abstracts over most
loader-specific code we need to use, and is then implemented by each mod-loader-specific project. The concrete
implementation is then loaded with Java's [`ServiceLoader`][ServiceLoader], in a design based on [jaredlll08's
multi-loader template][MultiLoader-Template]. We use a similar system for communicating between the API and its
implementation.
```mermaid
flowchart LR
subgraph Common
platform(PlatformHelper)
impl[AbstractComputerCraftAPIImpl]
end
subgraph API
api(ComputerCraft API) --> impl
end
subgraph Forge[Forge]
platform --> forgePlatform[PlatformHelperImpl]
impl -.-> forgeImpl[ComputerCraftAPIImpl]
end
subgraph Fabric
platform --> fabricPlatform[PlatformHelperImpl]
impl -.-> fabricImpl[ComputerCraftAPIImpl]
end
```
Note the `PlatformHelper` is only used when calling from our code into loader-specific code. While we use this to _fire_
events, we do not use it to _subscribe_ to events. For that we just subscribe to the events in the loader-specific
project, and then dispatch to the common `CommonHooks` (for shared code) and `ClientHooks` (for client-specific code).
You may notice there's a couple of other, smaller modules in the codebase. These you can probably ignore, but are worth
mentioning:
- `lints`: This defines an [ErrorProne] plugin which adds a couple of compile-time checks to our code. This is what
enforces that no client-specific code is used inside the `main` source set (and a couple of other things!).
- `web`: This contains the additional tooling for building [the documentation website][tweaked.cc], such as support for
rendering recipes
- `build-logic` (in the base directory, not in `projects/`): This contains any build logic shared between modules. For
instance, `cc-tweaked.java-convention.gradle.kts` sets up the defaults for Java that we use across the whole project.
> **Note**
> The Forge and Fabric modules (and their API counterparts) depend on the common modules. However, in order to correctly
> process mixins we need to compile the common code along with the Forge/Fabric code. This leads to a slightly strange
> build process:
>
> - In your IDE, Forge/Fabric depend on the common as normal.
> - When building via Gradle, the common code is compiled alongside Forge/Fabric.
>
> You shouldn't need to worry about this - it should all be set up automatically - but hopefully explains a little bit
> why our Gradle scripts are slightly odd!
## Testing
CC: Tweaked has a small (though growing!) test suite to ensure various features behave correctly. Most tests are written
in Java using [JUnit], though we also make use of [jqwik] for property testing.
### Test Fixtures
Some projects define an additional `testFixtures` folder alongside their main `test` code (i.e.
`projects/core/src/testFixtures`). This source set contains test-related code which might be consumed in dependent
projects. For instance, core's test fixtures defines additional [Hamcrest] matchers, which are used in both `core` and
`common`'s test suite.
Test fixtures may also define [Test Interfaces]. This is a pattern for writing tests to ensure that an implementation
obeys its interface's contract. For instance, we might have a `ListContract` test, which asserts an abstract list
behaves as expected:
```java
interface ListContract<T extends List<Integer>> {
T newList();
@Test
default void testAddInsert() {
var list = newList();
assertTrue(list.add(123));
assertTrue(list.contains(123));
}
}
```
We can then use this interface to create tests for a specific implementation:
```java
class ArrayListTest implements ListContract<ArrayList<Integer>> {
@Override public ArrayList<Integer> newList() { return new ArrayList<>(); }
}
```
This is especially useful when testing `PlatformHelper` and other mod loader abstractions.
### Lua tests
While the majority of CC: Tweaked is written in Java, a significant portion of the code is written in Lua. As such, it's
also useful to test that.
This is done by starting a Lua VM with all of ComputerCraft's APIs loaded, then starting a custom test framework
(`mcfly.lua`). This test framework discovers tests and sends them back to the Java side. These are turned into JUnit
tests which are then in turn run on the computer again. This allows the tests to integrate with existing Java testing
tooling (for instance, XML test reports and IDE integration).
There's a slightly more detailed description of the process at `CraftOsLuaTest.java`.
### Game tests
CC: Tweaked also runs several tests in-game using Minecraft's [gametest framework][mc-test]. These work by starting
a Minecraft server and then, for each test, spawning a structure and then interacting with the blocks inside the
structure, asserting they behave as expected.
Unlike most of our other tests, these are written in Kotlin. We make extensive use of [extension methods] to augment
vanilla's own test classes, which helps give a more consistent feel to the API.
Each test works by defining a sequence of steps. Each step can either run an action (`thenExecute`), sleep for a period
(`thenIdle`) or sleep until a condition is met (`thenWaitUntil`).
```kotlin
fun Some_test(context: GameTestHelper) = context.sequence {
thenExecute { context.setBlock(BlockPos(2, 2, 2), Blocks.AIR) }
thenIdle(4)
thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit") }
}
```
Some tests need to use Lua APIs from a computer, such as when testing `turtle.dig`. In order to do this, we install
a custom "Lua" runtime (see `ManagedComputers.kt`) which actually runs Java functions. Tests can then enqueue a function
to run on a particular computer and then wait for it to finish.
While the internals of this is quite complex, it ends up being a much nicer workflow than writing parts of the test in
Lua. It also ends up being much more efficient, which is important when running a dozen tests at once!
[MultiLoader-Template]: https://github.com/jaredlll08/MultiLoader-Template/ "MultiLoader-Template - A template for a Forge + Fabric project setup using a Common source set."
[ServiceLoader]: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ServiceLoader.html "ServiceLoader (Java SE 17 and JDK 17)"
[ErrorProne]: https://errorprone.info/ "ErrorProne"
[tweaked.cc]: https://tweaked.cc "CC: Tweaked"
[JUnit]: https://junit.org/junit5/ "JUnit 5"
[jqwik]: https://jqwik.net/
[Hamcrest]: https://hamcrest.org/JavaHamcrest/ "Java Hamcrest"
[Test Interfaces]: https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-interfaces-and-default-methods
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg "Testing Minecraft in Minecraft on YouTube"
[extension methods]: https://kotlinlang.org/docs/extensions.html "Extensions | Kotlin"

View File

@ -6,11 +6,19 @@
package dan200.computercraft.mixin;
import net.minecraft.world.item.CreativeModeTab;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(CreativeModeTab.class)
public interface CreativeModeTabAccessor {
@Accessor("langId")
String computercraft$langId();
@Final
@Mutable
@Accessor("TABS")
static void computercraft$setTabs(CreativeModeTab[] tabs) {
}
}

View File

@ -18,6 +18,8 @@ import net.minecraftforge.fml.config.ModConfig;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.filter.MarkerFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.List;
@ -25,6 +27,8 @@ import java.util.Objects;
import java.util.concurrent.TimeUnit;
public final class ConfigSpec {
private static final Logger LOG = LoggerFactory.getLogger(ConfigSpec.class);
private static final int MODEM_MAX_RANGE = 100000;
private static final String TRANSLATION_PREFIX = "gui.computercraft.config.";
@ -337,6 +341,8 @@ public final class ConfigSpec {
}
private static void syncServer() {
if (!serverSpec.isLoaded()) return;
// General
Config.computerSpaceLimit = computerSpaceLimit.get();
Config.floppySpaceLimit = floppySpaceLimit.get();
@ -399,6 +405,8 @@ public final class ConfigSpec {
}
private static void syncClient() {
if (!clientSpec.isLoaded()) return;
Config.monitorRenderer = monitorRenderer.get();
Config.monitorDistance = monitorDistance.get();
Config.uploadNagDelay = uploadNagDelay.get();
@ -406,7 +414,17 @@ public final class ConfigSpec {
public static void sync(ModConfig config) {
if (!config.getModId().equals(ComputerCraftAPI.MOD_ID)) return;
if (config.getType() == ModConfig.Type.SERVER) syncServer();
if (config.getType() == ModConfig.Type.CLIENT) syncClient();
try {
if (config.getType() == ModConfig.Type.SERVER) syncServer();
if (config.getType() == ModConfig.Type.CLIENT) syncClient();
} catch (IllegalStateException e) {
// TODO: Remove when https://github.com/Fuzss/forgeconfigapiport-fabric/issues/26 is fixed.
if (e.getMessage() != null && e.getMessage().startsWith("Cannot get config value before config is loaded.")) {
return;
}
throw e;
}
}
}

View File

@ -0,0 +1,17 @@
plugins {
id("cc-tweaked.publishing")
id("cc-tweaked.fabric")
}
val mcVersion: String by extra
java {
withJavadocJar()
}
cct.inlineProject(":common-api")
dependencies {
api(project(":core-api"))
compileOnly(project(":forge-stubs"))
}

View File

@ -0,0 +1,22 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.detail;
import dan200.computercraft.impl.ComputerCraftAPIFabricService;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
/**
* {@link DetailRegistry}s for Fabric's types.
*
* @see VanillaDetailRegistries Detail registries for vanilla types.
*/
public class FabricDetailRegistries {
/**
* Detail provider for {@link FluidVariant}s.
*/
public static final DetailRegistry<StorageView<FluidVariant>> FLUID_VARIANT = ComputerCraftAPIFabricService.get().getFluidDetailRegistry();
}

View File

@ -0,0 +1,29 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.node.wired;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.network.wired.IWiredElement;
import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
/**
* {@linkplain BlockApiLookup Block API lookup} for {@link IWiredElement}s. This should be used to query wired elements
* from a block.
*/
public final class WiredElementLookup {
public static final ResourceLocation ID = new ResourceLocation(ComputerCraftAPI.MOD_ID, "wired_node");
private static final BlockApiLookup<IWiredElement, Direction> lookup = BlockApiLookup.get(ID, IWiredElement.class, Direction.class);
private WiredElementLookup() {
}
public static BlockApiLookup<IWiredElement, Direction> get() {
return lookup;
}
}

View File

@ -0,0 +1,28 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.ComputerCraftAPI;
import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
/**
* {@linkplain BlockApiLookup Block API lookup} for {@link IPeripheral}s. This should be used to register peripherals
* for a block. It should <em>NOT</em> be used to query peripherals.
*/
public final class PeripheralLookup {
public static final ResourceLocation ID = new ResourceLocation(ComputerCraftAPI.MOD_ID, "peripheral");
private static final BlockApiLookup<IPeripheral, Direction> lookup = BlockApiLookup.get(ID, IPeripheral.class, Direction.class);
private PeripheralLookup() {
}
public static BlockApiLookup<IPeripheral, Direction> get() {
return lookup;
}
}

View File

@ -0,0 +1,25 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.impl;
import dan200.computercraft.api.detail.DetailRegistry;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
import org.jetbrains.annotations.ApiStatus;
/**
* A Fabric-specific version of {@link ComputerCraftAPIService}.
* <p>
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
*/
@ApiStatus.Internal
public interface ComputerCraftAPIFabricService extends ComputerCraftAPIService {
static ComputerCraftAPIFabricService get() {
return (ComputerCraftAPIFabricService) ComputerCraftAPIService.get();
}
DetailRegistry<StorageView<FluidVariant>> getFluidDetailRegistry();
}

View File

@ -0,0 +1,155 @@
import cc.tweaked.gradle.annotationProcessorEverywhere
import cc.tweaked.gradle.clientClasses
import cc.tweaked.gradle.commonClasses
import net.fabricmc.loom.configuration.ide.RunConfigSettings
plugins {
id("cc-tweaked.fabric")
id("cc-tweaked.gametest")
}
val modVersion: String by extra
val mcVersion: String by extra
val allProjects = listOf(":core-api", ":core", ":fabric-api").map { evaluationDependsOn(it) }
cct {
inlineProject(":common")
allProjects.forEach { externalSources(it) }
}
dependencies {
modImplementation(libs.bundles.externalMods.fabric)
modCompileOnly(libs.bundles.externalMods.fabric.compile) {
exclude("net.fabricmc", "fabric-loader")
exclude("net.fabricmc.fabric-api")
}
modClientRuntimeOnly(libs.bundles.externalMods.fabric.runtime) {
exclude("net.fabricmc", "fabric-loader")
exclude("net.fabricmc.fabric-api")
}
include(libs.cobalt)
include(libs.netty.http) // It might be better to shadowJar this, as we don't use half of it.
include(libs.forgeConfig)
include(libs.nightConfig.core)
include(libs.nightConfig.toml)
// Pull in our other projects. See comments in MinecraftConfigurations on this nastiness.
implementation(project(":core"))
compileOnly(project(":forge-stubs"))
implementation(commonClasses(project(":fabric-api")))
clientImplementation(clientClasses(project(":fabric-api")))
annotationProcessorEverywhere(libs.autoService)
testModImplementation(testFixtures(project(":core")))
testModImplementation(testFixtures(project(":fabric")))
testImplementation(libs.byteBuddyAgent)
testImplementation(libs.bundles.test)
testRuntimeOnly(libs.bundles.testRuntime)
}
sourceSets.main { resources.srcDir("src/generated/resources") }
loom {
accessWidenerPath.set(project(":common").file("src/main/resources/computercraft.accesswidener"))
mixin.defaultRefmapName.set("computercraft.refmap.json")
mods {
register("computercraft") {
// Configure sources when running via the IDE. Note these don't add build dependencies (hence why it's safe
// to use common), only change how the launch.cfg file is generated.
cct.sourceDirectories.get().forEach { sourceSet(it.sourceSet) }
// Running via Gradle
dependency(dependencies.project(":core").apply { isTransitive = false })
}
register("cctest") {
sourceSet(sourceSets.testMod.get())
sourceSet(project(":common").sourceSets.testMod.get())
}
}
runs {
configureEach {
ideConfigGenerated(true)
}
named("client") {
configName = "Client"
}
named("server") {
configName = "Server"
runDir("run/server")
}
register("data") {
configName = "Datagen"
server()
runDir("run/dataGen")
property("cct.pretty-json")
property("fabric-api.datagen")
property("fabric-api.datagen.output-dir", file("src/generated/resources").absolutePath)
property("fabric-api.datagen.strict-validation")
}
fun configureForGameTest(config: RunConfigSettings) = config.run {
source(sourceSets.testMod.get())
val testSources = project(":common").file("src/testMod/resources/data/cctest").absolutePath
property("cctest.sources", testSources)
// Load cctest last, so it can override resources. This bypasses Fabric's shuffling of mods
property("fabric.debug.loadLate", "cctest")
}
val testClient by registering {
configName = "Test Client"
client()
configureForGameTest(this)
runDir("run/testClient")
}
register("gametest") {
configName = "Game Test"
server()
configureForGameTest(this)
property("fabric-api.gametest")
property("fabric-api.gametest.report-file", project.buildDir.resolve("test-results/gametest/gametest.xml").absolutePath)
runDir("run/gametest")
}
}
}
tasks.processResources {
inputs.property("version", modVersion)
filesMatching("fabric.mod.json") {
expand(mapOf("version" to modVersion))
}
exclude(".cache")
}
tasks.jar {
from(allProjects.map { zipTree(it.tasks.jar.get().archiveFile) })
}
val validateMixinNames by tasks.registering(net.fabricmc.loom.task.ValidateMixinNameTask::class) {
source(sourceSets.main.get().output)
source(sourceSets.client.get().output)
source(sourceSets.testMod.get().output)
}
tasks.test { dependsOn(tasks.generateDLIConfig) }
val runGametest = tasks.named<JavaExec>("runGametest")
cct.jacoco(runGametest)
tasks.check { dependsOn(validateMixinNames, runGametest) }

View File

@ -0,0 +1,71 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client;
import dan200.computercraft.client.model.turtle.TurtleModelLoader;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.network.client.ClientNetworkContext;
import dan200.computercraft.shared.peripheral.modem.wired.CableBlock;
import dan200.computercraft.shared.platform.NetworkHandler;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import static dan200.computercraft.core.util.Nullability.assertNonNull;
public class ComputerCraftClient {
public static void init() {
ClientPlayNetworking.registerGlobalReceiver(NetworkHandler.ID, (client, handler, buf, responseSender) -> {
var packet = NetworkHandler.decodeClient(buf);
if (packet != null) client.execute(() -> packet.handle(ClientNetworkContext.get()));
});
ClientRegistry.register();
ClientRegistry.registerItemColours(ColorProviderRegistry.ITEM::register);
ClientRegistry.registerBlockEntityRenderers(BlockEntityRendererRegistry::register);
ClientRegistry.registerMainThread();
ModelLoadingRegistry.INSTANCE.registerModelProvider((manager, out) -> ClientRegistry.registerExtraModels(out));
ModelLoadingRegistry.INSTANCE.registerResourceProvider(loader -> (path, ctx) -> TurtleModelLoader.load(loader, path));
BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.MONITOR_NORMAL.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.MONITOR_ADVANCED.get(), RenderType.cutout());
ClientTickEvents.START_CLIENT_TICK.register(client -> ClientHooks.onTick());
// This isn't 100% consistent with Forge, but not worth a mixin.
WorldRenderEvents.START.register(context -> ClientHooks.onRenderTick());
WorldRenderEvents.BLOCK_OUTLINE.register((context, hitResult) -> {
var hit = Minecraft.getInstance().hitResult;
if (hit instanceof BlockHitResult blockHit && blockHit.getBlockPos().equals(hitResult.blockPos())) {
return !ClientHooks.drawHighlight(context.matrixStack(), assertNonNull(context.consumers()), context.camera(), blockHit);
} else {
return true;
}
});
// Easier to hook in as an event than use BlockPickInteractionAware.
ClientPickBlockGatherCallback.EVENT.register((player, hit) -> {
if (hit.getType() != HitResult.Type.BLOCK) return ItemStack.EMPTY;
var pos = ((BlockHitResult) hit).getBlockPos();
var level = Minecraft.getInstance().level;
var state = level.getBlockState(pos);
if (!(state.getBlock() instanceof CableBlock cable)) return ItemStack.EMPTY;
return cable.getCloneItemStack(state, hit, level, pos, player);
});
}
}

View File

@ -0,0 +1,72 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.integration;
import com.google.auto.service.AutoService;
import com.mojang.blaze3d.vertex.VertexFormat;
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
import net.fabricmc.loader.api.FabricLoader;
import net.irisshaders.iris.api.v0.IrisApi;
import net.irisshaders.iris.api.v0.IrisTextVertexSink;
import java.nio.ByteBuffer;
import java.util.Optional;
import java.util.function.IntFunction;
@AutoService(ShaderMod.Provider.class)
public class IrisShaderMod implements ShaderMod.Provider {
@Override
public Optional<ShaderMod> get() {
return FabricLoader.getInstance().isModLoaded("iris") ? Optional.of(new Impl()) : Optional.empty();
}
private static final class Impl extends ShaderMod {
@Override
public boolean isRenderingShadowPass() {
return IrisApi.getInstance().isRenderingShadowPass();
}
@Override
public boolean isShaderMod() {
return true;
}
@Override
public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, IntFunction<ByteBuffer> makeBuffer) {
return IrisApi.getInstance().getMinorApiRevision() >= 1
? new IrisQuadEmitter(vertexCount, makeBuffer)
: super.getQuadEmitter(vertexCount, makeBuffer);
}
private static final class IrisQuadEmitter implements DirectFixedWidthFontRenderer.QuadEmitter {
private final IrisTextVertexSink sink;
private IrisQuadEmitter(int vertexCount, IntFunction<ByteBuffer> makeBuffer) {
sink = IrisApi.getInstance().createTextVertexSink(vertexCount, makeBuffer);
}
@Override
public VertexFormat format() {
return sink.getUnderlyingVertexFormat();
}
@Override
public ByteBuffer buffer() {
return sink.getUnderlyingByteBuffer();
}
@Override
public void quad(float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2) {
sink.quad(x1, y1, x2, y2, z, pack(rgba[0], rgba[1], rgba[2], rgba[3]), u1, v1, u2, v2, RenderTypes.FULL_BRIGHT_LIGHTMAP);
}
private static int pack(int r, int g, int b, int a) {
return (a & 255) << 24 | (b & 255) << 16 | (g & 255) << 8 | r & 255;
}
}
}
}

View File

@ -0,0 +1,55 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.integration.rei;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.integration.RecipeModHelpers;
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
import dan200.computercraft.shared.turtle.items.TurtleItem;
import dev.architectury.event.EventResult;
import me.shedaniel.rei.api.client.plugins.REIClientPlugin;
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry;
import me.shedaniel.rei.api.common.entry.comparison.ItemComparatorRegistry;
import me.shedaniel.rei.plugin.common.BuiltinPlugin;
/**
* REI integration for ComputerCraft.
* <p>
* This is Fabric-only for now - getting the common jar working outside of architectury is awkward.
*/
public class REIComputerCraft implements REIClientPlugin {
@Override
public void registerItemComparators(ItemComparatorRegistry registry) {
registry.register((context, stack) -> {
var turtle = (TurtleItem) stack.getItem();
long hash = 1;
var left = turtle.getUpgrade(stack, TurtleSide.LEFT);
var right = turtle.getUpgrade(stack, TurtleSide.RIGHT);
if (left != null) hash = hash * 31 + left.getUpgradeID().hashCode();
if (right != null) hash = hash * 31 + right.getUpgradeID().hashCode();
return hash;
}, ModRegistry.Items.TURTLE_NORMAL.get(), ModRegistry.Items.TURTLE_ADVANCED.get());
registry.register((context, stack) -> {
var upgrade = PocketComputerItem.getUpgrade(stack);
return upgrade == null ? 1 : upgrade.getUpgradeID().hashCode();
}, ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get());
}
@Override
public void registerDisplays(DisplayRegistry registry) {
registry.registerDisplayGenerator(BuiltinPlugin.CRAFTING, new UpgradeDisplayGenerator());
// Hide all upgrade recipes
registry.registerVisibilityPredicate((category, display) ->
display.getDisplayLocation().map(RecipeModHelpers::shouldRemoveRecipe).orElse(false)
? EventResult.interruptFalse() : EventResult.pass());
}
}

View File

@ -0,0 +1,32 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.integration.rei;
import dan200.computercraft.shared.integration.UpgradeRecipeGenerator;
import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes;
import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCraftingDisplay;
import java.util.List;
import java.util.Optional;
/**
* Provides custom recipe and usage hints for pocket/turtle upgrades.
*/
class UpgradeDisplayGenerator implements DynamicDisplayGenerator<DefaultCraftingDisplay<?>> {
private final UpgradeRecipeGenerator<DefaultCraftingDisplay<?>> resolver = new UpgradeRecipeGenerator<>(DefaultCraftingDisplay::of);
@Override
public Optional<List<DefaultCraftingDisplay<?>>> getRecipeFor(EntryStack<?> entry) {
return entry.getType() == VanillaEntryTypes.ITEM ? Optional.of(resolver.findRecipesWithOutput(entry.castValue())) : Optional.empty();
}
@Override
public Optional<List<DefaultCraftingDisplay<?>>> getUsageFor(EntryStack<?> entry) {
return entry.getType() == VanillaEntryTypes.ITEM ? Optional.of(resolver.findRecipesWithInput(entry.castValue())) : Optional.empty();
}
}

View File

@ -0,0 +1,74 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.model;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Stream;
/**
* A {@link BakedModel} formed from two or more other models stitched together.
*/
public class CompositeBakedModel extends CustomBakedModel {
private final List<BakedModel> models;
public CompositeBakedModel(List<BakedModel> models) {
super(models.get(0));
this.models = models;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState blockState, @Nullable Direction face, RandomSource rand) {
@SuppressWarnings({ "unchecked", "rawtypes" })
List<BakedQuad>[] quads = new List[models.size()];
var i = 0;
for (var model : models) quads[i++] = model.getQuads(blockState, face, rand);
return new ConcatListView(quads);
}
private static final class ConcatListView extends AbstractList<BakedQuad> {
private final List<BakedQuad>[] quads;
private ConcatListView(List<BakedQuad>[] quads) {
this.quads = quads;
}
@Override
public Iterator<BakedQuad> iterator() {
return stream().iterator();
}
@Override
public Stream<BakedQuad> stream() {
return Arrays.stream(quads).flatMap(Collection::stream);
}
@Override
public BakedQuad get(int index) {
var i = index;
for (var modelQuads : quads) {
if (i < modelQuads.size()) return modelQuads.get(i);
i -= modelQuads.size();
}
throw new IndexOutOfBoundsException(i);
}
@Override
public int size() {
var size = 0;
for (var modelQuads : quads) size += modelQuads.size();
return size;
}
}
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.model;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Supplier;
/**
* A subclass of {@link ForwardingBakedModel} which doesn't forward rendering.
*/
public abstract class CustomBakedModel extends ForwardingBakedModel {
public CustomBakedModel(BakedModel wrapped) {
this.wrapped = wrapped;
}
@Override
public abstract List<BakedQuad> getQuads(@Nullable BlockState blockState, @Nullable Direction face, RandomSource rand);
@Override
public final void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<RandomSource> randomSupplier, RenderContext context) {
context.fallbackConsumer().accept(this);
}
@Override
public final void emitItemQuads(ItemStack stack, Supplier<RandomSource> randomSupplier, RenderContext context) {
context.fallbackConsumer().accept(this);
}
}

View File

@ -0,0 +1,89 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.model;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormatElement;
import com.mojang.math.Matrix4f;
import com.mojang.math.Transformation;
import com.mojang.math.Vector4f;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* A {@link BakedModel} which applies a transformation matrix to its underlying quads.
*/
public class TransformedBakedModel extends CustomBakedModel {
private static final int STRIDE = DefaultVertexFormat.BLOCK.getIntegerSize();
private static final int POS_OFFSET = findOffset(DefaultVertexFormat.BLOCK, DefaultVertexFormat.ELEMENT_POSITION);
private final Matrix4f transformation;
private @Nullable TransformedQuads cache;
public TransformedBakedModel(BakedModel model, Transformation transformation) {
super(model);
this.transformation = transformation.getMatrix();
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState blockState, @Nullable Direction face, RandomSource rand) {
var cache = this.cache;
var quads = wrapped.getQuads(blockState, face, rand);
if (quads.isEmpty()) return List.of();
// We do some basic caching here to avoid recomputing every frame. Most turtle models don't have culled faces,
// so it's not worth being smarter here.
if (cache != null && quads.equals(cache.original())) return cache.transformed();
List<BakedQuad> transformed = new ArrayList<>(quads.size());
for (var quad : quads) transformed.add(transformQuad(quad));
this.cache = new TransformedQuads(quads, transformed);
return transformed;
}
private BakedQuad transformQuad(BakedQuad quad) {
var vertexData = quad.getVertices().clone();
for (var i = 0; i < 4; i++) {
// Apply the matrix to our position
var start = STRIDE * i + POS_OFFSET;
var x = Float.intBitsToFloat(vertexData[start]);
var y = Float.intBitsToFloat(vertexData[start + 1]);
var z = Float.intBitsToFloat(vertexData[start + 2]);
// Transform the position
var pos = new Vector4f(x, y, z, 1);
pos.transform(transformation);
pos.perspectiveDivide();
vertexData[start] = Float.floatToRawIntBits(pos.x());
vertexData[start + 1] = Float.floatToRawIntBits(pos.y());
vertexData[start + 2] = Float.floatToRawIntBits(pos.z());
}
return new BakedQuad(vertexData, quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade());
}
private record TransformedQuads(List<BakedQuad> original, List<BakedQuad> transformed) {
}
private static int findOffset(VertexFormat format, VertexFormatElement element) {
var offset = 0;
for (var other : format.getElements()) {
if (other == element) return offset / Integer.BYTES;
offset += element.getByteSize();
}
throw new IllegalArgumentException("Cannot find " + element + " in " + format);
}
}

View File

@ -0,0 +1,46 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.model.turtle;
import dan200.computercraft.client.model.CompositeBakedModel;
import dan200.computercraft.client.model.TransformedBakedModel;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
public class TurtleModel extends ForwardingBakedModel {
private final TurtleModelParts parts;
private final Map<TurtleModelParts.Combination, BakedModel> cachedModels = new HashMap<>();
private final ItemOverrides overrides = new ItemOverrides() {
@Override
public BakedModel resolve(BakedModel model, ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) {
return cachedModels.computeIfAbsent(parts.getCombination(stack), TurtleModel.this::buildModel);
}
};
public TurtleModel(BakedModel familyModel, BakedModel colourModel) {
wrapped = familyModel;
parts = new TurtleModelParts(familyModel, colourModel, TransformedBakedModel::new);
}
@Override
public ItemOverrides getOverrides() {
return overrides;
}
private BakedModel buildModel(TurtleModelParts.Combination combo) {
var models = parts.buildModel(combo);
return models.size() == 1 ? models.get(0) : new CompositeBakedModel(models);
}
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.model.turtle;
import com.mojang.datafixers.util.Pair;
import dan200.computercraft.api.ComputerCraftAPI;
import net.fabricmc.fabric.api.client.model.ModelProviderException;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.GsonHelper;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
public final class TurtleModelLoader {
private static final ResourceLocation COLOUR_TURTLE_MODEL = new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_colour");
private TurtleModelLoader() {
}
public static @Nullable UnbakedModel load(ResourceManager resources, ResourceLocation path) throws ModelProviderException {
if (!path.getNamespace().equals(ComputerCraftAPI.MOD_ID)) return null;
if (!path.getPath().equals("item/turtle_normal") && !path.getPath().equals("item/turtle_advanced")) {
return null;
}
try (var reader = resources.openAsReader(new ResourceLocation(path.getNamespace(), "models/" + path.getPath() + ".json"))) {
var modelContents = GsonHelper.parse(reader).getAsJsonObject();
var loader = GsonHelper.getAsString(modelContents, "loader", null);
if (!Objects.equals(loader, ComputerCraftAPI.MOD_ID + ":turtle")) return null;
var model = new ResourceLocation(GsonHelper.getAsString(modelContents, "model"));
return new Unbaked(model);
} catch (IOException e) {
throw new ModelProviderException("Failed loading model " + path, e);
}
}
public static final class Unbaked implements UnbakedModel {
private final ResourceLocation model;
private Unbaked(ResourceLocation model) {
this.model = model;
}
@Override
public Collection<ResourceLocation> getDependencies() {
return List.of(model, COLOUR_TURTLE_MODEL);
}
@Override
public Collection<Material> getMaterials(Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
Set<Material> materials = new HashSet<>();
materials.addAll(modelGetter.apply(model).getMaterials(modelGetter, missingTextureErrors));
materials.addAll(modelGetter.apply(COLOUR_TURTLE_MODEL).getMaterials(modelGetter, missingTextureErrors));
return materials;
}
@Override
public BakedModel bake(ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState transform, ResourceLocation location) {
var mainModel = bakery.bake(model, transform);
if (mainModel == null) throw new NullPointerException(model + " failed to bake");
var colourModel = bakery.bake(COLOUR_TURTLE_MODEL, transform);
if (colourModel == null) throw new NullPointerException(COLOUR_TURTLE_MODEL + " failed to bake");
return new TurtleModel(mainModel, colourModel);
}
}
}

View File

@ -0,0 +1,25 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.platform;
import com.google.auto.service.AutoService;
import dan200.computercraft.shared.network.client.ClientNetworkContext;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvent;
import javax.annotation.Nullable;
@AutoService(ClientNetworkContext.class)
public class ClientNetworkHandlerImpl extends AbstractClientNetworkContext {
@Override
public void handlePlayRecord(BlockPos pos, @Nullable SoundEvent sound, @Nullable String name) {
var mc = Minecraft.getInstance();
mc.levelRenderer.playStreamingMusic(sound, pos);
if (name != null) mc.gui.setNowPlaying(Component.literal(name));
}
}

View File

@ -0,0 +1,30 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.platform;
import com.google.auto.service.AutoService;
import dan200.computercraft.shared.network.NetworkMessage;
import dan200.computercraft.shared.network.server.ServerNetworkContext;
import dan200.computercraft.shared.platform.NetworkHandler;
import net.fabricmc.fabric.api.client.model.BakedModelManagerHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.resources.ResourceLocation;
@AutoService(dan200.computercraft.impl.client.ClientPlatformHelper.class)
public class ClientPlatformHelperImpl implements ClientPlatformHelper {
@Override
public void sendToServer(NetworkMessage<ServerNetworkContext> message) {
Minecraft.getInstance().player.connection.send(NetworkHandler.encodeServer(message));
}
@Override
public BakedModel getModel(ModelManager manager, ResourceLocation location) {
var model = BakedModelManagerHelper.getModel(manager, location);
return model == null ? manager.getMissingModel() : model;
}
}

View File

@ -0,0 +1,67 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.mixin.client;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import dan200.computercraft.client.ClientHooks;
import net.minecraft.client.renderer.block.BlockModelShaper;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Provides custom block breaking progress for modems, so it only applies to the current part.
*
* @see BlockRenderDispatcher#renderBreakingTexture(BlockState, BlockPos, BlockAndTintGetter, PoseStack, VertexConsumer)
*/
@Mixin(BlockRenderDispatcher.class)
class BlockRenderDispatcherMixin {
@Shadow
@Final
private RandomSource random;
@Shadow
@Final
private BlockModelShaper blockModelShaper;
@Shadow
@Final
private ModelBlockRenderer modelRenderer;
@Inject(
method = "renderBreakingTexture",
at = @At("HEAD"),
cancellable = true,
require = 0 // This isn't critical functionality, so don't worry if we can't apply it.
)
@SuppressWarnings("UnusedMethod")
private void renderBlockDamage(
BlockState state, BlockPos pos, BlockAndTintGetter world, PoseStack pose, VertexConsumer buffers,
CallbackInfo info
) {
var newState = ClientHooks.getBlockBreakingState(state, pos);
if (newState != null) {
info.cancel();
var model = blockModelShaper.getBlockModel(newState);
modelRenderer.tesselateBlock(
world, model, newState, pos, pose, buffers, true, random, newState.getSeed(pos),
OverlayTexture.NO_OVERLAY
);
}
}
}

View File

@ -0,0 +1,24 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.mixin.client;
import dan200.computercraft.client.ClientHooks;
import net.minecraft.client.gui.components.DebugScreenOverlay;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Mixin(DebugScreenOverlay.class)
class DebugScreenOverlayMixin {
@Inject(method = "getSystemInformation", at = @At("RETURN"))
@SuppressWarnings("UnusedMethod")
private void appendDebugInfo(CallbackInfoReturnable<List<String>> cir) {
ClientHooks.addDebugInfo(cir.getReturnValue()::add);
}
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.mixin.client;
import dan200.computercraft.client.ClientRegistry;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.server.packs.resources.ResourceManager;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Map;
@Mixin(GameRenderer.class)
class GameRendererMixin {
@Final
@Shadow
@SuppressWarnings("NullAway")
private Map<String, ShaderInstance> shaders;
@Inject(method = "reloadShaders", at = @At(value = "TAIL"))
@SuppressWarnings("UnusedMethod")
private void onReloadShaders(ResourceManager resourceManager, CallbackInfo ci) {
try {
ClientRegistry.registerShaders(resourceManager, (shader, callback) -> {
shaders.put(shader.getName(), shader);
callback.accept(shader);
});
} catch (IOException e) {
throw new UncheckedIOException("Could not reload shaders", e);
}
}
}

View File

@ -0,0 +1,30 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.mixin.client;
import com.mojang.blaze3d.vertex.PoseStack;
import dan200.computercraft.client.ClientHooks;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.ItemFrameRenderer;
import net.minecraft.world.entity.decoration.ItemFrame;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ItemFrameRenderer.class)
@SuppressWarnings("UnusedMethod")
class ItemFrameRendererMixin {
@Inject(
method = "render(Lnet/minecraft/world/entity/decoration/ItemFrame;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lcom/mojang/math/Quaternion;)V", ordinal = 2, shift = At.Shift.AFTER),
cancellable = true
)
@SuppressWarnings("UnusedMethod")
private void render(ItemFrame entity, float yaw, float partialTicks, PoseStack pose, MultiBufferSource buffers, int light, CallbackInfo ci) {
if (ClientHooks.onRenderItemFrame(pose, buffers, entity, entity.getItem(), light)) ci.cancel();
}
}

View File

@ -0,0 +1,32 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.mixin.client;
import com.mojang.blaze3d.vertex.PoseStack;
import dan200.computercraft.client.ClientHooks;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ItemInHandRenderer.class)
class ItemInHandRendererMixin {
@Inject(method = "renderArmWithItem", at = @At("HEAD"), cancellable = true)
@SuppressWarnings("UnusedMethod")
private void onRenderItem(
AbstractClientPlayer player, float partialTicks, float pitch, InteractionHand hand, float swingProgress, ItemStack stack,
float equippedProgress, PoseStack transform, MultiBufferSource buffer, int combinedLight, CallbackInfo ci
) {
if (ClientHooks.onRenderHeldItem(transform, buffer, combinedLight, hand, pitch, equippedProgress, swingProgress, stack)) {
ci.cancel();
}
}
}

View File

@ -0,0 +1,30 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.mixin.client;
import dan200.computercraft.client.ClientHooks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Minecraft.class)
class MinecraftMixin {
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("HEAD"))
@SuppressWarnings("UnusedMethod")
private void clearLevel(Screen screen, CallbackInfo ci) {
ClientHooks.onWorldUnload();
}
@Inject(method = "setLevel", at = @At("HEAD"))
@SuppressWarnings("UnusedMethod")
private void setLevel(ClientLevel screen, CallbackInfo ci) {
ClientHooks.onWorldUnload();
}
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.mixin.client;
import dan200.computercraft.shared.FabricCommonHooks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.MultiPlayerGameMode;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(MultiPlayerGameMode.class)
class MultiPlayerGameModeMixin {
@Shadow
@Final
private Minecraft minecraft;
@Inject(
method = "destroyBlock",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"),
cancellable = true,
locals = LocalCapture.CAPTURE_FAILHARD
)
@SuppressWarnings("UnusedMethod")
private void onBlockBreak(BlockPos pos, CallbackInfoReturnable<Boolean> cir, Level level, BlockState state, Block block) {
if (!FabricCommonHooks.onBlockDestroy(level, minecraft.player, pos, state, null)) cir.setReturnValue(true);
}
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.mixin.client;
import com.mojang.blaze3d.audio.Channel;
import dan200.computercraft.client.sound.SpeakerManager;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.client.sounds.AudioStream;
import net.minecraft.client.sounds.SoundEngine;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable;
import static dan200.computercraft.core.util.Nullability.assertNonNull;
@Mixin(SoundEngine.class)
class SoundEngineMixin {
@Nullable
@Unique
private static SoundEngine self;
@Inject(method = "play", at = @At(value = "HEAD"))
@SuppressWarnings("UnusedMethod")
private void playSound(SoundInstance sound, CallbackInfo ci) {
self = (SoundEngine) (Object) this;
}
@Inject(at = @At("TAIL"), method = "method_19755")
@SuppressWarnings("UnusedMethod")
private static void onStream(AudioStream stream, Channel channel, CallbackInfo ci) {
SpeakerManager.onPlayStreaming(assertNonNull(self), channel, stream);
}
}

View File

@ -0,0 +1,19 @@
{
"required": true,
"package": "dan200.computercraft.mixin.client",
"minVersion": "0.8",
"compatibilityLevel": "JAVA_17",
"injectors": {
"defaultRequire": 1
},
"client": [
"BlockRenderDispatcherMixin",
"DebugScreenOverlayMixin",
"GameRendererMixin",
"ItemFrameRendererMixin",
"ItemInHandRendererMixin",
"MinecraftMixin",
"MultiPlayerGameModeMixin",
"SoundEngineMixin"
]
}

View File

@ -0,0 +1,125 @@
{
"multipart": [
{
"apply": {"model": "computercraft:block/cable_core_facing", "x": 90},
"when": {
"OR": [
{"cable": "true", "east": "false", "north": "false", "south": "false", "up": "true", "west": "false"},
{"cable": "true", "down": "true", "east": "false", "north": "false", "south": "false", "west": "false"}
]
}
},
{
"apply": {"model": "computercraft:block/cable_core_facing", "y": 0},
"when": {
"OR": [
{
"cable": "true",
"down": "false",
"east": "false",
"north": "false",
"south": "false",
"up": "false",
"west": "false"
},
{"cable": "true", "down": "false", "east": "false", "north": "true", "up": "false", "west": "false"},
{"cable": "true", "down": "false", "east": "false", "south": "true", "up": "false", "west": "false"}
]
}
},
{
"apply": {"model": "computercraft:block/cable_core_facing", "y": 90},
"when": {
"OR": [
{"cable": "true", "down": "false", "east": "true", "north": "false", "south": "false", "up": "false"},
{"cable": "true", "down": "false", "north": "false", "south": "false", "up": "false", "west": "true"}
]
}
},
{
"apply": {"model": "computercraft:block/cable_core_any"},
"when": {
"OR": [
{"cable": "true", "down": "true", "north": "true"},
{"cable": "true", "down": "true", "south": "true"},
{"cable": "true", "down": "true", "west": "true"},
{"cable": "true", "down": "true", "east": "true"},
{"cable": "true", "north": "true", "up": "true"},
{"cable": "true", "south": "true", "up": "true"},
{"cable": "true", "up": "true", "west": "true"},
{"cable": "true", "east": "true", "up": "true"},
{"cable": "true", "north": "true", "west": "true"},
{"cable": "true", "east": "true", "north": "true"},
{"cable": "true", "south": "true", "west": "true"},
{"cable": "true", "east": "true", "south": "true"}
]
}
},
{"apply": {"model": "computercraft:block/cable_arm", "x": 270, "y": 0}, "when": {"down": "true"}},
{"apply": {"model": "computercraft:block/cable_arm", "x": 90, "y": 0}, "when": {"up": "true"}},
{"apply": {"model": "computercraft:block/cable_arm", "x": 0, "y": 180}, "when": {"north": "true"}},
{"apply": {"model": "computercraft:block/cable_arm", "x": 0, "y": 0}, "when": {"south": "true"}},
{"apply": {"model": "computercraft:block/cable_arm", "x": 0, "y": 90}, "when": {"west": "true"}},
{"apply": {"model": "computercraft:block/cable_arm", "x": 0, "y": 270}, "when": {"east": "true"}},
{"apply": {"model": "computercraft:block/wired_modem_off", "x": 90, "y": 0}, "when": {"modem": "down_off"}},
{
"apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 90, "y": 0},
"when": {"modem": "down_off_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_on", "x": 90, "y": 0}, "when": {"modem": "down_on"}},
{
"apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 90, "y": 0},
"when": {"modem": "down_on_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_off", "x": 270, "y": 0}, "when": {"modem": "up_off"}},
{
"apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 270, "y": 0},
"when": {"modem": "up_off_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_on", "x": 270, "y": 0}, "when": {"modem": "up_on"}},
{
"apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 270, "y": 0},
"when": {"modem": "up_on_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_off", "x": 0, "y": 0}, "when": {"modem": "north_off"}},
{
"apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 0, "y": 0},
"when": {"modem": "north_off_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_on", "x": 0, "y": 0}, "when": {"modem": "north_on"}},
{
"apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 0, "y": 0},
"when": {"modem": "north_on_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_off", "x": 0, "y": 180}, "when": {"modem": "south_off"}},
{
"apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 0, "y": 180},
"when": {"modem": "south_off_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_on", "x": 0, "y": 180}, "when": {"modem": "south_on"}},
{
"apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 0, "y": 180},
"when": {"modem": "south_on_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_off", "x": 0, "y": 270}, "when": {"modem": "west_off"}},
{
"apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 0, "y": 270},
"when": {"modem": "west_off_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_on", "x": 0, "y": 270}, "when": {"modem": "west_on"}},
{
"apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 0, "y": 270},
"when": {"modem": "west_on_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_off", "x": 0, "y": 90}, "when": {"modem": "east_off"}},
{
"apply": {"model": "computercraft:block/wired_modem_off_peripheral", "x": 0, "y": 90},
"when": {"modem": "east_off_peripheral"}
},
{"apply": {"model": "computercraft:block/wired_modem_on", "x": 0, "y": 90}, "when": {"modem": "east_on"}},
{
"apply": {"model": "computercraft:block/wired_modem_on_peripheral", "x": 0, "y": 90},
"when": {"modem": "east_on_peripheral"}
}
]
}

View File

@ -0,0 +1,16 @@
{
"variants": {
"facing=east,state=blinking": {"model": "computercraft:block/computer_advanced_blinking", "y": 90},
"facing=east,state=off": {"model": "computercraft:block/computer_advanced_off", "y": 90},
"facing=east,state=on": {"model": "computercraft:block/computer_advanced_on", "y": 90},
"facing=north,state=blinking": {"model": "computercraft:block/computer_advanced_blinking", "y": 0},
"facing=north,state=off": {"model": "computercraft:block/computer_advanced_off", "y": 0},
"facing=north,state=on": {"model": "computercraft:block/computer_advanced_on", "y": 0},
"facing=south,state=blinking": {"model": "computercraft:block/computer_advanced_blinking", "y": 180},
"facing=south,state=off": {"model": "computercraft:block/computer_advanced_off", "y": 180},
"facing=south,state=on": {"model": "computercraft:block/computer_advanced_on", "y": 180},
"facing=west,state=blinking": {"model": "computercraft:block/computer_advanced_blinking", "y": 270},
"facing=west,state=off": {"model": "computercraft:block/computer_advanced_off", "y": 270},
"facing=west,state=on": {"model": "computercraft:block/computer_advanced_on", "y": 270}
}
}

View File

@ -0,0 +1,16 @@
{
"variants": {
"facing=east,state=blinking": {"model": "computercraft:block/computer_command_blinking", "y": 90},
"facing=east,state=off": {"model": "computercraft:block/computer_command_off", "y": 90},
"facing=east,state=on": {"model": "computercraft:block/computer_command_on", "y": 90},
"facing=north,state=blinking": {"model": "computercraft:block/computer_command_blinking", "y": 0},
"facing=north,state=off": {"model": "computercraft:block/computer_command_off", "y": 0},
"facing=north,state=on": {"model": "computercraft:block/computer_command_on", "y": 0},
"facing=south,state=blinking": {"model": "computercraft:block/computer_command_blinking", "y": 180},
"facing=south,state=off": {"model": "computercraft:block/computer_command_off", "y": 180},
"facing=south,state=on": {"model": "computercraft:block/computer_command_on", "y": 180},
"facing=west,state=blinking": {"model": "computercraft:block/computer_command_blinking", "y": 270},
"facing=west,state=off": {"model": "computercraft:block/computer_command_off", "y": 270},
"facing=west,state=on": {"model": "computercraft:block/computer_command_on", "y": 270}
}
}

View File

@ -0,0 +1,16 @@
{
"variants": {
"facing=east,state=blinking": {"model": "computercraft:block/computer_normal_blinking", "y": 90},
"facing=east,state=off": {"model": "computercraft:block/computer_normal_off", "y": 90},
"facing=east,state=on": {"model": "computercraft:block/computer_normal_on", "y": 90},
"facing=north,state=blinking": {"model": "computercraft:block/computer_normal_blinking", "y": 0},
"facing=north,state=off": {"model": "computercraft:block/computer_normal_off", "y": 0},
"facing=north,state=on": {"model": "computercraft:block/computer_normal_on", "y": 0},
"facing=south,state=blinking": {"model": "computercraft:block/computer_normal_blinking", "y": 180},
"facing=south,state=off": {"model": "computercraft:block/computer_normal_off", "y": 180},
"facing=south,state=on": {"model": "computercraft:block/computer_normal_on", "y": 180},
"facing=west,state=blinking": {"model": "computercraft:block/computer_normal_blinking", "y": 270},
"facing=west,state=off": {"model": "computercraft:block/computer_normal_off", "y": 270},
"facing=west,state=on": {"model": "computercraft:block/computer_normal_on", "y": 270}
}
}

View File

@ -0,0 +1,16 @@
{
"variants": {
"facing=east,state=empty": {"model": "computercraft:block/disk_drive_empty", "y": 90},
"facing=east,state=full": {"model": "computercraft:block/disk_drive_full", "y": 90},
"facing=east,state=invalid": {"model": "computercraft:block/disk_drive_invalid", "y": 90},
"facing=north,state=empty": {"model": "computercraft:block/disk_drive_empty", "y": 0},
"facing=north,state=full": {"model": "computercraft:block/disk_drive_full", "y": 0},
"facing=north,state=invalid": {"model": "computercraft:block/disk_drive_invalid", "y": 0},
"facing=south,state=empty": {"model": "computercraft:block/disk_drive_empty", "y": 180},
"facing=south,state=full": {"model": "computercraft:block/disk_drive_full", "y": 180},
"facing=south,state=invalid": {"model": "computercraft:block/disk_drive_invalid", "y": 180},
"facing=west,state=empty": {"model": "computercraft:block/disk_drive_empty", "y": 270},
"facing=west,state=full": {"model": "computercraft:block/disk_drive_full", "y": 270},
"facing=west,state=invalid": {"model": "computercraft:block/disk_drive_invalid", "y": 270}
}
}

View File

@ -0,0 +1,268 @@
{
"variants": {
"facing=east,orientation=down,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 90, "y": 90},
"facing=east,orientation=down,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 90, "y": 90},
"facing=east,orientation=down,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 90, "y": 90},
"facing=east,orientation=down,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 90, "y": 90},
"facing=east,orientation=down,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 90, "y": 90},
"facing=east,orientation=down,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 90, "y": 90},
"facing=east,orientation=down,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 90,
"y": 90
},
"facing=east,orientation=down,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 90, "y": 90},
"facing=east,orientation=down,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 90, "y": 90},
"facing=east,orientation=down,state=none": {"model": "computercraft:block/monitor_advanced", "x": 90, "y": 90},
"facing=east,orientation=down,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 90, "y": 90},
"facing=east,orientation=down,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 90, "y": 90},
"facing=east,orientation=down,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 90, "y": 90},
"facing=east,orientation=down,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 90, "y": 90},
"facing=east,orientation=down,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 90, "y": 90},
"facing=east,orientation=down,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 90, "y": 90},
"facing=east,orientation=north,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 0, "y": 90},
"facing=east,orientation=north,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 0, "y": 90},
"facing=east,orientation=north,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 0, "y": 90},
"facing=east,orientation=north,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 0, "y": 90},
"facing=east,orientation=north,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 0, "y": 90},
"facing=east,orientation=north,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 0, "y": 90},
"facing=east,orientation=north,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 0,
"y": 90
},
"facing=east,orientation=north,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 0, "y": 90},
"facing=east,orientation=north,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 0, "y": 90},
"facing=east,orientation=north,state=none": {"model": "computercraft:block/monitor_advanced", "x": 0, "y": 90},
"facing=east,orientation=north,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 0, "y": 90},
"facing=east,orientation=north,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 0, "y": 90},
"facing=east,orientation=north,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 0, "y": 90},
"facing=east,orientation=north,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 0, "y": 90},
"facing=east,orientation=north,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 0, "y": 90},
"facing=east,orientation=north,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 0, "y": 90},
"facing=east,orientation=up,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 270, "y": 90},
"facing=east,orientation=up,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 270, "y": 90},
"facing=east,orientation=up,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 270, "y": 90},
"facing=east,orientation=up,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 270, "y": 90},
"facing=east,orientation=up,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 270, "y": 90},
"facing=east,orientation=up,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 270, "y": 90},
"facing=east,orientation=up,state=lrud": {"model": "computercraft:block/monitor_advanced_lrud", "x": 270, "y": 90},
"facing=east,orientation=up,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 270, "y": 90},
"facing=east,orientation=up,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 270, "y": 90},
"facing=east,orientation=up,state=none": {"model": "computercraft:block/monitor_advanced", "x": 270, "y": 90},
"facing=east,orientation=up,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 270, "y": 90},
"facing=east,orientation=up,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 270, "y": 90},
"facing=east,orientation=up,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 270, "y": 90},
"facing=east,orientation=up,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 270, "y": 90},
"facing=east,orientation=up,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 270, "y": 90},
"facing=east,orientation=up,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 270, "y": 90},
"facing=north,orientation=down,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 90, "y": 0},
"facing=north,orientation=down,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 90, "y": 0},
"facing=north,orientation=down,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 90, "y": 0},
"facing=north,orientation=down,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 90, "y": 0},
"facing=north,orientation=down,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 90, "y": 0},
"facing=north,orientation=down,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 90, "y": 0},
"facing=north,orientation=down,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 90,
"y": 0
},
"facing=north,orientation=down,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 90, "y": 0},
"facing=north,orientation=down,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 90, "y": 0},
"facing=north,orientation=down,state=none": {"model": "computercraft:block/monitor_advanced", "x": 90, "y": 0},
"facing=north,orientation=down,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 90, "y": 0},
"facing=north,orientation=down,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 90, "y": 0},
"facing=north,orientation=down,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 90, "y": 0},
"facing=north,orientation=down,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 90, "y": 0},
"facing=north,orientation=down,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 90, "y": 0},
"facing=north,orientation=down,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 90, "y": 0},
"facing=north,orientation=north,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 0, "y": 0},
"facing=north,orientation=north,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 0, "y": 0},
"facing=north,orientation=north,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 0, "y": 0},
"facing=north,orientation=north,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 0, "y": 0},
"facing=north,orientation=north,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 0, "y": 0},
"facing=north,orientation=north,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 0, "y": 0},
"facing=north,orientation=north,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 0,
"y": 0
},
"facing=north,orientation=north,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 0, "y": 0},
"facing=north,orientation=north,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 0, "y": 0},
"facing=north,orientation=north,state=none": {"model": "computercraft:block/monitor_advanced", "x": 0, "y": 0},
"facing=north,orientation=north,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 0, "y": 0},
"facing=north,orientation=north,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 0, "y": 0},
"facing=north,orientation=north,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 0, "y": 0},
"facing=north,orientation=north,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 0, "y": 0},
"facing=north,orientation=north,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 0, "y": 0},
"facing=north,orientation=north,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 0, "y": 0},
"facing=north,orientation=up,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 270, "y": 0},
"facing=north,orientation=up,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 270, "y": 0},
"facing=north,orientation=up,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 270, "y": 0},
"facing=north,orientation=up,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 270, "y": 0},
"facing=north,orientation=up,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 270, "y": 0},
"facing=north,orientation=up,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 270, "y": 0},
"facing=north,orientation=up,state=lrud": {"model": "computercraft:block/monitor_advanced_lrud", "x": 270, "y": 0},
"facing=north,orientation=up,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 270, "y": 0},
"facing=north,orientation=up,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 270, "y": 0},
"facing=north,orientation=up,state=none": {"model": "computercraft:block/monitor_advanced", "x": 270, "y": 0},
"facing=north,orientation=up,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 270, "y": 0},
"facing=north,orientation=up,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 270, "y": 0},
"facing=north,orientation=up,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 270, "y": 0},
"facing=north,orientation=up,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 270, "y": 0},
"facing=north,orientation=up,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 270, "y": 0},
"facing=north,orientation=up,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 270, "y": 0},
"facing=south,orientation=down,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 90, "y": 180},
"facing=south,orientation=down,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 90, "y": 180},
"facing=south,orientation=down,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 90, "y": 180},
"facing=south,orientation=down,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 90, "y": 180},
"facing=south,orientation=down,state=lrd": {
"model": "computercraft:block/monitor_advanced_lrd",
"x": 90,
"y": 180
},
"facing=south,orientation=down,state=lru": {
"model": "computercraft:block/monitor_advanced_lru",
"x": 90,
"y": 180
},
"facing=south,orientation=down,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 90,
"y": 180
},
"facing=south,orientation=down,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 90, "y": 180},
"facing=south,orientation=down,state=lud": {
"model": "computercraft:block/monitor_advanced_lud",
"x": 90,
"y": 180
},
"facing=south,orientation=down,state=none": {"model": "computercraft:block/monitor_advanced", "x": 90, "y": 180},
"facing=south,orientation=down,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 90, "y": 180},
"facing=south,orientation=down,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 90, "y": 180},
"facing=south,orientation=down,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 90, "y": 180},
"facing=south,orientation=down,state=rud": {
"model": "computercraft:block/monitor_advanced_rud",
"x": 90,
"y": 180
},
"facing=south,orientation=down,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 90, "y": 180},
"facing=south,orientation=down,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 90, "y": 180},
"facing=south,orientation=north,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 0, "y": 180},
"facing=south,orientation=north,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 0, "y": 180},
"facing=south,orientation=north,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 0, "y": 180},
"facing=south,orientation=north,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 0, "y": 180},
"facing=south,orientation=north,state=lrd": {
"model": "computercraft:block/monitor_advanced_lrd",
"x": 0,
"y": 180
},
"facing=south,orientation=north,state=lru": {
"model": "computercraft:block/monitor_advanced_lru",
"x": 0,
"y": 180
},
"facing=south,orientation=north,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 0,
"y": 180
},
"facing=south,orientation=north,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 0, "y": 180},
"facing=south,orientation=north,state=lud": {
"model": "computercraft:block/monitor_advanced_lud",
"x": 0,
"y": 180
},
"facing=south,orientation=north,state=none": {"model": "computercraft:block/monitor_advanced", "x": 0, "y": 180},
"facing=south,orientation=north,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 0, "y": 180},
"facing=south,orientation=north,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 0, "y": 180},
"facing=south,orientation=north,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 0, "y": 180},
"facing=south,orientation=north,state=rud": {
"model": "computercraft:block/monitor_advanced_rud",
"x": 0,
"y": 180
},
"facing=south,orientation=north,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 0, "y": 180},
"facing=south,orientation=north,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 0, "y": 180},
"facing=south,orientation=up,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 270, "y": 180},
"facing=south,orientation=up,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 270, "y": 180},
"facing=south,orientation=up,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 270, "y": 180},
"facing=south,orientation=up,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 270, "y": 180},
"facing=south,orientation=up,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 270, "y": 180},
"facing=south,orientation=up,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 270, "y": 180},
"facing=south,orientation=up,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 270,
"y": 180
},
"facing=south,orientation=up,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 270, "y": 180},
"facing=south,orientation=up,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 270, "y": 180},
"facing=south,orientation=up,state=none": {"model": "computercraft:block/monitor_advanced", "x": 270, "y": 180},
"facing=south,orientation=up,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 270, "y": 180},
"facing=south,orientation=up,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 270, "y": 180},
"facing=south,orientation=up,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 270, "y": 180},
"facing=south,orientation=up,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 270, "y": 180},
"facing=south,orientation=up,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 270, "y": 180},
"facing=south,orientation=up,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 270, "y": 180},
"facing=west,orientation=down,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 90, "y": 270},
"facing=west,orientation=down,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 90, "y": 270},
"facing=west,orientation=down,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 90, "y": 270},
"facing=west,orientation=down,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 90, "y": 270},
"facing=west,orientation=down,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 90, "y": 270},
"facing=west,orientation=down,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 90, "y": 270},
"facing=west,orientation=down,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 90,
"y": 270
},
"facing=west,orientation=down,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 90, "y": 270},
"facing=west,orientation=down,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 90, "y": 270},
"facing=west,orientation=down,state=none": {"model": "computercraft:block/monitor_advanced", "x": 90, "y": 270},
"facing=west,orientation=down,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 90, "y": 270},
"facing=west,orientation=down,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 90, "y": 270},
"facing=west,orientation=down,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 90, "y": 270},
"facing=west,orientation=down,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 90, "y": 270},
"facing=west,orientation=down,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 90, "y": 270},
"facing=west,orientation=down,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 90, "y": 270},
"facing=west,orientation=north,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 0, "y": 270},
"facing=west,orientation=north,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 0, "y": 270},
"facing=west,orientation=north,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 0, "y": 270},
"facing=west,orientation=north,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 0, "y": 270},
"facing=west,orientation=north,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 0, "y": 270},
"facing=west,orientation=north,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 0, "y": 270},
"facing=west,orientation=north,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 0,
"y": 270
},
"facing=west,orientation=north,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 0, "y": 270},
"facing=west,orientation=north,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 0, "y": 270},
"facing=west,orientation=north,state=none": {"model": "computercraft:block/monitor_advanced", "x": 0, "y": 270},
"facing=west,orientation=north,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 0, "y": 270},
"facing=west,orientation=north,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 0, "y": 270},
"facing=west,orientation=north,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 0, "y": 270},
"facing=west,orientation=north,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 0, "y": 270},
"facing=west,orientation=north,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 0, "y": 270},
"facing=west,orientation=north,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 0, "y": 270},
"facing=west,orientation=up,state=d": {"model": "computercraft:block/monitor_advanced_d", "x": 270, "y": 270},
"facing=west,orientation=up,state=l": {"model": "computercraft:block/monitor_advanced_l", "x": 270, "y": 270},
"facing=west,orientation=up,state=ld": {"model": "computercraft:block/monitor_advanced_ld", "x": 270, "y": 270},
"facing=west,orientation=up,state=lr": {"model": "computercraft:block/monitor_advanced_lr", "x": 270, "y": 270},
"facing=west,orientation=up,state=lrd": {"model": "computercraft:block/monitor_advanced_lrd", "x": 270, "y": 270},
"facing=west,orientation=up,state=lru": {"model": "computercraft:block/monitor_advanced_lru", "x": 270, "y": 270},
"facing=west,orientation=up,state=lrud": {
"model": "computercraft:block/monitor_advanced_lrud",
"x": 270,
"y": 270
},
"facing=west,orientation=up,state=lu": {"model": "computercraft:block/monitor_advanced_lu", "x": 270, "y": 270},
"facing=west,orientation=up,state=lud": {"model": "computercraft:block/monitor_advanced_lud", "x": 270, "y": 270},
"facing=west,orientation=up,state=none": {"model": "computercraft:block/monitor_advanced", "x": 270, "y": 270},
"facing=west,orientation=up,state=r": {"model": "computercraft:block/monitor_advanced_r", "x": 270, "y": 270},
"facing=west,orientation=up,state=rd": {"model": "computercraft:block/monitor_advanced_rd", "x": 270, "y": 270},
"facing=west,orientation=up,state=ru": {"model": "computercraft:block/monitor_advanced_ru", "x": 270, "y": 270},
"facing=west,orientation=up,state=rud": {"model": "computercraft:block/monitor_advanced_rud", "x": 270, "y": 270},
"facing=west,orientation=up,state=u": {"model": "computercraft:block/monitor_advanced_u", "x": 270, "y": 270},
"facing=west,orientation=up,state=ud": {"model": "computercraft:block/monitor_advanced_ud", "x": 270, "y": 270}
}
}

View File

@ -0,0 +1,204 @@
{
"variants": {
"facing=east,orientation=down,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 90, "y": 90},
"facing=east,orientation=down,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 90, "y": 90},
"facing=east,orientation=down,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 90, "y": 90},
"facing=east,orientation=down,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 90, "y": 90},
"facing=east,orientation=down,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 90, "y": 90},
"facing=east,orientation=down,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 90, "y": 90},
"facing=east,orientation=down,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 90, "y": 90},
"facing=east,orientation=down,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 90, "y": 90},
"facing=east,orientation=down,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 90, "y": 90},
"facing=east,orientation=down,state=none": {"model": "computercraft:block/monitor_normal", "x": 90, "y": 90},
"facing=east,orientation=down,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 90, "y": 90},
"facing=east,orientation=down,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 90, "y": 90},
"facing=east,orientation=down,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 90, "y": 90},
"facing=east,orientation=down,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 90, "y": 90},
"facing=east,orientation=down,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 90, "y": 90},
"facing=east,orientation=down,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 90, "y": 90},
"facing=east,orientation=north,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 0, "y": 90},
"facing=east,orientation=north,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 0, "y": 90},
"facing=east,orientation=north,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 0, "y": 90},
"facing=east,orientation=north,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 0, "y": 90},
"facing=east,orientation=north,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 0, "y": 90},
"facing=east,orientation=north,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 0, "y": 90},
"facing=east,orientation=north,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 0, "y": 90},
"facing=east,orientation=north,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 0, "y": 90},
"facing=east,orientation=north,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 0, "y": 90},
"facing=east,orientation=north,state=none": {"model": "computercraft:block/monitor_normal", "x": 0, "y": 90},
"facing=east,orientation=north,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 0, "y": 90},
"facing=east,orientation=north,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 0, "y": 90},
"facing=east,orientation=north,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 0, "y": 90},
"facing=east,orientation=north,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 0, "y": 90},
"facing=east,orientation=north,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 0, "y": 90},
"facing=east,orientation=north,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 0, "y": 90},
"facing=east,orientation=up,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 270, "y": 90},
"facing=east,orientation=up,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 270, "y": 90},
"facing=east,orientation=up,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 270, "y": 90},
"facing=east,orientation=up,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 270, "y": 90},
"facing=east,orientation=up,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 270, "y": 90},
"facing=east,orientation=up,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 270, "y": 90},
"facing=east,orientation=up,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 270, "y": 90},
"facing=east,orientation=up,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 270, "y": 90},
"facing=east,orientation=up,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 270, "y": 90},
"facing=east,orientation=up,state=none": {"model": "computercraft:block/monitor_normal", "x": 270, "y": 90},
"facing=east,orientation=up,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 270, "y": 90},
"facing=east,orientation=up,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 270, "y": 90},
"facing=east,orientation=up,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 270, "y": 90},
"facing=east,orientation=up,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 270, "y": 90},
"facing=east,orientation=up,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 270, "y": 90},
"facing=east,orientation=up,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 270, "y": 90},
"facing=north,orientation=down,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 90, "y": 0},
"facing=north,orientation=down,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 90, "y": 0},
"facing=north,orientation=down,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 90, "y": 0},
"facing=north,orientation=down,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 90, "y": 0},
"facing=north,orientation=down,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 90, "y": 0},
"facing=north,orientation=down,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 90, "y": 0},
"facing=north,orientation=down,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 90, "y": 0},
"facing=north,orientation=down,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 90, "y": 0},
"facing=north,orientation=down,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 90, "y": 0},
"facing=north,orientation=down,state=none": {"model": "computercraft:block/monitor_normal", "x": 90, "y": 0},
"facing=north,orientation=down,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 90, "y": 0},
"facing=north,orientation=down,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 90, "y": 0},
"facing=north,orientation=down,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 90, "y": 0},
"facing=north,orientation=down,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 90, "y": 0},
"facing=north,orientation=down,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 90, "y": 0},
"facing=north,orientation=down,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 90, "y": 0},
"facing=north,orientation=north,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 0, "y": 0},
"facing=north,orientation=north,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 0, "y": 0},
"facing=north,orientation=north,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 0, "y": 0},
"facing=north,orientation=north,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 0, "y": 0},
"facing=north,orientation=north,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 0, "y": 0},
"facing=north,orientation=north,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 0, "y": 0},
"facing=north,orientation=north,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 0, "y": 0},
"facing=north,orientation=north,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 0, "y": 0},
"facing=north,orientation=north,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 0, "y": 0},
"facing=north,orientation=north,state=none": {"model": "computercraft:block/monitor_normal", "x": 0, "y": 0},
"facing=north,orientation=north,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 0, "y": 0},
"facing=north,orientation=north,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 0, "y": 0},
"facing=north,orientation=north,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 0, "y": 0},
"facing=north,orientation=north,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 0, "y": 0},
"facing=north,orientation=north,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 0, "y": 0},
"facing=north,orientation=north,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 0, "y": 0},
"facing=north,orientation=up,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 270, "y": 0},
"facing=north,orientation=up,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 270, "y": 0},
"facing=north,orientation=up,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 270, "y": 0},
"facing=north,orientation=up,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 270, "y": 0},
"facing=north,orientation=up,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 270, "y": 0},
"facing=north,orientation=up,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 270, "y": 0},
"facing=north,orientation=up,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 270, "y": 0},
"facing=north,orientation=up,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 270, "y": 0},
"facing=north,orientation=up,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 270, "y": 0},
"facing=north,orientation=up,state=none": {"model": "computercraft:block/monitor_normal", "x": 270, "y": 0},
"facing=north,orientation=up,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 270, "y": 0},
"facing=north,orientation=up,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 270, "y": 0},
"facing=north,orientation=up,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 270, "y": 0},
"facing=north,orientation=up,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 270, "y": 0},
"facing=north,orientation=up,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 270, "y": 0},
"facing=north,orientation=up,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 270, "y": 0},
"facing=south,orientation=down,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 90, "y": 180},
"facing=south,orientation=down,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 90, "y": 180},
"facing=south,orientation=down,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 90, "y": 180},
"facing=south,orientation=down,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 90, "y": 180},
"facing=south,orientation=down,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 90, "y": 180},
"facing=south,orientation=down,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 90, "y": 180},
"facing=south,orientation=down,state=lrud": {
"model": "computercraft:block/monitor_normal_lrud",
"x": 90,
"y": 180
},
"facing=south,orientation=down,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 90, "y": 180},
"facing=south,orientation=down,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 90, "y": 180},
"facing=south,orientation=down,state=none": {"model": "computercraft:block/monitor_normal", "x": 90, "y": 180},
"facing=south,orientation=down,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 90, "y": 180},
"facing=south,orientation=down,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 90, "y": 180},
"facing=south,orientation=down,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 90, "y": 180},
"facing=south,orientation=down,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 90, "y": 180},
"facing=south,orientation=down,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 90, "y": 180},
"facing=south,orientation=down,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 90, "y": 180},
"facing=south,orientation=north,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 0, "y": 180},
"facing=south,orientation=north,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 0, "y": 180},
"facing=south,orientation=north,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 0, "y": 180},
"facing=south,orientation=north,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 0, "y": 180},
"facing=south,orientation=north,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 0, "y": 180},
"facing=south,orientation=north,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 0, "y": 180},
"facing=south,orientation=north,state=lrud": {
"model": "computercraft:block/monitor_normal_lrud",
"x": 0,
"y": 180
},
"facing=south,orientation=north,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 0, "y": 180},
"facing=south,orientation=north,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 0, "y": 180},
"facing=south,orientation=north,state=none": {"model": "computercraft:block/monitor_normal", "x": 0, "y": 180},
"facing=south,orientation=north,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 0, "y": 180},
"facing=south,orientation=north,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 0, "y": 180},
"facing=south,orientation=north,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 0, "y": 180},
"facing=south,orientation=north,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 0, "y": 180},
"facing=south,orientation=north,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 0, "y": 180},
"facing=south,orientation=north,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 0, "y": 180},
"facing=south,orientation=up,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 270, "y": 180},
"facing=south,orientation=up,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 270, "y": 180},
"facing=south,orientation=up,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 270, "y": 180},
"facing=south,orientation=up,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 270, "y": 180},
"facing=south,orientation=up,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 270, "y": 180},
"facing=south,orientation=up,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 270, "y": 180},
"facing=south,orientation=up,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 270, "y": 180},
"facing=south,orientation=up,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 270, "y": 180},
"facing=south,orientation=up,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 270, "y": 180},
"facing=south,orientation=up,state=none": {"model": "computercraft:block/monitor_normal", "x": 270, "y": 180},
"facing=south,orientation=up,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 270, "y": 180},
"facing=south,orientation=up,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 270, "y": 180},
"facing=south,orientation=up,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 270, "y": 180},
"facing=south,orientation=up,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 270, "y": 180},
"facing=south,orientation=up,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 270, "y": 180},
"facing=south,orientation=up,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 270, "y": 180},
"facing=west,orientation=down,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 90, "y": 270},
"facing=west,orientation=down,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 90, "y": 270},
"facing=west,orientation=down,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 90, "y": 270},
"facing=west,orientation=down,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 90, "y": 270},
"facing=west,orientation=down,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 90, "y": 270},
"facing=west,orientation=down,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 90, "y": 270},
"facing=west,orientation=down,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 90, "y": 270},
"facing=west,orientation=down,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 90, "y": 270},
"facing=west,orientation=down,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 90, "y": 270},
"facing=west,orientation=down,state=none": {"model": "computercraft:block/monitor_normal", "x": 90, "y": 270},
"facing=west,orientation=down,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 90, "y": 270},
"facing=west,orientation=down,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 90, "y": 270},
"facing=west,orientation=down,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 90, "y": 270},
"facing=west,orientation=down,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 90, "y": 270},
"facing=west,orientation=down,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 90, "y": 270},
"facing=west,orientation=down,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 90, "y": 270},
"facing=west,orientation=north,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 0, "y": 270},
"facing=west,orientation=north,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 0, "y": 270},
"facing=west,orientation=north,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 0, "y": 270},
"facing=west,orientation=north,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 0, "y": 270},
"facing=west,orientation=north,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 0, "y": 270},
"facing=west,orientation=north,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 0, "y": 270},
"facing=west,orientation=north,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 0, "y": 270},
"facing=west,orientation=north,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 0, "y": 270},
"facing=west,orientation=north,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 0, "y": 270},
"facing=west,orientation=north,state=none": {"model": "computercraft:block/monitor_normal", "x": 0, "y": 270},
"facing=west,orientation=north,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 0, "y": 270},
"facing=west,orientation=north,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 0, "y": 270},
"facing=west,orientation=north,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 0, "y": 270},
"facing=west,orientation=north,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 0, "y": 270},
"facing=west,orientation=north,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 0, "y": 270},
"facing=west,orientation=north,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 0, "y": 270},
"facing=west,orientation=up,state=d": {"model": "computercraft:block/monitor_normal_d", "x": 270, "y": 270},
"facing=west,orientation=up,state=l": {"model": "computercraft:block/monitor_normal_l", "x": 270, "y": 270},
"facing=west,orientation=up,state=ld": {"model": "computercraft:block/monitor_normal_ld", "x": 270, "y": 270},
"facing=west,orientation=up,state=lr": {"model": "computercraft:block/monitor_normal_lr", "x": 270, "y": 270},
"facing=west,orientation=up,state=lrd": {"model": "computercraft:block/monitor_normal_lrd", "x": 270, "y": 270},
"facing=west,orientation=up,state=lru": {"model": "computercraft:block/monitor_normal_lru", "x": 270, "y": 270},
"facing=west,orientation=up,state=lrud": {"model": "computercraft:block/monitor_normal_lrud", "x": 270, "y": 270},
"facing=west,orientation=up,state=lu": {"model": "computercraft:block/monitor_normal_lu", "x": 270, "y": 270},
"facing=west,orientation=up,state=lud": {"model": "computercraft:block/monitor_normal_lud", "x": 270, "y": 270},
"facing=west,orientation=up,state=none": {"model": "computercraft:block/monitor_normal", "x": 270, "y": 270},
"facing=west,orientation=up,state=r": {"model": "computercraft:block/monitor_normal_r", "x": 270, "y": 270},
"facing=west,orientation=up,state=rd": {"model": "computercraft:block/monitor_normal_rd", "x": 270, "y": 270},
"facing=west,orientation=up,state=ru": {"model": "computercraft:block/monitor_normal_ru", "x": 270, "y": 270},
"facing=west,orientation=up,state=rud": {"model": "computercraft:block/monitor_normal_rud", "x": 270, "y": 270},
"facing=west,orientation=up,state=u": {"model": "computercraft:block/monitor_normal_u", "x": 270, "y": 270},
"facing=west,orientation=up,state=ud": {"model": "computercraft:block/monitor_normal_ud", "x": 270, "y": 270}
}
}

View File

@ -0,0 +1,20 @@
{
"variants": {
"bottom=false,facing=east,top=false": {"model": "computercraft:block/printer_empty", "y": 90},
"bottom=false,facing=east,top=true": {"model": "computercraft:block/printer_top_full", "y": 90},
"bottom=false,facing=north,top=false": {"model": "computercraft:block/printer_empty", "y": 0},
"bottom=false,facing=north,top=true": {"model": "computercraft:block/printer_top_full", "y": 0},
"bottom=false,facing=south,top=false": {"model": "computercraft:block/printer_empty", "y": 180},
"bottom=false,facing=south,top=true": {"model": "computercraft:block/printer_top_full", "y": 180},
"bottom=false,facing=west,top=false": {"model": "computercraft:block/printer_empty", "y": 270},
"bottom=false,facing=west,top=true": {"model": "computercraft:block/printer_top_full", "y": 270},
"bottom=true,facing=east,top=false": {"model": "computercraft:block/printer_bottom_full", "y": 90},
"bottom=true,facing=east,top=true": {"model": "computercraft:block/printer_both_full", "y": 90},
"bottom=true,facing=north,top=false": {"model": "computercraft:block/printer_bottom_full", "y": 0},
"bottom=true,facing=north,top=true": {"model": "computercraft:block/printer_both_full", "y": 0},
"bottom=true,facing=south,top=false": {"model": "computercraft:block/printer_bottom_full", "y": 180},
"bottom=true,facing=south,top=true": {"model": "computercraft:block/printer_both_full", "y": 180},
"bottom=true,facing=west,top=false": {"model": "computercraft:block/printer_bottom_full", "y": 270},
"bottom=true,facing=west,top=true": {"model": "computercraft:block/printer_both_full", "y": 270}
}
}

View File

@ -0,0 +1,8 @@
{
"variants": {
"facing=east": {"model": "computercraft:block/speaker", "y": 90},
"facing=north": {"model": "computercraft:block/speaker"},
"facing=south": {"model": "computercraft:block/speaker", "y": 180},
"facing=west": {"model": "computercraft:block/speaker", "y": 270}
}
}

View File

@ -0,0 +1,8 @@
{
"variants": {
"facing=east": {"model": "computercraft:block/turtle_advanced", "y": 90},
"facing=north": {"model": "computercraft:block/turtle_advanced", "y": 0},
"facing=south": {"model": "computercraft:block/turtle_advanced", "y": 180},
"facing=west": {"model": "computercraft:block/turtle_advanced", "y": 270}
}
}

View File

@ -0,0 +1,8 @@
{
"variants": {
"facing=east": {"model": "computercraft:block/turtle_normal", "y": 90},
"facing=north": {"model": "computercraft:block/turtle_normal", "y": 0},
"facing=south": {"model": "computercraft:block/turtle_normal", "y": 180},
"facing=west": {"model": "computercraft:block/turtle_normal", "y": 270}
}
}

View File

@ -0,0 +1,8 @@
{
"variants": {
"modem=false,peripheral=false": {"model": "computercraft:block/wired_modem_full_off"},
"modem=false,peripheral=true": {"model": "computercraft:block/wired_modem_full_off_peripheral"},
"modem=true,peripheral=false": {"model": "computercraft:block/wired_modem_full_on"},
"modem=true,peripheral=true": {"model": "computercraft:block/wired_modem_full_on_peripheral"}
}
}

View File

@ -0,0 +1,16 @@
{
"variants": {
"facing=down,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 90, "y": 0},
"facing=down,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 90, "y": 0},
"facing=east,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 0, "y": 90},
"facing=east,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 0, "y": 90},
"facing=north,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 0, "y": 0},
"facing=north,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 0, "y": 0},
"facing=south,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 0, "y": 180},
"facing=south,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 0, "y": 180},
"facing=up,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 270, "y": 0},
"facing=up,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 270, "y": 0},
"facing=west,on=false": {"model": "computercraft:block/wireless_modem_advanced_off", "x": 0, "y": 270},
"facing=west,on=true": {"model": "computercraft:block/wireless_modem_advanced_on", "x": 0, "y": 270}
}
}

View File

@ -0,0 +1,16 @@
{
"variants": {
"facing=down,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 90, "y": 0},
"facing=down,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 90, "y": 0},
"facing=east,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 0, "y": 90},
"facing=east,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 0, "y": 90},
"facing=north,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 0, "y": 0},
"facing=north,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 0, "y": 0},
"facing=south,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 0, "y": 180},
"facing=south,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 0, "y": 180},
"facing=up,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 270, "y": 0},
"facing=up,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 270, "y": 0},
"facing=west,on=false": {"model": "computercraft:block/wireless_modem_normal_off", "x": 0, "y": 270},
"facing=west,on=true": {"model": "computercraft:block/wireless_modem_normal_on", "x": 0, "y": 270}
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_advanced_front_blink",
"side": "computercraft:block/computer_advanced_side",
"top": "computercraft:block/computer_advanced_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_advanced_front",
"side": "computercraft:block/computer_advanced_side",
"top": "computercraft:block/computer_advanced_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_advanced_front_on",
"side": "computercraft:block/computer_advanced_side",
"top": "computercraft:block/computer_advanced_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_command_front_blink",
"side": "computercraft:block/computer_command_side",
"top": "computercraft:block/computer_command_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_command_front",
"side": "computercraft:block/computer_command_side",
"top": "computercraft:block/computer_command_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_command_front_on",
"side": "computercraft:block/computer_command_side",
"top": "computercraft:block/computer_command_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_normal_front_blink",
"side": "computercraft:block/computer_normal_side",
"top": "computercraft:block/computer_normal_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_normal_front",
"side": "computercraft:block/computer_normal_side",
"top": "computercraft:block/computer_normal_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/computer_normal_front_on",
"side": "computercraft:block/computer_normal_side",
"top": "computercraft:block/computer_normal_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/disk_drive_front",
"side": "computercraft:block/disk_drive_side",
"top": "computercraft:block/disk_drive_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/disk_drive_front_accepted",
"side": "computercraft:block/disk_drive_side",
"top": "computercraft:block/disk_drive_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/disk_drive_front_rejected",
"side": "computercraft:block/disk_drive_side",
"top": "computercraft:block/disk_drive_top"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_32",
"front": "computercraft:block/monitor_advanced_16",
"side": "computercraft:block/monitor_advanced_4",
"top": "computercraft:block/monitor_advanced_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_36",
"front": "computercraft:block/monitor_advanced_20",
"side": "computercraft:block/monitor_advanced_7",
"top": "computercraft:block/monitor_advanced_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_32",
"front": "computercraft:block/monitor_advanced_15",
"side": "computercraft:block/monitor_advanced_4",
"top": "computercraft:block/monitor_advanced_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_33",
"front": "computercraft:block/monitor_advanced_19",
"side": "computercraft:block/monitor_advanced_4",
"top": "computercraft:block/monitor_advanced_1"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_45",
"front": "computercraft:block/monitor_advanced_31",
"side": "computercraft:block/monitor_advanced_7",
"top": "computercraft:block/monitor_advanced_1"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_34",
"front": "computercraft:block/monitor_advanced_18",
"side": "computercraft:block/monitor_advanced_4",
"top": "computercraft:block/monitor_advanced_2"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_46",
"front": "computercraft:block/monitor_advanced_30",
"side": "computercraft:block/monitor_advanced_7",
"top": "computercraft:block/monitor_advanced_2"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_40",
"front": "computercraft:block/monitor_advanced_24",
"side": "computercraft:block/monitor_advanced_5",
"top": "computercraft:block/monitor_advanced_2"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_43",
"front": "computercraft:block/monitor_advanced_27",
"side": "computercraft:block/monitor_advanced_6",
"top": "computercraft:block/monitor_advanced_2"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_39",
"front": "computercraft:block/monitor_advanced_25",
"side": "computercraft:block/monitor_advanced_5",
"top": "computercraft:block/monitor_advanced_1"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_42",
"front": "computercraft:block/monitor_advanced_28",
"side": "computercraft:block/monitor_advanced_6",
"top": "computercraft:block/monitor_advanced_1"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_35",
"front": "computercraft:block/monitor_advanced_17",
"side": "computercraft:block/monitor_advanced_4",
"top": "computercraft:block/monitor_advanced_3"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_47",
"front": "computercraft:block/monitor_advanced_29",
"side": "computercraft:block/monitor_advanced_7",
"top": "computercraft:block/monitor_advanced_3"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_41",
"front": "computercraft:block/monitor_advanced_23",
"side": "computercraft:block/monitor_advanced_5",
"top": "computercraft:block/monitor_advanced_3"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_44",
"front": "computercraft:block/monitor_advanced_26",
"side": "computercraft:block/monitor_advanced_6",
"top": "computercraft:block/monitor_advanced_3"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_38",
"front": "computercraft:block/monitor_advanced_22",
"side": "computercraft:block/monitor_advanced_5",
"top": "computercraft:block/monitor_advanced_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_advanced_37",
"front": "computercraft:block/monitor_advanced_21",
"side": "computercraft:block/monitor_advanced_6",
"top": "computercraft:block/monitor_advanced_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_32",
"front": "computercraft:block/monitor_normal_16",
"side": "computercraft:block/monitor_normal_4",
"top": "computercraft:block/monitor_normal_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_36",
"front": "computercraft:block/monitor_normal_20",
"side": "computercraft:block/monitor_normal_7",
"top": "computercraft:block/monitor_normal_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_32",
"front": "computercraft:block/monitor_normal_15",
"side": "computercraft:block/monitor_normal_4",
"top": "computercraft:block/monitor_normal_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_33",
"front": "computercraft:block/monitor_normal_19",
"side": "computercraft:block/monitor_normal_4",
"top": "computercraft:block/monitor_normal_1"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_45",
"front": "computercraft:block/monitor_normal_31",
"side": "computercraft:block/monitor_normal_7",
"top": "computercraft:block/monitor_normal_1"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_34",
"front": "computercraft:block/monitor_normal_18",
"side": "computercraft:block/monitor_normal_4",
"top": "computercraft:block/monitor_normal_2"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_46",
"front": "computercraft:block/monitor_normal_30",
"side": "computercraft:block/monitor_normal_7",
"top": "computercraft:block/monitor_normal_2"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_40",
"front": "computercraft:block/monitor_normal_24",
"side": "computercraft:block/monitor_normal_5",
"top": "computercraft:block/monitor_normal_2"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_43",
"front": "computercraft:block/monitor_normal_27",
"side": "computercraft:block/monitor_normal_6",
"top": "computercraft:block/monitor_normal_2"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_39",
"front": "computercraft:block/monitor_normal_25",
"side": "computercraft:block/monitor_normal_5",
"top": "computercraft:block/monitor_normal_1"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_42",
"front": "computercraft:block/monitor_normal_28",
"side": "computercraft:block/monitor_normal_6",
"top": "computercraft:block/monitor_normal_1"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_35",
"front": "computercraft:block/monitor_normal_17",
"side": "computercraft:block/monitor_normal_4",
"top": "computercraft:block/monitor_normal_3"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_47",
"front": "computercraft:block/monitor_normal_29",
"side": "computercraft:block/monitor_normal_7",
"top": "computercraft:block/monitor_normal_3"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_41",
"front": "computercraft:block/monitor_normal_23",
"side": "computercraft:block/monitor_normal_5",
"top": "computercraft:block/monitor_normal_3"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_44",
"front": "computercraft:block/monitor_normal_26",
"side": "computercraft:block/monitor_normal_6",
"top": "computercraft:block/monitor_normal_3"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_38",
"front": "computercraft:block/monitor_normal_22",
"side": "computercraft:block/monitor_normal_5",
"top": "computercraft:block/monitor_normal_0"
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "computercraft:block/monitor_base",
"textures": {
"back": "computercraft:block/monitor_normal_37",
"front": "computercraft:block/monitor_normal_21",
"side": "computercraft:block/monitor_normal_6",
"top": "computercraft:block/monitor_normal_0"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/printer_front_both_trays",
"side": "computercraft:block/printer_side",
"top": "computercraft:block/printer_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/printer_front_bottom_tray",
"side": "computercraft:block/printer_side",
"top": "computercraft:block/printer_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/printer_front_empty",
"side": "computercraft:block/printer_side",
"top": "computercraft:block/printer_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/printer_front_top_tray",
"side": "computercraft:block/printer_side",
"top": "computercraft:block/printer_top"
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/orientable",
"textures": {
"front": "computercraft:block/speaker_front",
"side": "computercraft:block/speaker_side",
"top": "computercraft:block/speaker_top"
}
}

View File

@ -0,0 +1 @@
{"parent": "computercraft:block/turtle_base", "textures": {"texture": "computercraft:block/turtle_advanced"}}

Some files were not shown because too many files have changed in this diff Show More