mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-15 14:07:38 +00:00
Compare commits
21 Commits
mc-1.20.y
...
v1.21-1.11
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2c740bb904 | ||
![]() |
0e4710a956 | ||
![]() |
aca1d43550 | ||
![]() |
f10e401aea | ||
![]() |
7744d2663b | ||
![]() |
4566cb8273 | ||
![]() |
052e7a7ae5 | ||
![]() |
0895200681 | ||
![]() |
1a1623075f | ||
![]() |
54a95e07a4 | ||
![]() |
09d0f563b7 | ||
![]() |
e188f1d3fa | ||
![]() |
efd9a0f315 | ||
![]() |
28f75a0687 | ||
![]() |
819a4f7231 | ||
![]() |
898cb2a95d | ||
![]() |
03a8f83191 | ||
![]() |
aef92c8ebc | ||
![]() |
571ea794a8 | ||
![]() |
4b102f16b3 | ||
![]() |
e81af93043 |
6
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -8,10 +8,8 @@ body:
|
||||
label: Minecraft Version
|
||||
description: What version of Minecraft are you using?
|
||||
options:
|
||||
- 1.16.x
|
||||
- 1.18.x
|
||||
- 1.19.x
|
||||
- 1.20.x
|
||||
- 1.20.1
|
||||
- 1.21.x
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
|
@@ -39,7 +39,7 @@ on is present.
|
||||
```groovy
|
||||
repositories {
|
||||
maven {
|
||||
url "https://squiddev.cc/maven/"
|
||||
url "https://maven.squiddev.cc"
|
||||
content {
|
||||
includeGroup("cc.tweaked")
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@ repositories {
|
||||
}
|
||||
}
|
||||
|
||||
maven("https://squiddev.cc/maven") {
|
||||
maven("https://maven.squiddev.cc") {
|
||||
name = "SquidDev"
|
||||
content {
|
||||
includeGroup("cc.tweaked.vanilla-extract")
|
||||
|
@@ -38,7 +38,7 @@ java {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
val mainMaven = maven("https://squiddev.cc/maven") {
|
||||
val mainMaven = maven("https://maven.squiddev.cc/mirror") {
|
||||
name = "SquidDev"
|
||||
}
|
||||
|
||||
@@ -133,8 +133,8 @@ tasks.processResources {
|
||||
tasks.withType(AbstractArchiveTask::class.java).configureEach {
|
||||
isPreserveFileTimestamps = false
|
||||
isReproducibleFileOrder = true
|
||||
dirMode = Integer.valueOf("755", 8)
|
||||
fileMode = Integer.valueOf("664", 8)
|
||||
filePermissions {}
|
||||
dirPermissions {}
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
|
@@ -38,7 +38,7 @@ publishing {
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://squiddev.cc/maven") {
|
||||
maven("https://maven.squiddev.cc") {
|
||||
name = "SquidDev"
|
||||
|
||||
credentials(PasswordCredentials::class)
|
||||
|
@@ -9,6 +9,7 @@ import org.gradle.api.file.FileSystemLocation
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.kotlin.dsl.getByName
|
||||
import org.gradle.process.BaseExecSpec
|
||||
import org.gradle.process.JavaExecSpec
|
||||
import org.gradle.process.ProcessForkOptions
|
||||
@@ -46,6 +47,21 @@ fun JavaExec.copyToFull(spec: JavaExec) {
|
||||
copyToExec(spec)
|
||||
}
|
||||
|
||||
/**
|
||||
* Base this [JavaExec] task on an existing task.
|
||||
*/
|
||||
fun JavaExec.copyFromTask(task: JavaExec) {
|
||||
for (dep in task.dependsOn) dependsOn(dep)
|
||||
task.copyToFull(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Base this [JavaExec] task on an existing task.
|
||||
*/
|
||||
fun JavaExec.copyFromTask(task: String) {
|
||||
copyFromTask(project.tasks.getByName<JavaExec>(task))
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy additional [BaseExecSpec] options which aren't handled by [ProcessForkOptions.copyTo].
|
||||
*/
|
||||
|
@@ -1,62 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package cc.tweaked.gradle
|
||||
|
||||
import net.neoforged.gradle.common.runs.run.RunImpl
|
||||
import net.neoforged.gradle.common.runs.tasks.RunExec
|
||||
import net.neoforged.gradle.dsl.common.extensions.RunnableSourceSet
|
||||
import net.neoforged.gradle.dsl.common.runs.run.Run
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
||||
import org.gradle.kotlin.dsl.assign
|
||||
import org.gradle.kotlin.dsl.create
|
||||
import org.gradle.kotlin.dsl.findByType
|
||||
import java.nio.file.Files
|
||||
|
||||
/**
|
||||
* Set [JavaExec] task to run a given [RunConfig].
|
||||
*
|
||||
* See also [RunExec].
|
||||
*/
|
||||
fun JavaExec.setRunConfig(config: Run) {
|
||||
mainClass.set(config.mainClass)
|
||||
workingDir = config.workingDirectory.get().asFile
|
||||
argumentProviders.add { config.programArguments.get() }
|
||||
jvmArgumentProviders.add { config.jvmArguments.get() }
|
||||
|
||||
environment(config.environmentVariables.get())
|
||||
systemProperties(config.systemProperties.get())
|
||||
|
||||
config.modSources.get().forEach { classpath(it.runtimeClasspath) }
|
||||
classpath(config.classpath)
|
||||
classpath(config.dependencies.get().configuration)
|
||||
|
||||
(config as RunImpl).taskDependencies.forEach { dependsOn(it) }
|
||||
|
||||
javaLauncher.set(
|
||||
project.extensions.getByType(JavaToolchainService::class.java)
|
||||
.launcherFor(project.extensions.getByType(JavaPluginExtension::class.java).toolchain),
|
||||
)
|
||||
|
||||
doFirst("Create working directory") { Files.createDirectories(workingDir.toPath()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new [Run.modSource] with a specific mod id.
|
||||
*/
|
||||
fun Run.modSourceAs(sourceSet: SourceSet, mod: String) {
|
||||
// NeoGradle requires a RunnableSourceSet to be present, so we inject it into other project's source sets.
|
||||
val runnable = sourceSet.extensions.findByType<RunnableSourceSet>() ?: run {
|
||||
val extension = sourceSet.extensions.create<RunnableSourceSet>(RunnableSourceSet.NAME, project)
|
||||
extension.modIdentifier = mod
|
||||
extension.modIdentifier.finalizeValueOnRead()
|
||||
extension
|
||||
}
|
||||
if (runnable.modIdentifier.get() != mod) throw IllegalArgumentException("Multiple mod identifiers")
|
||||
|
||||
modSource(sourceSet)
|
||||
}
|
@@ -25,13 +25,13 @@ as documentation for breaking changes and "gotchas" one should look out for betw
|
||||
|
||||
- Update to Lua 5.2:
|
||||
- Support for Lua 5.0's pseudo-argument `arg` has been removed. You should always use `...` for varargs.
|
||||
- Environments are no longer baked into the runtime, and instead use the `_ENV` local or upvalue. `getfenv`/`setfenv`
|
||||
now only work on Lua functions with an `_ENV` upvalue. `getfenv` will return the global environment when called
|
||||
with other functions, and `setfenv` will have no effect.
|
||||
- `load`/`loadstring` defaults to using the global environment (`_G`) rather than the current coroutine's
|
||||
- Environments are no longer baked into the runtime, and instead use the `_ENV` local or upvalue. [`getfenv`]/[`setfenv`]
|
||||
now only work on Lua functions with an `_ENV` upvalue. [`getfenv`] will return the global environment when called
|
||||
with other functions, and [`setfenv`] will have no effect.
|
||||
- [`load`]/[`loadstring`] defaults to using the global environment (`_G`) rather than the current coroutine's
|
||||
environment.
|
||||
- Support for dumping functions (`string.dump`) and loading binary chunks has been removed.
|
||||
- `math.random` now uses Lua 5.4's random number generator.
|
||||
- Support for dumping functions ([`string.dump`]) and loading binary chunks has been removed.
|
||||
- [`math.random`] now uses Lua 5.4's random number generator.
|
||||
|
||||
- File handles, HTTP requests and websockets now always use the original bytes rather than encoding/decoding to UTF-8.
|
||||
|
||||
@@ -44,7 +44,7 @@ as documentation for breaking changes and "gotchas" one should look out for betw
|
||||
`keys.enter` constant was queued when the key was pressed)
|
||||
|
||||
- Minecraft 1.13 removed the concept of item damage and block metadata (see ["The Flattening"][flattening]). As a
|
||||
result `turtle.inspect` no longer provides block metadata, and `turtle.getItemDetail` no longer provides damage.
|
||||
result [`turtle.inspect`] no longer provides block metadata, and [`turtle.getItemDetail`] no longer provides damage.
|
||||
|
||||
- Block states (`turtle.inspect().state`) should provide all the same information as block metadata, but in a much
|
||||
more understandable format.
|
||||
@@ -70,7 +70,7 @@ as documentation for breaking changes and "gotchas" one should look out for betw
|
||||
- Unlabelled computers and turtles now keep their ID when broken, meaning that unlabelled computers/items do not stack.
|
||||
|
||||
## ComputerCraft 1.80pr1 {#cc-1.80}
|
||||
- Programs run via `shell.run` are now started in their own isolated environment. This means globals set by programs
|
||||
- Programs run via [`shell.run`] are now started in their own isolated environment. This means globals set by programs
|
||||
will not be accessible outside of this program.
|
||||
|
||||
- Programs containing `/` are looked up in the current directory and are no longer looked up on the path. For instance,
|
||||
|
@@ -8,9 +8,11 @@ org.gradle.parallel=true
|
||||
kotlin.stdlib.default.dependency=false
|
||||
kotlin.jvm.target.validation.mode=error
|
||||
|
||||
neogradle.subsystems.conventions.runs.enabled=false
|
||||
|
||||
# Mod properties
|
||||
isUnstable=true
|
||||
modVersion=1.111.0
|
||||
modVersion=1.111.1
|
||||
|
||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
||||
mcVersion=1.20.6
|
||||
mcVersion=1.21
|
||||
|
@@ -7,14 +7,14 @@
|
||||
# Minecraft
|
||||
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
||||
# Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml
|
||||
fabric-api = "0.98.0+1.20.6"
|
||||
fabric-loader = "0.15.10"
|
||||
neoForge = "20.6.48-beta"
|
||||
fabric-api = "0.100.3+1.21"
|
||||
fabric-loader = "0.15.11"
|
||||
neoForge = "21.0.42-beta"
|
||||
neoForgeSpi = "8.0.1"
|
||||
mixin = "0.8.5"
|
||||
parchment = "2024.05.01"
|
||||
parchment = "2024.06.16"
|
||||
parchmentMc = "1.20.6"
|
||||
yarn = "1.20.6+build.1"
|
||||
yarn = "1.21+build.1"
|
||||
|
||||
# Core dependencies (these versions are tied to the version Minecraft uses)
|
||||
fastutil = "8.5.12"
|
||||
@@ -36,14 +36,14 @@ kotlin-coroutines = "1.7.3"
|
||||
nightConfig = "3.6.7"
|
||||
|
||||
# Minecraft mods
|
||||
emi = "1.1.5+1.20.6"
|
||||
emi = "1.1.7+1.21"
|
||||
fabricPermissions = "0.3.1"
|
||||
iris = "1.6.14+1.20.4"
|
||||
jei = "17.3.0.48"
|
||||
modmenu = "9.0.0"
|
||||
jei = "19.0.0.1"
|
||||
modmenu = "11.0.0-rc.4"
|
||||
moreRed = "4.0.0.4"
|
||||
oculus = "1.2.5"
|
||||
rei = "15.0.728"
|
||||
rei = "16.0.729"
|
||||
rubidium = "0.6.1"
|
||||
sodium = "mc1.20-0.4.10"
|
||||
mixinExtra = "0.3.5"
|
||||
@@ -60,18 +60,18 @@ checkstyle = "10.14.1"
|
||||
curseForgeGradle = "1.1.18"
|
||||
errorProne-core = "2.27.0"
|
||||
errorProne-plugin = "3.1.0"
|
||||
fabric-loom = "1.6.7"
|
||||
fabric-loom = "1.7.1"
|
||||
githubRelease = "2.5.2"
|
||||
gradleVersions = "0.50.0"
|
||||
ideaExt = "1.1.7"
|
||||
illuaminate = "0.1.0-73-g43ee16c"
|
||||
lwjgl = "3.3.3"
|
||||
minotaur = "2.8.7"
|
||||
neoGradle = "7.0.116"
|
||||
neoGradle = "7.0.152"
|
||||
nullAway = "0.10.25"
|
||||
spotless = "6.23.3"
|
||||
taskTree = "2.1.1"
|
||||
teavm = "0.10.0-SQUID.4"
|
||||
teavm = "0.11.0-SQUID.1"
|
||||
vanillaExtract = "0.1.3"
|
||||
versionCatalogUpdate = "0.8.1"
|
||||
|
||||
@@ -106,9 +106,9 @@ fabric-junit = { module = "net.fabricmc:fabric-loader-junit", version.ref = "fab
|
||||
fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" }
|
||||
emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" }
|
||||
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
|
||||
jei-api = { module = "mezz.jei:jei-1.20.4-common-api", version.ref = "jei" }
|
||||
jei-fabric = { module = "mezz.jei:jei-1.20.4-fabric", version.ref = "jei" }
|
||||
jei-forge = { module = "mezz.jei:jei-1.20.4-forge", version.ref = "jei" }
|
||||
jei-api = { module = "mezz.jei:jei-1.21-common-api", version.ref = "jei" }
|
||||
jei-fabric = { module = "mezz.jei:jei-1.21-fabric", version.ref = "jei" }
|
||||
jei-forge = { module = "mezz.jei:jei-1.21-neoforge", version.ref = "jei" }
|
||||
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
|
||||
mixinExtra = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinExtra" }
|
||||
modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" }
|
||||
@@ -179,9 +179,9 @@ kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
||||
# Minecraft
|
||||
externalMods-common = ["jei-api", "nightConfig-core", "nightConfig-toml"]
|
||||
externalMods-forge-compile = ["moreRed", "oculus", "jei-api"]
|
||||
externalMods-forge-runtime = []
|
||||
externalMods-forge-runtime = ["jei-forge"]
|
||||
externalMods-fabric-compile = ["fabricPermissions", "iris", "jei-api", "rei-api", "rei-builtin"]
|
||||
externalMods-fabric-runtime = [] # ["jei-fabric", "modmenu"]
|
||||
externalMods-fabric-runtime = ["jei-fabric", "modmenu"]
|
||||
|
||||
# Testing
|
||||
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
2
gradlew
vendored
2
gradlew
vendored
@@ -55,7 +55,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
@@ -0,0 +1,84 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.api.client;
|
||||
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* The location of a model to load. This may either be:
|
||||
*
|
||||
* <ul>
|
||||
* <li>A {@link ModelResourceLocation}, referencing an already baked model (such as {@code minecraft:dirt#inventory}).</li>
|
||||
* <li>
|
||||
* A {@link ResourceLocation}, referencing a path to a model resource (such as {@code minecraft:item/dirt}.
|
||||
* These models will be baked and stored in the {@link ModelManager} in a loader-specific way.
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class ModelLocation {
|
||||
/**
|
||||
* The location of the model.
|
||||
* <p>
|
||||
* When {@link #resourceLocation} is null, this is the location of the model to load. When {@link #resourceLocation}
|
||||
* is non-null, this is the "standalone" variant of the model resource — this is used by NeoForge's implementation
|
||||
* of {@link ClientPlatformHelper#getModel(ModelManager, ModelResourceLocation, ResourceLocation)} to fetch the
|
||||
* model from the model manger. It is not used on Fabric.
|
||||
*/
|
||||
private final ModelResourceLocation modelLocation;
|
||||
private final @Nullable ResourceLocation resourceLocation;
|
||||
|
||||
private ModelLocation(ModelResourceLocation modelLocation, @Nullable ResourceLocation resourceLocation) {
|
||||
this.modelLocation = modelLocation;
|
||||
this.resourceLocation = resourceLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ModelLocation} from model in the model manager.
|
||||
*
|
||||
* @param location The name of the model to load.
|
||||
* @return The new {@link ModelLocation} instance.
|
||||
*/
|
||||
public static ModelLocation ofModel(ModelResourceLocation location) {
|
||||
return new ModelLocation(location, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ModelLocation} from a resource.
|
||||
*
|
||||
* @param location The location of the model resource, such as {@code minecraft:item/dirt}.
|
||||
* @return The new {@link ModelLocation} instance.
|
||||
*/
|
||||
public static ModelLocation ofResource(ResourceLocation location) {
|
||||
return new ModelLocation(new ModelResourceLocation(location, "standalone"), location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this model from the provided model manager.
|
||||
*
|
||||
* @param manager The model manger.
|
||||
* @return This model, or the missing model if it could not be found.
|
||||
*/
|
||||
public BakedModel getModel(ModelManager manager) {
|
||||
return ClientPlatformHelper.get().getModel(manager, modelLocation, resourceLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models this model location depends on.
|
||||
*
|
||||
* @return A list of models that this model location depends on.
|
||||
* @see TurtleUpgradeModeller#getDependencies()
|
||||
*/
|
||||
public Stream<ResourceLocation> getDependencies() {
|
||||
return resourceLocation == null ? Stream.empty() : Stream.of(resourceLocation);
|
||||
}
|
||||
}
|
@@ -13,30 +13,47 @@ import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A model to render, combined with a transformation matrix to apply.
|
||||
*
|
||||
* @param model The model.
|
||||
* @param matrix The transformation matrix.
|
||||
*/
|
||||
public final class TransformedModel {
|
||||
private final BakedModel model;
|
||||
private final Transformation matrix;
|
||||
|
||||
public TransformedModel(BakedModel model, Transformation matrix) {
|
||||
this.model = Objects.requireNonNull(model);
|
||||
this.matrix = Objects.requireNonNull(matrix);
|
||||
}
|
||||
|
||||
public record TransformedModel(BakedModel model, Transformation matrix) {
|
||||
public TransformedModel(BakedModel model) {
|
||||
this.model = Objects.requireNonNull(model);
|
||||
matrix = Transformation.identity();
|
||||
this(model, Transformation.identity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||
*
|
||||
* @param location The location of the model to load.
|
||||
* @return The new {@link TransformedModel} instance.
|
||||
*/
|
||||
public static TransformedModel of(ModelLocation location) {
|
||||
var modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel(location.getModel(modelManager));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||
*
|
||||
* @param location The location of the model to load.
|
||||
* @return The new {@link TransformedModel} instance.
|
||||
* @see ModelLocation#ofModel(ModelResourceLocation)
|
||||
*/
|
||||
public static TransformedModel of(ModelResourceLocation location) {
|
||||
var modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel(modelManager.getModel(location));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||
*
|
||||
* @param location The location of the model to load.
|
||||
* @return The new {@link TransformedModel} instance.
|
||||
* @see ModelLocation#ofResource(ResourceLocation)
|
||||
*/
|
||||
public static TransformedModel of(ResourceLocation location) {
|
||||
var modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel(ClientPlatformHelper.get().getModel(modelManager, location));
|
||||
@@ -46,12 +63,4 @@ public final class TransformedModel {
|
||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item);
|
||||
return new TransformedModel(model, transform);
|
||||
}
|
||||
|
||||
public BakedModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public Transformation getMatrix() {
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
package dan200.computercraft.api.client.turtle;
|
||||
|
||||
import dan200.computercraft.api.client.ModelLocation;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
@@ -77,6 +78,18 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
||||
* @return The constructed modeller.
|
||||
*/
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
||||
return sided(ModelLocation.ofResource(left), ModelLocation.ofResource(right));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a {@link TurtleUpgradeModeller} which has a single model for the left and right side.
|
||||
*
|
||||
* @param left The model to use on the left.
|
||||
* @param right The model to use on the right.
|
||||
* @param <T> The type of the turtle upgrade.
|
||||
* @return The constructed modeller.
|
||||
*/
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ModelLocation left, ModelLocation right) {
|
||||
return new TurtleUpgradeModeller<>() {
|
||||
@Override
|
||||
public TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data) {
|
||||
@@ -85,7 +98,7 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
||||
|
||||
@Override
|
||||
public Stream<ResourceLocation> getDependencies() {
|
||||
return Stream.of(left, right);
|
||||
return Stream.of(left, right).flatMap(ModelLocation::getDependencies);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
package dan200.computercraft.impl.client;
|
||||
|
||||
import dan200.computercraft.api.client.ModelLocation;
|
||||
import dan200.computercraft.impl.Services;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
@@ -17,13 +18,28 @@ import javax.annotation.Nullable;
|
||||
@ApiStatus.Internal
|
||||
public interface ClientPlatformHelper {
|
||||
/**
|
||||
* Equivalent to {@link ModelManager#getModel(ModelResourceLocation)} but for arbitrary {@link ResourceLocation}s.
|
||||
* Get a model from a resource.
|
||||
*
|
||||
* @param manager The model manager.
|
||||
* @param location The model location.
|
||||
* @param manager The model manager.
|
||||
* @param resourceLocation The model resourceLocation.
|
||||
* @return The baked model.
|
||||
* @see ModelLocation
|
||||
*/
|
||||
BakedModel getModel(ModelManager manager, ResourceLocation location);
|
||||
BakedModel getModel(ModelManager manager, ResourceLocation resourceLocation);
|
||||
|
||||
/**
|
||||
* Set a model from a {@link ModelResourceLocation} or {@link ResourceLocation}.
|
||||
* <p>
|
||||
* This is largely equivalent to {@code resourceLocation == null ? manager.getModel(modelLocation) : getModel(manager, resourceLocation)},
|
||||
* but allows pre-computing {@code modelLocation} (if needed).
|
||||
*
|
||||
* @param manager The model manager.
|
||||
* @param modelLocation The location of the model to load.
|
||||
* @param resourceLocation The location of the resource, if trying to load from a resource.
|
||||
* @return The baked model.
|
||||
* @see ModelLocation
|
||||
*/
|
||||
BakedModel getModel(ModelManager manager, ModelResourceLocation modelLocation, @Nullable ResourceLocation resourceLocation);
|
||||
|
||||
/**
|
||||
* Wrap this model in a version which renders a foil/enchantment glint.
|
||||
|
@@ -46,7 +46,7 @@ public class ComputerCraftTags {
|
||||
public static final TagKey<Item> DYEABLE = make("dyeable");
|
||||
|
||||
private static TagKey<Item> make(String name) {
|
||||
return TagKey.create(Registries.ITEM, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||
return TagKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class ComputerCraftTags {
|
||||
public static final TagKey<Block> TURTLE_CAN_USE = make("turtle_can_use");
|
||||
|
||||
private static TagKey<Block> make(String name) {
|
||||
return TagKey.create(Registries.BLOCK, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||
return TagKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,11 +7,13 @@ package dan200.computercraft.api.media;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.filesystem.Mount;
|
||||
import dan200.computercraft.api.filesystem.WritableMount;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.JukeboxSong;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -25,11 +27,12 @@ public interface IMedia {
|
||||
/**
|
||||
* Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua.
|
||||
*
|
||||
* @param stack The {@link ItemStack} to inspect.
|
||||
* @param registries The currently loaded registries.
|
||||
* @param stack The {@link ItemStack} to inspect.
|
||||
* @return The label. ie: "Dan's Programs".
|
||||
*/
|
||||
@Nullable
|
||||
String getLabel(ItemStack stack);
|
||||
String getLabel(HolderLookup.Provider registries, ItemStack stack);
|
||||
|
||||
/**
|
||||
* Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua.
|
||||
@@ -43,26 +46,15 @@ public interface IMedia {
|
||||
}
|
||||
|
||||
/**
|
||||
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie:
|
||||
* "Jonathan Coulton - Still Alive"
|
||||
* If this disk represents an item with audio (like a record), get the corresponding {@link JukeboxSong}.
|
||||
*
|
||||
* @param stack The {@link ItemStack} to modify.
|
||||
* @return The name, or null if this item does not represent an item with audio.
|
||||
* @param registries The currently loaded registries.
|
||||
* @param stack The {@link ItemStack} to query.
|
||||
* @return The song, or null if this item does not represent an item with audio.
|
||||
*/
|
||||
@Nullable
|
||||
default String getAudioTitle(ItemStack stack) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this disk represents an item with audio (like a record), get the resource name of the audio track to play.
|
||||
*
|
||||
* @param stack The {@link ItemStack} to modify.
|
||||
* @return The name, or null if this item does not represent an item with audio.
|
||||
*/
|
||||
@Nullable
|
||||
default SoundEvent getAudio(ItemStack stack) {
|
||||
return null;
|
||||
default Holder<JukeboxSong> getAudio(HolderLookup.Provider registries, ItemStack stack) {
|
||||
return JukeboxSong.fromStack(registries, stack).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -48,7 +48,7 @@ import javax.annotation.Nullable;
|
||||
* }
|
||||
*/
|
||||
public interface IPocketUpgrade extends UpgradeBase {
|
||||
ResourceKey<Registry<IPocketUpgrade>> REGISTRY = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade"));
|
||||
ResourceKey<Registry<IPocketUpgrade>> REGISTRY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "pocket_upgrade"));
|
||||
|
||||
/**
|
||||
* The registry key for pocket upgrade types.
|
||||
|
@@ -57,7 +57,7 @@ public interface ITurtleUpgrade extends UpgradeBase {
|
||||
/**
|
||||
* The registry in which turtle upgrades are stored.
|
||||
*/
|
||||
ResourceKey<Registry<ITurtleUpgrade>> REGISTRY = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade"));
|
||||
ResourceKey<Registry<ITurtleUpgrade>> REGISTRY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_upgrade"));
|
||||
|
||||
/**
|
||||
* Create a {@link ResourceKey} for a turtle upgrade given a {@link ResourceLocation}.
|
||||
|
@@ -35,7 +35,7 @@ import java.util.Optional;
|
||||
* import net.minecraft.world.item.Items;
|
||||
*
|
||||
* public void registerTool(BootstrapContext<ITurtleUpgrade> upgrades) {
|
||||
* TurtleToolBuilder.tool(new ResourceLocation("my_mod", "wooden_pickaxe"), Items.WOODEN_PICKAXE).register(upgrades);
|
||||
* TurtleToolBuilder.tool(ResourceLocation.fromNamespaceAndPath("my_mod", "wooden_pickaxe"), Items.WOODEN_PICKAXE).register(upgrades);
|
||||
* }
|
||||
*}
|
||||
*/
|
||||
|
@@ -55,7 +55,7 @@ import java.util.function.Function;
|
||||
* public void generate(DataGenerator.PackGenerator output, CompletableFuture<HolderLookup.Provider> registries) {
|
||||
* var newRegistries = RegistryPatchGenerator.createLookup(registries, Util.make(new RegistrySetBuilder(), builder -> {
|
||||
* builder.add(ITurtleUpgrade.REGISTRY, upgrades -> {
|
||||
* upgrades.register(ITurtleUpgrade.createKey(new ResourceLocation("my_mod", "my_upgrade")), new MyUpgrade());
|
||||
* upgrades.register(ITurtleUpgrade.createKey(ResourceLocation.fromNamespaceAndPath("my_mod", "my_upgrade")), new MyUpgrade());
|
||||
* });
|
||||
* }));
|
||||
* output.addProvider(o -> new DatapackBuiltinEntriesProvider(o, newRegistries, Set.of("my_mod")));
|
||||
|
@@ -24,8 +24,8 @@ import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||
import dan200.computercraft.shared.computer.inventory.ViewComputerMenu;
|
||||
import dan200.computercraft.shared.media.items.DiskItem;
|
||||
import dan200.computercraft.shared.turtle.TurtleOverlay;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.color.item.ItemColor;
|
||||
@@ -54,6 +54,7 @@ import net.minecraft.world.level.ItemLike;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
@@ -101,15 +102,12 @@ public final class ClientRegistry {
|
||||
|
||||
public static void registerMenuScreens(RegisterMenuScreen register) {
|
||||
register.<AbstractComputerMenu, ComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.COMPUTER.get(), ComputerScreen::new);
|
||||
register.<AbstractComputerMenu, ComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.POCKET_COMPUTER.get(), ComputerScreen::new);
|
||||
register.<AbstractComputerMenu, NoTermComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.POCKET_COMPUTER_NO_TERM.get(), NoTermComputerScreen::new);
|
||||
register.register(ModRegistry.Menus.TURTLE.get(), TurtleScreen::new);
|
||||
|
||||
register.register(ModRegistry.Menus.PRINTER.get(), PrinterScreen::new);
|
||||
register.register(ModRegistry.Menus.DISK_DRIVE.get(), DiskDriveScreen::new);
|
||||
register.register(ModRegistry.Menus.PRINTOUT.get(), PrintoutScreen::new);
|
||||
|
||||
register.<ViewComputerMenu, ComputerScreen<ViewComputerMenu>>register(ModRegistry.Menus.VIEW_COMPUTER.get(), ComputerScreen::new);
|
||||
}
|
||||
|
||||
public interface RegisterMenuScreen {
|
||||
@@ -118,12 +116,12 @@ public final class ClientRegistry {
|
||||
|
||||
public static void registerTurtleModellers(RegisterTurtleUpgradeModeller register) {
|
||||
register.register(ModRegistry.TurtleUpgradeTypes.SPEAKER.get(), TurtleUpgradeModeller.sided(
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_left"),
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_right")
|
||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_left"),
|
||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_right")
|
||||
));
|
||||
register.register(ModRegistry.TurtleUpgradeTypes.WORKBENCH.get(), TurtleUpgradeModeller.sided(
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_crafting_table_left"),
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_crafting_table_right")
|
||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_crafting_table_left"),
|
||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_crafting_table_right")
|
||||
));
|
||||
register.register(ModRegistry.TurtleUpgradeTypes.WIRELESS_MODEM.get(), new TurtleModemModeller());
|
||||
register.register(ModRegistry.TurtleUpgradeTypes.TOOL.get(), TurtleUpgradeModeller.flatItem());
|
||||
@@ -131,7 +129,7 @@ public final class ClientRegistry {
|
||||
|
||||
@SafeVarargs
|
||||
private static void registerItemProperty(RegisterItemProperty itemProperties, String name, ClampedItemPropertyFunction getter, Supplier<? extends Item>... items) {
|
||||
var id = new ResourceLocation(ComputerCraftAPI.MOD_ID, name);
|
||||
var id = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name);
|
||||
for (var item : items) itemProperties.register(item.get(), id, getter);
|
||||
}
|
||||
|
||||
@@ -147,15 +145,14 @@ public final class ClientRegistry {
|
||||
register.accept(GuiSprites.initialise(minecraft.getTextureManager()));
|
||||
}
|
||||
|
||||
private static final String[] EXTRA_MODELS = new String[]{
|
||||
"block/turtle_colour",
|
||||
"block/turtle_elf_overlay",
|
||||
"block/turtle_rainbow_overlay",
|
||||
"block/turtle_trans_overlay",
|
||||
private static final ResourceLocation[] EXTRA_MODELS = {
|
||||
TurtleOverlay.ELF_MODEL,
|
||||
TurtleBlockEntityRenderer.COLOUR_TURTLE_MODEL,
|
||||
};
|
||||
|
||||
public static void registerExtraModels(Consumer<ResourceLocation> register) {
|
||||
for (var model : EXTRA_MODELS) register.accept(new ResourceLocation(ComputerCraftAPI.MOD_ID, model));
|
||||
public static void registerExtraModels(Consumer<ResourceLocation> register, Collection<ResourceLocation> extraModels) {
|
||||
for (var model : EXTRA_MODELS) register.accept(model);
|
||||
extraModels.forEach(register);
|
||||
TurtleUpgradeModellers.getDependencies().forEach(register);
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@ import net.minecraft.world.entity.player.Inventory;
|
||||
* The GUI for disk drives.
|
||||
*/
|
||||
public class DiskDriveScreen extends AbstractContainerScreen<DiskDriveMenu> {
|
||||
private static final ResourceLocation BACKGROUND = new ResourceLocation("computercraft", "textures/gui/disk_drive.png");
|
||||
private static final ResourceLocation BACKGROUND = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/disk_drive.png");
|
||||
|
||||
public DiskDriveScreen(DiskDriveMenu container, Inventory player, Component title) {
|
||||
super(container, player, title);
|
||||
|
@@ -21,7 +21,7 @@ import java.util.stream.Stream;
|
||||
* Sprite sheet for all GUI texutres in the mod.
|
||||
*/
|
||||
public final class GuiSprites extends TextureAtlasHolder {
|
||||
public static final ResourceLocation SPRITE_SHEET = new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui");
|
||||
public static final ResourceLocation SPRITE_SHEET = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui");
|
||||
public static final ResourceLocation TEXTURE = SPRITE_SHEET.withPath(x -> "textures/atlas/" + x + ".png");
|
||||
|
||||
public static final ButtonTextures TURNED_OFF = button("turned_off");
|
||||
@@ -35,16 +35,16 @@ public final class GuiSprites extends TextureAtlasHolder {
|
||||
|
||||
private static ButtonTextures button(String name) {
|
||||
return new ButtonTextures(
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name),
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name + "_hover")
|
||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name),
|
||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name + "_hover")
|
||||
);
|
||||
}
|
||||
|
||||
private static ComputerTextures computer(String name, boolean pocket, boolean sidebar) {
|
||||
return new ComputerTextures(
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/border_" + name),
|
||||
pocket ? new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/pocket_bottom_" + name) : null,
|
||||
sidebar ? new ResourceLocation(ComputerCraftAPI.MOD_ID, "gui/sidebar_" + name) : null
|
||||
ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/border_" + name),
|
||||
pocket ? ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/pocket_bottom_" + name) : null,
|
||||
sidebar ? ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/sidebar_" + name) : null
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ import java.util.List;
|
||||
* A {@link Toast} implementation which displays an arbitrary message along with an optional {@link ItemStack}.
|
||||
*/
|
||||
public class ItemToast implements Toast {
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation("toast/recipe");
|
||||
private static final ResourceLocation TEXTURE = ResourceLocation.withDefaultNamespace("toast/recipe");
|
||||
public static final Object TRANSFER_NO_RESPONSE_TOKEN = new Object();
|
||||
|
||||
private static final long DISPLAY_TIME = 7000L;
|
||||
|
@@ -24,7 +24,7 @@ import static dan200.computercraft.core.util.Nullability.assertNonNull;
|
||||
* When closed, it returns to the previous screen.
|
||||
*/
|
||||
public final class OptionScreen extends Screen {
|
||||
private static final ResourceLocation BACKGROUND = new ResourceLocation("computercraft", "textures/gui/blank_screen.png");
|
||||
private static final ResourceLocation BACKGROUND = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/blank_screen.png");
|
||||
|
||||
public static final int BUTTON_WIDTH = 100;
|
||||
public static final int BUTTON_HEIGHT = 20;
|
||||
|
@@ -15,7 +15,7 @@ import net.minecraft.world.entity.player.Inventory;
|
||||
* The GUI for printers.
|
||||
*/
|
||||
public class PrinterScreen extends AbstractContainerScreen<PrinterMenu> {
|
||||
private static final ResourceLocation BACKGROUND = new ResourceLocation("computercraft", "textures/gui/printer.png");
|
||||
private static final ResourceLocation BACKGROUND = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/printer.png");
|
||||
|
||||
public PrinterScreen(PrinterMenu container, Inventory player, Component title) {
|
||||
super(container, player, title);
|
||||
|
@@ -4,7 +4,6 @@
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.common.HeldItemMenu;
|
||||
@@ -12,7 +11,6 @@ import dan200.computercraft.shared.media.items.PrintoutData;
|
||||
import dan200.computercraft.shared.media.items.PrintoutItem;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -90,10 +88,8 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
|
||||
graphics.pose().pushPose();
|
||||
graphics.pose().translate(0, 0, 1);
|
||||
|
||||
var renderer = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
||||
drawBorder(graphics.pose(), renderer, leftPos, topPos, 0, page, pages, book, FULL_BRIGHT_LIGHTMAP);
|
||||
drawText(graphics.pose(), renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutData.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours);
|
||||
renderer.endBatch();
|
||||
drawBorder(graphics.pose(), graphics.bufferSource(), leftPos, topPos, 0, page, pages, book, FULL_BRIGHT_LIGHTMAP);
|
||||
drawText(graphics.pose(), graphics.bufferSource(), leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutData.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours);
|
||||
|
||||
graphics.pose().popPose();
|
||||
}
|
||||
|
@@ -23,8 +23,8 @@ import static dan200.computercraft.shared.turtle.inventory.TurtleMenu.*;
|
||||
* The GUI for turtles.
|
||||
*/
|
||||
public class TurtleScreen extends AbstractComputerScreen<TurtleMenu> {
|
||||
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_normal.png");
|
||||
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_advanced.png");
|
||||
private static final ResourceLocation BACKGROUND_NORMAL = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_normal.png");
|
||||
private static final ResourceLocation BACKGROUND_ADVANCED = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_advanced.png");
|
||||
|
||||
private static final int TEX_WIDTH = 278;
|
||||
private static final int TEX_HEIGHT = 217;
|
||||
|
@@ -4,7 +4,6 @@
|
||||
|
||||
package dan200.computercraft.client.gui.widgets;
|
||||
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import dan200.computercraft.client.render.RenderTypes;
|
||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
@@ -16,7 +15,6 @@ import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.narration.NarratedElementType;
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
@@ -259,15 +257,12 @@ public class TerminalWidget extends AbstractWidget {
|
||||
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||
if (!visible) return;
|
||||
|
||||
var bufferSource = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
|
||||
var emitter = FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), bufferSource.getBuffer(RenderTypes.TERMINAL));
|
||||
var emitter = FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), graphics.bufferSource().getBuffer(RenderTypes.TERMINAL));
|
||||
|
||||
FixedWidthFontRenderer.drawTerminal(
|
||||
emitter,
|
||||
(float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN
|
||||
);
|
||||
|
||||
bufferSource.endBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.shared.integration.jei;
|
||||
package dan200.computercraft.client.integration.jei;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
@@ -19,6 +19,8 @@ import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter;
|
||||
import mezz.jei.api.registration.IAdvancedRegistration;
|
||||
import mezz.jei.api.registration.ISubtypeRegistration;
|
||||
import mezz.jei.api.runtime.IJeiRuntime;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
@@ -28,7 +30,7 @@ import java.util.List;
|
||||
public class JEIComputerCraft implements IModPlugin {
|
||||
@Override
|
||||
public ResourceLocation getPluginUid() {
|
||||
return new ResourceLocation(ComputerCraftAPI.MOD_ID, "jei");
|
||||
return ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "jei");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,7 +46,7 @@ public class JEIComputerCraft implements IModPlugin {
|
||||
|
||||
@Override
|
||||
public void registerAdvanced(IAdvancedRegistration registry) {
|
||||
registry.addRecipeManagerPlugin(new RecipeResolver());
|
||||
registry.addRecipeManagerPlugin(new RecipeResolver(getRegistryAccess()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,7 +54,7 @@ public class JEIComputerCraft implements IModPlugin {
|
||||
var registry = runtime.getRecipeManager();
|
||||
|
||||
// Register all turtles/pocket computers (not just vanilla upgrades) as upgrades on JEI.
|
||||
var upgradeItems = RecipeModHelpers.getExtraStacks(RecipeModHelpers.getEmptyRegistryAccess());
|
||||
var upgradeItems = RecipeModHelpers.getExtraStacks(getRegistryAccess());
|
||||
if (!upgradeItems.isEmpty()) {
|
||||
runtime.getIngredientManager().addIngredientsAtRuntime(VanillaTypes.ITEM_STACK, upgradeItems);
|
||||
}
|
||||
@@ -99,4 +101,8 @@ public class JEIComputerCraft implements IModPlugin {
|
||||
* Distinguishes disks by colour.
|
||||
*/
|
||||
private static final IIngredientSubtypeInterpreter<ItemStack> diskSubtype = (stack, ctx) -> Integer.toString(DiskItem.getColour(stack));
|
||||
|
||||
private static RegistryAccess getRegistryAccess() {
|
||||
return Minecraft.getInstance().level.registryAccess();
|
||||
}
|
||||
}
|
@@ -2,10 +2,9 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.shared.integration.jei;
|
||||
package dan200.computercraft.client.integration.jei;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.shared.integration.RecipeModHelpers;
|
||||
import dan200.computercraft.shared.integration.UpgradeRecipeGenerator;
|
||||
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
||||
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
||||
@@ -14,6 +13,7 @@ import mezz.jei.api.recipe.IFocus;
|
||||
import mezz.jei.api.recipe.RecipeType;
|
||||
import mezz.jei.api.recipe.advanced.IRecipeManagerPlugin;
|
||||
import mezz.jei.api.recipe.category.IRecipeCategory;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.CraftingRecipe;
|
||||
@@ -22,8 +22,19 @@ import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import java.util.List;
|
||||
|
||||
class RecipeResolver implements IRecipeManagerPlugin {
|
||||
private static final ResourceLocation RECIPE_ID = new ResourceLocation(ComputerCraftAPI.MOD_ID, "upgrade");
|
||||
private final UpgradeRecipeGenerator<RecipeHolder<CraftingRecipe>> resolver = new UpgradeRecipeGenerator<>(x -> new RecipeHolder<>(RECIPE_ID, x), RecipeModHelpers.getEmptyRegistryAccess());
|
||||
private final UpgradeRecipeGenerator<RecipeHolder<CraftingRecipe>> resolver;
|
||||
|
||||
/**
|
||||
* We need to generate unique ids for each recipe, as JEI will attempt to deduplicate them otherwise.
|
||||
*/
|
||||
private int nextId = 0;
|
||||
|
||||
RecipeResolver(HolderLookup.Provider registries) {
|
||||
resolver = new UpgradeRecipeGenerator<>(
|
||||
x -> new RecipeHolder<>(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "upgrade_" + nextId++), x),
|
||||
registries
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> List<RecipeType<?>> getRecipeTypes(IFocus<V> focus) {
|
||||
@@ -60,7 +71,7 @@ class RecipeResolver implements IRecipeManagerPlugin {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({ "unchecked", "rawtypes", "UnusedVariable" })
|
||||
private static <T, U> List<T> cast(RecipeType<U> ignoredType, List<U> from) {
|
||||
return (List) from;
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.client.model;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.shared.turtle.TurtleOverlay;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A list of extra models to load on the client.
|
||||
* <p>
|
||||
* This is largely intended for use with {@linkplain TurtleOverlay turtle overlays}. As overlays are stored in a dynamic
|
||||
* registry, they are not available when resources are loaded, and so we need a way to request the overlays' models be
|
||||
* loaded.
|
||||
*
|
||||
* @param models The models to load.
|
||||
*/
|
||||
public record ExtraModels(List<ResourceLocation> models) {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ExtraModels.class);
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
/**
|
||||
* The path where the extra models are listed.
|
||||
*/
|
||||
public static final ResourceLocation PATH = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "extra_models.json");
|
||||
|
||||
/**
|
||||
* The coded used to store the extra model file.
|
||||
*/
|
||||
public static final Codec<ExtraModels> CODEC = ResourceLocation.CODEC.listOf().xmap(ExtraModels::new, ExtraModels::models);
|
||||
|
||||
/**
|
||||
* Get the list of all extra models to load.
|
||||
*
|
||||
* @param resources The current resource manager.
|
||||
* @return A set of all resources to load.
|
||||
*/
|
||||
public static Collection<ResourceLocation> loadAll(ResourceManager resources) {
|
||||
Set<ResourceLocation> out = new HashSet<>();
|
||||
|
||||
for (var path : resources.getResourceStack(PATH)) {
|
||||
ExtraModels models;
|
||||
try (var stream = path.openAsReader()) {
|
||||
models = ExtraModels.CODEC.parse(JsonOps.INSTANCE, GSON.fromJson(stream, JsonElement.class)).getOrThrow(JsonParseException::new);
|
||||
} catch (IOException | RuntimeException e) {
|
||||
LOG.error("Failed to load extra models from {}", path.sourcePackId());
|
||||
continue;
|
||||
}
|
||||
|
||||
out.addAll(models.models());
|
||||
}
|
||||
|
||||
return Collections.unmodifiableCollection(out);
|
||||
}
|
||||
}
|
@@ -4,11 +4,9 @@
|
||||
|
||||
package dan200.computercraft.client.model.turtle;
|
||||
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
||||
import com.mojang.math.Transformation;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.FaceBakery;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.Direction;
|
||||
import org.joml.Matrix4f;
|
||||
@@ -29,8 +27,8 @@ import java.util.List;
|
||||
public class ModelTransformer {
|
||||
private static final int[] INVERSE_ORDER = new int[]{ 3, 2, 1, 0 };
|
||||
|
||||
private static final int STRIDE = DefaultVertexFormat.BLOCK.getIntegerSize();
|
||||
private static final int POS_OFFSET = findOffset(DefaultVertexFormat.BLOCK, DefaultVertexFormat.ELEMENT_POSITION);
|
||||
private static final int STRIDE = FaceBakery.VERTEX_INT_SIZE;
|
||||
private static final int POS_OFFSET = 0;
|
||||
|
||||
protected final Matrix4f transformation;
|
||||
protected final boolean invert;
|
||||
@@ -91,13 +89,4 @@ public class ModelTransformer {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@@ -12,13 +12,14 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.client.platform.ClientPlatformHelper;
|
||||
import dan200.computercraft.client.render.TurtleBlockEntityRenderer;
|
||||
import dan200.computercraft.client.turtle.TurtleUpgradeModellers;
|
||||
import dan200.computercraft.shared.turtle.TurtleOverlay;
|
||||
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
||||
import dan200.computercraft.shared.util.DataComponentUtil;
|
||||
import dan200.computercraft.shared.util.Holiday;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@@ -52,7 +53,7 @@ public final class TurtleModelParts<T> {
|
||||
boolean colour,
|
||||
@Nullable UpgradeData<ITurtleUpgrade> leftUpgrade,
|
||||
@Nullable UpgradeData<ITurtleUpgrade> rightUpgrade,
|
||||
@Nullable ResourceLocation overlay,
|
||||
@Nullable TurtleOverlay overlay,
|
||||
boolean christmas,
|
||||
boolean flip
|
||||
) {
|
||||
@@ -85,7 +86,7 @@ public final class TurtleModelParts<T> {
|
||||
public TurtleModelParts(BakedModel familyModel, BakedModel colourModel, ModelTransformer transformer, Function<List<BakedModel>, T> combineModel) {
|
||||
this.familyModel = familyModel;
|
||||
this.colourModel = colourModel;
|
||||
this.transformer = x -> transformer.transform(x.getModel(), x.getMatrix());
|
||||
this.transformer = x -> transformer.transform(x.model(), x.matrix());
|
||||
buildModel = x -> combineModel.apply(buildModel(x));
|
||||
}
|
||||
|
||||
@@ -113,10 +114,10 @@ public final class TurtleModelParts<T> {
|
||||
var parts = new ArrayList<BakedModel>(4);
|
||||
parts.add(transform(combo.colour() ? colourModel : familyModel, transformation));
|
||||
|
||||
var overlayModelLocation = TurtleBlockEntityRenderer.getTurtleOverlayModel(combo.overlay(), combo.christmas());
|
||||
if (overlayModelLocation != null) {
|
||||
parts.add(transform(ClientPlatformHelper.get().getModel(modelManager, overlayModelLocation), transformation));
|
||||
}
|
||||
if (combo.overlay() != null) addPart(parts, modelManager, transformation, combo.overlay().model());
|
||||
|
||||
var showChristmas = TurtleOverlay.showElfOverlay(combo.overlay(), combo.christmas());
|
||||
if (showChristmas) addPart(parts, modelManager, transformation, TurtleOverlay.ELF_MODEL);
|
||||
|
||||
addUpgrade(parts, transformation, TurtleSide.LEFT, combo.leftUpgrade());
|
||||
addUpgrade(parts, transformation, TurtleSide.RIGHT, combo.rightUpgrade());
|
||||
@@ -124,10 +125,14 @@ public final class TurtleModelParts<T> {
|
||||
return parts;
|
||||
}
|
||||
|
||||
private void addPart(List<BakedModel> parts, ModelManager modelManager, Transformation transformation, ResourceLocation model) {
|
||||
parts.add(transform(ClientPlatformHelper.get().getModel(modelManager, model), transformation));
|
||||
}
|
||||
|
||||
private void addUpgrade(List<BakedModel> parts, Transformation transformation, TurtleSide side, @Nullable UpgradeData<ITurtleUpgrade> upgrade) {
|
||||
if (upgrade == null) return;
|
||||
var model = TurtleUpgradeModellers.getModel(upgrade.upgrade(), upgrade.data(), side);
|
||||
parts.add(transform(model.getModel(), transformation.compose(model.getMatrix())));
|
||||
parts.add(transform(model.model(), transformation.compose(model.matrix())));
|
||||
}
|
||||
|
||||
private BakedModel transform(BakedModel model, Transformation transformation) {
|
||||
|
@@ -21,10 +21,11 @@ import dan200.computercraft.shared.peripheral.speaker.EncodedAudio;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.JukeboxSong;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -60,10 +61,12 @@ public final class ClientNetworkContextImpl implements ClientNetworkContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePlayRecord(BlockPos pos, @Nullable SoundEvent sound, @Nullable String name) {
|
||||
var mc = Minecraft.getInstance();
|
||||
ClientPlatformHelper.get().playStreamingMusic(pos, sound);
|
||||
if (name != null) mc.gui.setNowPlaying(Component.literal(name));
|
||||
public void handlePlayRecord(BlockPos pos, @Nullable Holder<JukeboxSong> song) {
|
||||
if (song == null) {
|
||||
Minecraft.getInstance().levelRenderer.stopJukeboxSongAndNotifyNearby(pos);
|
||||
} else {
|
||||
Minecraft.getInstance().levelRenderer.playJukeboxSong(song, pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -7,8 +7,6 @@ package dan200.computercraft.client.platform;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -28,13 +26,4 @@ public interface ClientPlatformHelper extends dan200.computercraft.impl.client.C
|
||||
* @param tints Block colour tints to apply to the model.
|
||||
*/
|
||||
void renderBakedModel(PoseStack transform, MultiBufferSource buffers, BakedModel model, int lightmapCoord, int overlayLight, @Nullable int[] tints);
|
||||
|
||||
/**
|
||||
* Play a record at a particular position.
|
||||
*
|
||||
* @param pos The position to play this record.
|
||||
* @param sound The record to play, or {@code null} to stop it.
|
||||
* @see net.minecraft.client.renderer.LevelRenderer#playStreamingMusic(SoundEvent, BlockPos)
|
||||
*/
|
||||
void playStreamingMusic(BlockPos pos, @Nullable SoundEvent sound);
|
||||
}
|
||||
|
@@ -62,15 +62,13 @@ public final class CableHighlightRenderer {
|
||||
zDelta = zDelta / len;
|
||||
|
||||
buffer
|
||||
.vertex(matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset))
|
||||
.color(0, 0, 0, 0.4f)
|
||||
.normal(transform.last(), xDelta, yDelta, zDelta)
|
||||
.endVertex();
|
||||
.addVertex(matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset))
|
||||
.setColor(0, 0, 0, 0.4f)
|
||||
.setNormal(transform.last(), xDelta, yDelta, zDelta);
|
||||
buffer
|
||||
.vertex(matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset))
|
||||
.color(0, 0, 0, 0.4f)
|
||||
.normal(transform.last(), xDelta, yDelta, zDelta)
|
||||
.endVertex();
|
||||
.addVertex(matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset))
|
||||
.setColor(0, 0, 0, 0.4f)
|
||||
.setNormal(transform.last(), xDelta, yDelta, zDelta);
|
||||
});
|
||||
|
||||
return true;
|
||||
|
@@ -50,28 +50,23 @@ public final class ModelRenderer {
|
||||
if (idx >= 0 && idx < tints.length) tint = tints[bakedquad.getTintIndex()];
|
||||
}
|
||||
|
||||
var r = (float) (tint >> 16 & 255) / 255.0F;
|
||||
var g = (float) (tint >> 8 & 255) / 255.0F;
|
||||
var b = (float) (tint & 255) / 255.0F;
|
||||
putBulkQuad(buffer, matrix, bakedquad, r, g, b, lightmapCoord, overlayLight, inverted);
|
||||
putBulkQuad(buffer, matrix, bakedquad, tint, lightmapCoord, overlayLight, inverted);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A version of {@link VertexConsumer#putBulkData(PoseStack.Pose, BakedQuad, float, float, float, int, int)} which
|
||||
* A version of {@link VertexConsumer#putBulkData(PoseStack.Pose, BakedQuad, float, float, float, float, int, int)} which
|
||||
* will reverse vertex order when the matrix is inverted.
|
||||
*
|
||||
* @param buffer The buffer to draw to.
|
||||
* @param pose The current matrix stack.
|
||||
* @param quad The quad to draw.
|
||||
* @param red The red tint of this quad.
|
||||
* @param green The green tint of this quad.
|
||||
* @param blue The blue tint of this quad.
|
||||
* @param colour The tint for this quad.
|
||||
* @param lightmapCoord The lightmap coordinate
|
||||
* @param overlayLight The overlay light.
|
||||
* @param invert Whether to reverse the order of this quad.
|
||||
*/
|
||||
private static void putBulkQuad(VertexConsumer buffer, PoseStack.Pose pose, BakedQuad quad, float red, float green, float blue, int lightmapCoord, int overlayLight, boolean invert) {
|
||||
private static void putBulkQuad(VertexConsumer buffer, PoseStack.Pose pose, BakedQuad quad, int colour, int lightmapCoord, int overlayLight, boolean invert) {
|
||||
var matrix = pose.pose();
|
||||
// It's a little dubious to transform using this matrix rather than the normal matrix. This mirrors the logic in
|
||||
// Direction.rotate (so not out of nowhere!), but is a little suspicious.
|
||||
@@ -93,9 +88,9 @@ public final class ModelRenderer {
|
||||
|
||||
var u = Float.intBitsToFloat(vertices[i + 4]);
|
||||
var v = Float.intBitsToFloat(vertices[i + 5]);
|
||||
buffer.vertex(
|
||||
buffer.addVertex(
|
||||
vector.x(), vector.y(), vector.z(),
|
||||
red, green, blue, 1.0F, u, v, overlayLight, lightmapCoord,
|
||||
colour, u, v, overlayLight, lightmapCoord,
|
||||
normalX, normalY, normalZ
|
||||
);
|
||||
}
|
||||
|
@@ -158,7 +158,7 @@ public final class PrintoutRenderer {
|
||||
}
|
||||
|
||||
private static void vertex(VertexConsumer buffer, Matrix4f matrix, float x, float y, float z, float u, float v, int light) {
|
||||
buffer.vertex(matrix, x, y, z).color(255, 255, 255, 255).uv(u, v).uv2(light).endVertex();
|
||||
buffer.addVertex(matrix, x, y, z).setColor(255, 255, 255, 255).setUv(u, v).setLight(light);
|
||||
}
|
||||
|
||||
public static float offsetAt(int page) {
|
||||
|
@@ -52,7 +52,7 @@ public class RenderTypes {
|
||||
* Printout's background texture. {@link RenderType#text(ResourceLocation)} is a <em>little</em> questionable, but
|
||||
* it is what maps use, so should behave the same as vanilla in both item frames and in-hand.
|
||||
*/
|
||||
public static final RenderType PRINTOUT_BACKGROUND = RenderType.text(new ResourceLocation("computercraft", "textures/gui/printout.png"));
|
||||
public static final RenderType PRINTOUT_BACKGROUND = RenderType.text(ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/printout.png"));
|
||||
|
||||
/**
|
||||
* Render type for {@linkplain GuiSprites GUI sprites}.
|
||||
|
@@ -118,10 +118,10 @@ public class SpriteRenderer {
|
||||
*/
|
||||
public void blit(
|
||||
int x, int y, int width, int height, float u0, float v0, float u1, float v1) {
|
||||
builder.vertex(transform, x, y + height, z).color(r, g, b, 255).uv(u0, v1).uv2(light).endVertex();
|
||||
builder.vertex(transform, x + width, y + height, z).color(r, g, b, 255).uv(u1, v1).uv2(light).endVertex();
|
||||
builder.vertex(transform, x + width, y, z).color(r, g, b, 255).uv(u1, v0).uv2(light).endVertex();
|
||||
builder.vertex(transform, x, y, z).color(r, g, b, 255).uv(u0, v0).uv2(light).endVertex();
|
||||
builder.addVertex(transform, x, y + height, z).setColor(r, g, b, 255).setUv(u0, v1).setLight(light);
|
||||
builder.addVertex(transform, x + width, y + height, z).setColor(r, g, b, 255).setUv(u1, v1).setLight(light);
|
||||
builder.addVertex(transform, x + width, y, z).setColor(r, g, b, 255).setUv(u1, v0).setLight(light);
|
||||
builder.addVertex(transform, x, y, z).setColor(r, g, b, 255).setUv(u0, v0).setLight(light);
|
||||
}
|
||||
|
||||
public static float u(TextureAtlasSprite sprite, int x, int width) {
|
||||
|
@@ -11,6 +11,7 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.client.platform.ClientPlatformHelper;
|
||||
import dan200.computercraft.client.turtle.TurtleUpgradeModellers;
|
||||
import dan200.computercraft.shared.turtle.TurtleOverlay;
|
||||
import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity;
|
||||
import dan200.computercraft.shared.util.Holiday;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -21,14 +22,14 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.CommonColors;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class TurtleBlockEntityRenderer implements BlockEntityRenderer<TurtleBlockEntity> {
|
||||
private static final ResourceLocation COLOUR_TURTLE_MODEL = new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_colour");
|
||||
private static final ResourceLocation ELF_OVERLAY_MODEL = new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_elf_overlay");
|
||||
public static final ResourceLocation COLOUR_TURTLE_MODEL = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_colour");
|
||||
|
||||
private final BlockEntityRenderDispatcher renderer;
|
||||
private final Font font;
|
||||
@@ -38,12 +39,6 @@ public class TurtleBlockEntityRenderer implements BlockEntityRenderer<TurtleBloc
|
||||
font = context.getFont();
|
||||
}
|
||||
|
||||
public static @Nullable ResourceLocation getTurtleOverlayModel(@Nullable ResourceLocation overlay, boolean christmas) {
|
||||
if (overlay != null) return overlay;
|
||||
if (christmas) return ELF_OVERLAY_MODEL;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(TurtleBlockEntity turtle, float partialTicks, PoseStack transform, MultiBufferSource buffers, int lightmapCoord, int overlayLight) {
|
||||
transform.pushPose();
|
||||
@@ -62,13 +57,13 @@ public class TurtleBlockEntityRenderer implements BlockEntityRenderer<TurtleBloc
|
||||
transform.pushPose();
|
||||
transform.translate(0.5, 1.2, 0.5);
|
||||
transform.mulPose(mc.getEntityRenderDispatcher().cameraOrientation());
|
||||
transform.scale(-0.025f, -0.025f, 0.025f);
|
||||
transform.scale(0.025f, -0.025f, 0.025f);
|
||||
|
||||
var matrix = transform.last().pose();
|
||||
var opacity = (int) (mc.options.getBackgroundOpacity(0.25f) * 255) << 24;
|
||||
var width = -font.width(label) / 2.0f;
|
||||
font.drawInBatch(label, width, (float) 0, 0x20ffffff, false, matrix, buffers, Font.DisplayMode.SEE_THROUGH, opacity, lightmapCoord);
|
||||
font.drawInBatch(label, width, (float) 0, 0xffffffff, false, matrix, buffers, Font.DisplayMode.NORMAL, 0, lightmapCoord);
|
||||
font.drawInBatch(label, width, (float) 0, CommonColors.WHITE, false, matrix, buffers, Font.DisplayMode.NORMAL, 0, lightmapCoord);
|
||||
|
||||
transform.popPose();
|
||||
}
|
||||
@@ -98,10 +93,11 @@ public class TurtleBlockEntityRenderer implements BlockEntityRenderer<TurtleBloc
|
||||
}
|
||||
|
||||
// Render the overlay
|
||||
var overlayModel = getTurtleOverlayModel(overlay, Holiday.getCurrent() == Holiday.CHRISTMAS);
|
||||
if (overlayModel != null) {
|
||||
renderModel(transform, buffers, lightmapCoord, overlayLight, overlayModel, null);
|
||||
}
|
||||
if (overlay != null) renderModel(transform, buffers, lightmapCoord, overlayLight, overlay.model(), null);
|
||||
|
||||
// And the Christmas overlay.
|
||||
var showChristmas = TurtleOverlay.showElfOverlay(overlay, Holiday.getCurrent() == Holiday.CHRISTMAS);
|
||||
if (showChristmas) renderModel(transform, buffers, lightmapCoord, overlayLight, TurtleOverlay.ELF_MODEL, null);
|
||||
|
||||
// Render the upgrades
|
||||
renderUpgrade(transform, buffers, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks);
|
||||
@@ -121,8 +117,8 @@ public class TurtleBlockEntityRenderer implements BlockEntityRenderer<TurtleBloc
|
||||
transform.translate(0.0f, -0.5f, -0.5f);
|
||||
|
||||
var model = TurtleUpgradeModellers.getModel(upgrade, turtle.getAccess(), side);
|
||||
applyTransformation(transform, model.getMatrix());
|
||||
renderModel(transform, buffers, lightmapCoord, overlayLight, model.getModel(), null);
|
||||
applyTransformation(transform, model.matrix());
|
||||
renderModel(transform, buffers, lightmapCoord, overlayLight, model.model(), null);
|
||||
|
||||
transform.popPose();
|
||||
}
|
||||
|
@@ -5,9 +5,11 @@
|
||||
package dan200.computercraft.client.render.monitor;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexBuffer;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import dan200.computercraft.annotations.ForgeOverride;
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
@@ -18,6 +20,7 @@ import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.client.render.vbo.DirectBuffers;
|
||||
import dan200.computercraft.client.render.vbo.DirectVertexBuffer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.core.util.Nullability;
|
||||
import dan200.computercraft.shared.config.Config;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorBlockEntity;
|
||||
@@ -31,6 +34,7 @@ import org.joml.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -160,13 +164,12 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
||||
var shader = RenderTypes.getMonitorTextureBufferShader();
|
||||
shader.setupUniform(renderState.tboUniform);
|
||||
|
||||
var buffer = Tesselator.getInstance().getBuilder();
|
||||
buffer.begin(RenderTypes.MONITOR_TBO.mode(), RenderTypes.MONITOR_TBO.format());
|
||||
var buffer = Tesselator.getInstance().begin(RenderTypes.MONITOR_TBO.mode(), RenderTypes.MONITOR_TBO.format());
|
||||
tboVertex(buffer, matrix, -xMargin, -yMargin);
|
||||
tboVertex(buffer, matrix, -xMargin, pixelHeight + yMargin);
|
||||
tboVertex(buffer, matrix, pixelWidth + xMargin, -yMargin);
|
||||
tboVertex(buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin);
|
||||
RenderTypes.MONITOR_TBO.end(buffer, VertexSorting.DISTANCE_TO_ORIGIN);
|
||||
RenderTypes.MONITOR_TBO.draw(Nullability.assertNonNull(buffer.build()));
|
||||
}
|
||||
case VBO -> {
|
||||
var backgroundBuffer = assertNonNull(renderState.backgroundBuffer);
|
||||
@@ -242,13 +245,13 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
||||
|
||||
private static void tboVertex(VertexConsumer builder, Matrix4f matrix, float x, float y) {
|
||||
// We encode position in the UV, as that's not transformed by the matrix.
|
||||
builder.vertex(matrix, x, y, 0).uv(x, y).endVertex();
|
||||
builder.addVertex(matrix, x, y, 0).setUv(x, y);
|
||||
}
|
||||
|
||||
private static ByteBuffer getBuffer(int capacity) {
|
||||
var buffer = backingBuffer;
|
||||
if (buffer == null || buffer.capacity() < capacity) {
|
||||
buffer = backingBuffer = buffer == null ? MemoryTracker.create(capacity) : MemoryTracker.resize(buffer, capacity);
|
||||
buffer = backingBuffer = buffer == null ? MemoryUtil.memAlloc(capacity) : MemoryUtil.memRealloc(buffer, capacity);
|
||||
}
|
||||
|
||||
buffer.clear();
|
||||
|
@@ -72,18 +72,16 @@ public final class MonitorHighlightRenderer {
|
||||
|
||||
private static void line(VertexConsumer buffer, Matrix4f transform, PoseStack.Pose normal, float x, float y, float z, Direction direction) {
|
||||
buffer
|
||||
.vertex(transform, x, y, z)
|
||||
.color(0, 0, 0, 0.4f)
|
||||
.normal(normal, direction.getStepX(), direction.getStepY(), direction.getStepZ())
|
||||
.endVertex();
|
||||
.addVertex(transform, x, y, z)
|
||||
.setColor(0, 0, 0, 0.4f)
|
||||
.setNormal(normal, direction.getStepX(), direction.getStepY(), direction.getStepZ());
|
||||
buffer
|
||||
.vertex(transform,
|
||||
.addVertex(transform,
|
||||
x + direction.getStepX(),
|
||||
y + direction.getStepY(),
|
||||
z + direction.getStepZ()
|
||||
)
|
||||
.color(0, 0, 0, 0.4f)
|
||||
.normal(normal, direction.getStepX(), direction.getStepY(), direction.getStepZ())
|
||||
.endVertex();
|
||||
.setColor(0, 0, 0, 0.4f)
|
||||
.setNormal(normal, direction.getStepX(), direction.getStepY(), direction.getStepZ());
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@
|
||||
|
||||
package dan200.computercraft.client.render.text;
|
||||
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
@@ -28,7 +27,7 @@ import static org.lwjgl.system.MemoryUtil.*;
|
||||
* <ul>
|
||||
* <li>No transformation matrix (not needed for VBOs).</li>
|
||||
* <li>Only works with {@link DefaultVertexFormat#POSITION_COLOR_TEX_LIGHTMAP}.</li>
|
||||
* <li>The buffer <strong>MUST</strong> be allocated with {@link MemoryTracker}, and not through any other means.</li>
|
||||
* <li>The buffer <strong>MUST</strong> be allocated with {@link MemoryUtil}, and not through any other means.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Note this is almost an exact copy of {@link FixedWidthFontRenderer}. While the code duplication is unfortunate,
|
||||
|
@@ -32,7 +32,7 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA
|
||||
* {@link DirectFixedWidthFontRenderer}.
|
||||
*/
|
||||
public final class FixedWidthFontRenderer {
|
||||
public static final ResourceLocation FONT = new ResourceLocation("computercraft", "textures/gui/term_font.png");
|
||||
public static final ResourceLocation FONT = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/term_font.png");
|
||||
|
||||
public static final int FONT_HEIGHT = 9;
|
||||
public static final int FONT_WIDTH = 6;
|
||||
@@ -221,9 +221,9 @@ public final class FixedWidthFontRenderer {
|
||||
var consumer = c.consumer();
|
||||
byte r = rgba[0], g = rgba[1], b = rgba[2], a = rgba[3];
|
||||
|
||||
consumer.vertex(poseMatrix, x1, y1, z).color(r, g, b, a).uv(u1, v1).uv2(light).endVertex();
|
||||
consumer.vertex(poseMatrix, x1, y2, z).color(r, g, b, a).uv(u1, v2).uv2(light).endVertex();
|
||||
consumer.vertex(poseMatrix, x2, y2, z).color(r, g, b, a).uv(u2, v2).uv2(light).endVertex();
|
||||
consumer.vertex(poseMatrix, x2, y1, z).color(r, g, b, a).uv(u2, v1).uv2(light).endVertex();
|
||||
consumer.addVertex(poseMatrix, x1, y1, z).setColor(r, g, b, a).setUv(u1, v1).setLight(light);
|
||||
consumer.addVertex(poseMatrix, x1, y2, z).setColor(r, g, b, a).setUv(u1, v2).setLight(light);
|
||||
consumer.addVertex(poseMatrix, x2, y2, z).setColor(r, g, b, a).setUv(u2, v2).setLight(light);
|
||||
consumer.addVertex(poseMatrix, x2, y1, z).setColor(r, g, b, a).setUv(u2, v1).setLight(light);
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ import javax.annotation.Nullable;
|
||||
* An instance of a speaker, which is either playing a {@link DfpwmStream} stream or a normal sound.
|
||||
*/
|
||||
public class SpeakerInstance {
|
||||
public static final ResourceLocation DFPWM_STREAM = new ResourceLocation(ComputerCraftAPI.MOD_ID, "speaker.dfpwm_fake_audio_should_not_be_played");
|
||||
public static final ResourceLocation DFPWM_STREAM = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "speaker.dfpwm_fake_audio_should_not_be_played");
|
||||
|
||||
private @Nullable DfpwmStream currentStream;
|
||||
private @Nullable SpeakerSound sound;
|
||||
|
@@ -5,6 +5,7 @@
|
||||
package dan200.computercraft.client.turtle;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.client.ModelLocation;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
@@ -38,23 +39,23 @@ public class TurtleModemModeller implements TurtleUpgradeModeller<TurtleModem> {
|
||||
}
|
||||
|
||||
private record ModemModels(
|
||||
ResourceLocation leftOffModel, ResourceLocation rightOffModel,
|
||||
ResourceLocation leftOnModel, ResourceLocation rightOnModel
|
||||
ModelLocation leftOffModel, ModelLocation rightOffModel,
|
||||
ModelLocation leftOnModel, ModelLocation rightOnModel
|
||||
) {
|
||||
private static final ModemModels NORMAL = create("normal");
|
||||
private static final ModemModels ADVANCED = create("advanced");
|
||||
|
||||
public static ModemModels create(String type) {
|
||||
return new ModemModels(
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_modem_" + type + "_off_left"),
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_modem_" + type + "_off_right"),
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_modem_" + type + "_on_left"),
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_modem_" + type + "_on_right")
|
||||
ModelLocation.ofResource(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_modem_" + type + "_off_left")),
|
||||
ModelLocation.ofResource(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_modem_" + type + "_off_right")),
|
||||
ModelLocation.ofResource(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_modem_" + type + "_on_left")),
|
||||
ModelLocation.ofResource(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "block/turtle_modem_" + type + "_on_right"))
|
||||
);
|
||||
}
|
||||
|
||||
public Stream<ResourceLocation> getDependencies() {
|
||||
return Stream.of(leftOffModel, rightOffModel, leftOnModel, rightOnModel);
|
||||
return Stream.of(leftOffModel, rightOffModel, leftOnModel, rightOnModel).flatMap(ModelLocation::getDependencies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,15 +6,18 @@ package dan200.computercraft.data.client;
|
||||
|
||||
import dan200.computercraft.client.gui.GuiSprites;
|
||||
import dan200.computercraft.data.DataProviders;
|
||||
import dan200.computercraft.shared.turtle.TurtleOverlay;
|
||||
import dan200.computercraft.shared.turtle.inventory.UpgradeSlot;
|
||||
import net.minecraft.client.renderer.texture.atlas.SpriteSource;
|
||||
import net.minecraft.client.renderer.texture.atlas.SpriteSources;
|
||||
import net.minecraft.client.renderer.texture.atlas.sources.SingleFile;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
@@ -26,9 +29,9 @@ public final class ClientDataProviders {
|
||||
private ClientDataProviders() {
|
||||
}
|
||||
|
||||
public static void add(DataProviders.GeneratorSink generator) {
|
||||
public static void add(DataProviders.GeneratorSink generator, CompletableFuture<HolderLookup.Provider> registries) {
|
||||
generator.addFromCodec("Block atlases", PackType.CLIENT_RESOURCES, "atlases", SpriteSources.FILE_CODEC, out -> {
|
||||
out.accept(new ResourceLocation("blocks"), List.of(
|
||||
out.accept(ResourceLocation.withDefaultNamespace("blocks"), List.of(
|
||||
new SingleFile(UpgradeSlot.LEFT_UPGRADE, Optional.empty()),
|
||||
new SingleFile(UpgradeSlot.RIGHT_UPGRADE, Optional.empty())
|
||||
));
|
||||
@@ -44,5 +47,12 @@ public final class ClientDataProviders {
|
||||
GuiSprites.COMPUTER_COLOUR.textures()
|
||||
).flatMap(x -> x).<SpriteSource>map(x -> new SingleFile(x, Optional.empty())).toList());
|
||||
});
|
||||
|
||||
generator.add(pack -> new ExtraModelsProvider(pack, registries) {
|
||||
@Override
|
||||
public Stream<ResourceLocation> getModels(HolderLookup.Provider registries) {
|
||||
return registries.lookupOrThrow(TurtleOverlay.REGISTRY).listElements().map(x -> x.value().model());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.data.client;
|
||||
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import dan200.computercraft.client.model.ExtraModels;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A data provider to generate {@link ExtraModels}.
|
||||
*/
|
||||
abstract class ExtraModelsProvider implements DataProvider {
|
||||
private final Path path;
|
||||
private final CompletableFuture<HolderLookup.Provider> registries;
|
||||
|
||||
ExtraModelsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
|
||||
path = output.getOutputFolder(PackOutput.Target.RESOURCE_PACK).resolve(ExtraModels.PATH.getNamespace()).resolve(ExtraModels.PATH.getPath());
|
||||
this.registries = registries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a stream of models to load.
|
||||
*
|
||||
* @param registries The current registries.
|
||||
* @return The collection of extra models to load.
|
||||
*/
|
||||
public abstract Stream<ResourceLocation> getModels(HolderLookup.Provider registries);
|
||||
|
||||
@Override
|
||||
public final CompletableFuture<?> run(CachedOutput output) {
|
||||
return registries.thenCompose(registries -> {
|
||||
var models = new ExtraModels(getModels(registries).sorted().toList());
|
||||
var json = ExtraModels.CODEC.encodeStart(JsonOps.INSTANCE, models).getOrThrow(IllegalStateException::new);
|
||||
return DataProvider.saveStable(output, json, path);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getName() {
|
||||
return "Extra Models";
|
||||
}
|
||||
}
|
1
projects/common/src/generated/resources/assets/computercraft/extra_models.json
generated
Normal file
1
projects/common/src/generated/resources/assets/computercraft/extra_models.json
generated
Normal file
@@ -0,0 +1 @@
|
||||
["computercraft:block/turtle_rainbow_overlay", "computercraft:block/turtle_trans_overlay"]
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user