mirror of
https://github.com/PuzzleMC/Puzzle.git
synced 2025-12-15 19:35:10 +01:00
Compare commits
1 Commits
7149307f1f
...
feat/mbp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99a450e395 |
@@ -1,6 +0,0 @@
|
||||
# Puzzle v2.2.0
|
||||
- Setup a **multiversion** build environment
|
||||
- Puzzle will now always be up-to-date on all relevant versions of Minecraft
|
||||
(Fabric/Forge 1.20.1; Fabric/NeoForge 1.21.1, 1.21.5, 1.21.8, 1.21.10)
|
||||
- Migrate to Mojang mappings in preparation for upcoming non-obfuscated releases
|
||||
- Updated Entity Model/Texture Features compatibility
|
||||
119
build.gradle
Executable file
119
build.gradle
Executable file
@@ -0,0 +1,119 @@
|
||||
import groovy.json.JsonSlurper
|
||||
import groovy.json.JsonOutput
|
||||
|
||||
plugins {
|
||||
id "architectury-plugin" version "3.4-SNAPSHOT"
|
||||
id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false
|
||||
id "me.shedaniel.unified-publishing" version "0.1.+" apply false
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||
}
|
||||
|
||||
architectury {
|
||||
minecraft = rootProject.minecraft_version
|
||||
}
|
||||
|
||||
subprojects {
|
||||
apply plugin: "dev.architectury.loom"
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url = "https://api.modrinth.com/maven"
|
||||
}
|
||||
maven { url "https://maven.terraformersmc.com/releases" }
|
||||
maven {
|
||||
name = 'AperLambda'
|
||||
url = 'https://aperlambda.github.io/maven'
|
||||
}
|
||||
mavenCentral()
|
||||
maven {
|
||||
name 'Gegy'
|
||||
url 'https://maven.gegy.dev'
|
||||
}
|
||||
|
||||
maven {
|
||||
url "https://www.cursemaven.com"
|
||||
content {
|
||||
includeGroup "curse.maven"
|
||||
}
|
||||
}
|
||||
maven {
|
||||
name = 'JitPack'
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
maven {
|
||||
url "https://maven.shedaniel.me/"
|
||||
}
|
||||
maven { url "https://maven.quiltmc.org/repository/release/" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
|
||||
// The following line declares the yarn mappings you may select this one as well.
|
||||
mappings loom.layered {
|
||||
it.mappings("net.fabricmc:yarn:$rootProject.yarn_mappings:v2")
|
||||
it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version")
|
||||
}
|
||||
modCompileOnlyApi ("maven.modrinth:cull-leaves:${project.cull_leaves_version}")
|
||||
|
||||
modCompileOnlyApi ("maven.modrinth:iris:${project.iris_version}")
|
||||
modCompileOnly ("maven.modrinth:cit-resewn:${project.cit_resewn_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:continuity:${project.continuity_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:animatica:${project.animatica_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:colormatic:${project.colormatic_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:borderless-mining:${project.borderless_mining_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:dynamic-fps:${project.dynamic_fps_version}")
|
||||
modCompileOnlyApi ("com.moandjiezana.toml:toml4j:${project.toml4j_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:entitytexturefeatures:${project.etf_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:entity-model-features:${project.emf_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:completeconfig:${project.complete_config_version}")
|
||||
//modImplementation ("maven.modrinth:exordium:${project.exordium_version}")
|
||||
|
||||
|
||||
modCompileOnlyApi ("maven.modrinth:lambdynamiclights:${project.ldl_version}")
|
||||
modCompileOnly("dev.lambdaurora.lambdynamiclights:lambdynamiclights-api:${project.ldl_version}")
|
||||
modCompileOnlyApi ("maven.modrinth:lambdabettergrass:${project.lbg_version}")
|
||||
modCompileOnlyApi "dev.lambdaurora:spruceui:${project.spruceui_version}"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
apply plugin: "java"
|
||||
apply plugin: "architectury-plugin"
|
||||
apply plugin: "maven-publish"
|
||||
|
||||
archivesBaseName = rootProject.archives_base_name
|
||||
version = rootProject.mod_version
|
||||
group = rootProject.maven_group
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = "UTF-8"
|
||||
options.release = 21
|
||||
}
|
||||
ext {
|
||||
releaseChangelog = {
|
||||
def changes = new StringBuilder()
|
||||
changes << "## Puzzle v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/PuzzleMC/Puzzle/commits/)"
|
||||
def proc = "git log --max-count=1 --pretty=format:%s".execute()
|
||||
proc.in.eachLine { line ->
|
||||
def processedLine = line.toString()
|
||||
if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) {
|
||||
changes << "\n- ${processedLine.capitalize()}"
|
||||
}
|
||||
}
|
||||
proc.waitFor()
|
||||
return changes.toString()
|
||||
}
|
||||
}
|
||||
processResources {
|
||||
// Minify json resources
|
||||
doLast {
|
||||
fileTree(dir: outputs.files.asPath, include: "**/*.json").each {
|
||||
File file -> file.text = JsonOutput.toJson(new JsonSlurper().parse(file))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
}
|
||||
292
build.gradle.kts
292
build.gradle.kts
@@ -1,292 +0,0 @@
|
||||
plugins {
|
||||
id("dev.architectury.loom")
|
||||
id("architectury-plugin")
|
||||
id("me.modmuss50.mod-publish-plugin")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
val minecraft = stonecutter.current.version
|
||||
val loader = loom.platform.get().name.lowercase()
|
||||
|
||||
version = "${mod.version}+$minecraft"
|
||||
group = mod.group
|
||||
base {
|
||||
archivesName.set("${mod.id}-$loader")
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://maven.neoforged.net/releases/")
|
||||
|
||||
// ModMenu
|
||||
maven("https://maven.terraformersmc.com/")
|
||||
maven("https://maven.nucleoid.xyz/")
|
||||
|
||||
// MidnightLib
|
||||
maven("https://maven.midnightdust.eu/releases/")
|
||||
|
||||
// Jigsaw modules
|
||||
maven("https://api.modrinth.com/maven")
|
||||
maven("https://maven.terraformersmc.com/releases")
|
||||
maven("https://aperlambda.github.io/maven")
|
||||
mavenCentral()
|
||||
maven("https://maven.gegy.dev")
|
||||
|
||||
maven("https://www.cursemaven.com")
|
||||
maven("https://jitpack.io")
|
||||
maven("https://maven.shedaniel.me/")
|
||||
maven("https://maven.quiltmc.org/repository/release/")
|
||||
}
|
||||
|
||||
val mappingsAttribute = Attribute.of("net.minecraft.mappings", String::class.java)
|
||||
|
||||
dependencies {
|
||||
attributesSchema {
|
||||
attribute(mappingsAttribute)
|
||||
}
|
||||
minecraft("com.mojang:minecraft:$minecraft")
|
||||
|
||||
// Jigsaw modules (GUI compat mods)
|
||||
modCompileOnlyApi ("maven.modrinth:cull-leaves:${mod.jigsaw("cull_leaves_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:iris:${mod.jigsaw("iris_version")}")
|
||||
modCompileOnly ("maven.modrinth:cit-resewn:${mod.jigsaw("cit_resewn_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:continuity:${mod.jigsaw("continuity_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:animatica:${mod.jigsaw("animatica_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:colormatic:${mod.jigsaw("colormatic_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:borderless-mining:${mod.jigsaw("borderless_mining_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:dynamic-fps:${mod.jigsaw("dynamic_fps_version")}")
|
||||
modCompileOnlyApi ("com.moandjiezana.toml:toml4j:${mod.jigsaw("toml4j_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:entitytexturefeatures:${mod.jigsaw("etf_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:entity-model-features:${mod.jigsaw("emf_version")}")
|
||||
modCompileOnlyApi ("maven.modrinth:completeconfig:${mod.jigsaw("complete_config_version")}")
|
||||
//modImplementation ("maven.modrinth:exordium:${project.exordium_version}")
|
||||
|
||||
modCompileOnlyApi ("maven.modrinth:lambdabettergrass:${mod.jigsaw("lbg_version")}")
|
||||
modCompileOnlyApi ("dev.lambdaurora:spruceui:${mod.jigsaw("spruceui_version")}")
|
||||
|
||||
// Required for Lambda's mods (DO NOT DEPEND ON OTHERWISE)
|
||||
modCompileOnly ("dev.yumi.mc.core:yumi-mc-foundation:1.0.0-alpha.15+1.21.1")
|
||||
modCompileOnlyApi ("org.aperlambda:lambdajcommon:1.8.1") {
|
||||
exclude(group = "com.google.code.gson")
|
||||
exclude(group = "com.google.guava")
|
||||
}
|
||||
|
||||
// MidnightLib
|
||||
val midnightlib = "eu.midnightdust:midnightlib:${mod.dep("midnightlib_version")}+${minecraft}-${loader}"
|
||||
modImplementation(midnightlib)
|
||||
include(midnightlib)
|
||||
|
||||
if (loader == "fabric") {
|
||||
modImplementation("net.fabricmc:fabric-loader:${mod.dep("fabric_loader")}")
|
||||
modImplementation("com.terraformersmc:modmenu:${mod.dep("modmenu_version")}")
|
||||
|
||||
// Fabric API is required to load modded resources
|
||||
modImplementation("net.fabricmc.fabric-api:fabric-api:${mod.dep("fabric_version")}")
|
||||
|
||||
modCompileOnly ("dev.lambdaurora.lambdynamiclights:lambdynamiclights-api:${mod.jigsaw("ldl_version")}")
|
||||
modCompileOnly ("dev.lambdaurora.lambdynamiclights:lambdynamiclights-runtime:${mod.jigsaw("ldl_version")}")
|
||||
}
|
||||
if (loader == "neoforge") {
|
||||
"neoForge"("net.neoforged:neoforge:${mod.dep("neoforge_loader")}")
|
||||
|
||||
modCompileOnly ("dev.lambdaurora.lambdynamiclights:lambdynamiclights-api:${mod.jigsaw("ldl_version")}") {
|
||||
attributes {
|
||||
attribute(mappingsAttribute, "mojmap")
|
||||
}
|
||||
}
|
||||
modCompileOnly ("dev.lambdaurora.lambdynamiclights:lambdynamiclights-runtime:${mod.jigsaw("ldl_version")}") {
|
||||
attributes {
|
||||
attribute(mappingsAttribute, "mojmap")
|
||||
}
|
||||
}
|
||||
}
|
||||
mappings (loom.officialMojangMappings())
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = rootProject.file("src/main/resources/puzzle-models.accesswidener")
|
||||
|
||||
decompilers {
|
||||
get("vineflower").apply { // Adds names to lambdas - useful for mixins
|
||||
options.put("mark-corresponding-synthetics", "1")
|
||||
}
|
||||
}
|
||||
if (loader == "forge") {
|
||||
forge.mixinConfigs("puzzle.mixins.json")
|
||||
}
|
||||
}
|
||||
|
||||
publishMods {
|
||||
val modrinthToken = System.getenv("MODRINTH_TOKEN")
|
||||
val curseforgeToken = System.getenv("CURSEFORGE_TOKEN")
|
||||
val githubToken = System.getenv("GITHUB_TOKEN").orEmpty()
|
||||
|
||||
file = project.tasks.remapJar.get().archiveFile
|
||||
dryRun = modrinthToken == null || curseforgeToken == null
|
||||
|
||||
displayName = "${mod.name} ${mod.version} - ${loader.replaceFirstChar { it.uppercase() }} ${property("mod.mc_title")}"
|
||||
version = "${mod.version}+${property("mod.mc_title")}-${loader}"
|
||||
changelog = rootProject.file("CHANGELOG.md").readText()
|
||||
type = STABLE
|
||||
|
||||
modLoaders.add(loader)
|
||||
if (loader == "fabric") {
|
||||
modLoaders.add("quilt")
|
||||
}
|
||||
|
||||
val targets = property("mod.mc_targets").toString().split(' ')
|
||||
modrinth {
|
||||
projectId = property("publish.modrinth").toString()
|
||||
accessToken = modrinthToken
|
||||
targets.forEach(minecraftVersions::add)
|
||||
requires("midnightlib")
|
||||
if (loader == "fabric") {
|
||||
requires("fabric-api")
|
||||
}
|
||||
}
|
||||
|
||||
curseforge {
|
||||
projectId = property("publish.curseforge").toString()
|
||||
accessToken = curseforgeToken.toString()
|
||||
targets.forEach(minecraftVersions::add)
|
||||
requires("midnightlib")
|
||||
if (loader == "fabric") {
|
||||
requires("fabric-api")
|
||||
}
|
||||
}
|
||||
|
||||
// github {
|
||||
// accessToken = githubToken
|
||||
// repository = "TeamMidnightDust/MidnightLib"
|
||||
// commitish = "multiversion" // This is the branch the release tag will be created from
|
||||
//
|
||||
// tagName = "v" + properties["mod.version"]
|
||||
//
|
||||
// // Allow the release to be initially created without any files.
|
||||
// allowEmptyFiles = true
|
||||
// }
|
||||
}
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
name = "MidnightDust"
|
||||
url = uri("https://maven.midnightdust.eu/releases")
|
||||
credentials(PasswordCredentials::class)
|
||||
}
|
||||
}
|
||||
publications {
|
||||
create<MavenPublication>("mavenJava") {
|
||||
pom {
|
||||
groupId = "eu.midnightdust"
|
||||
artifactId = project.mod.id
|
||||
version = "${project.version}-${loader}"
|
||||
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
val java = if (stonecutter.eval(minecraft, ">=1.20.5")) JavaVersion.VERSION_21 else JavaVersion.VERSION_17
|
||||
targetCompatibility = java
|
||||
sourceCompatibility = java
|
||||
}
|
||||
|
||||
val shadowBundle: Configuration by configurations.creating {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
}
|
||||
|
||||
tasks.shadowJar {
|
||||
configurations = listOf(shadowBundle)
|
||||
archiveClassifier = "dev-shadow"
|
||||
}
|
||||
|
||||
tasks.remapJar {
|
||||
injectAccessWidener = true
|
||||
input = tasks.shadowJar.get().archiveFile
|
||||
archiveClassifier = null
|
||||
dependsOn(tasks.shadowJar)
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
archiveClassifier = "dev"
|
||||
}
|
||||
|
||||
val buildAndCollect = tasks.register<Copy>("buildAndCollect") {
|
||||
group = "build"
|
||||
from(tasks.remapJar.get().archiveFile, tasks.remapSourcesJar.get().archiveFile)
|
||||
into(rootProject.layout.buildDirectory.file("libs/${mod.version}/$loader"))
|
||||
dependsOn("build")
|
||||
}
|
||||
|
||||
if (stonecutter.current.isActive) {
|
||||
rootProject.tasks.register("buildActive") {
|
||||
group = "project"
|
||||
dependsOn(buildAndCollect)
|
||||
}
|
||||
|
||||
rootProject.tasks.register("runActive") {
|
||||
group = "project"
|
||||
dependsOn(tasks.named("runClient"))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
properties(
|
||||
listOf("fabric.mod.json"),
|
||||
"id" to mod.id,
|
||||
"name" to mod.name,
|
||||
"version" to mod.version,
|
||||
"minecraft" to mod.prop("mc_dep_fabric")
|
||||
)
|
||||
properties(
|
||||
listOf("META-INF/mods.toml", "pack.mcmeta"),
|
||||
"id" to mod.id,
|
||||
"name" to mod.name,
|
||||
"version" to mod.version,
|
||||
"minecraft" to mod.prop("mc_dep_forgelike")
|
||||
)
|
||||
properties(
|
||||
listOf("META-INF/neoforge.mods.toml", "pack.mcmeta"),
|
||||
"id" to mod.id,
|
||||
"name" to mod.name,
|
||||
"version" to mod.version,
|
||||
"minecraft" to mod.prop("mc_dep_forgelike")
|
||||
)
|
||||
}
|
||||
|
||||
tasks.build {
|
||||
group = "versioned"
|
||||
description = "Must run through 'chiseledBuild'"
|
||||
}
|
||||
|
||||
|
||||
stonecutter {
|
||||
constants {
|
||||
arrayOf("fabric", "neoforge").forEach { it -> put(it, loader == it) }
|
||||
}
|
||||
|
||||
replacements.string {
|
||||
direction = eval(current.version, ">=1.21.8")
|
||||
replace("context.renderComponentTooltip(", "context.setComponentTooltipForNextFrame(")
|
||||
}
|
||||
replacements.string {
|
||||
direction = eval(current.version, ">=1.21.5")
|
||||
replace("getTextureImage", "loadContents")
|
||||
}
|
||||
replacements.string {
|
||||
direction = eval(current.version, ">=1.21.5")
|
||||
replace("TextureImage", "TextureContents")
|
||||
}
|
||||
replacements.string {
|
||||
direction = eval(current.version, ">=1.21.5")
|
||||
replace("SimpleTexture", "ReloadableTexture")
|
||||
}
|
||||
replacements.string {
|
||||
direction = eval(current.version, ">=1.21")
|
||||
replace("new ResourceLocation", "ResourceLocation.fromNamespaceAndPath")
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
kotlin("jvm") version "2.0.20"
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.kotlin.dsl.expand
|
||||
import org.gradle.kotlin.dsl.maven
|
||||
import org.gradle.language.jvm.tasks.ProcessResources
|
||||
import java.util.*
|
||||
|
||||
val Project.mod: ModData get() = ModData(this)
|
||||
fun Project.prop(key: String): String? = findProperty(key)?.toString()
|
||||
fun String.upperCaseFirst() = replaceFirstChar { if (it.isLowerCase()) it.uppercaseChar() else it }
|
||||
|
||||
fun RepositoryHandler.strictMaven(url: String, alias: String, vararg groups: String) = exclusiveContent {
|
||||
forRepository { maven(url) { name = alias } }
|
||||
filter { groups.forEach(::includeGroup) }
|
||||
}
|
||||
|
||||
fun ProcessResources.properties(files: Iterable<String>, vararg properties: Pair<String, Any>) {
|
||||
for ((name, value) in properties) inputs.property(name, value)
|
||||
filesMatching(files) {
|
||||
expand(properties.toMap())
|
||||
}
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class ModData(private val project: Project) {
|
||||
val id: String get() = requireNotNull(project.prop("mod.id")) { "Missing 'mod.id'" }
|
||||
val name: String get() = requireNotNull(project.prop("mod.name")) { "Missing 'mod.name'" }
|
||||
val version: String get() = requireNotNull(project.prop("mod.version")) { "Missing 'mod.version'" }
|
||||
val group: String get() = requireNotNull(project.prop("mod.group")) { "Missing 'mod.group'" }
|
||||
|
||||
fun prop(key: String) = requireNotNull(project.prop("mod.$key")) { "Missing 'mod.$key'" }
|
||||
fun dep(key: String) = requireNotNull(project.prop("deps.$key")) { "Missing 'deps.$key'" }
|
||||
fun jigsaw(key: String) = requireNotNull(project.prop("jigsaws.$key")) { "Missing 'jigsaws.$key'" }
|
||||
}
|
||||
34
common/build.gradle
Normal file
34
common/build.gradle
Normal file
@@ -0,0 +1,34 @@
|
||||
architectury {
|
||||
common(rootProject.enabled_platforms.split(","))
|
||||
}
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/puzzle-models.accesswidener")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
|
||||
// Do NOT use other classes from fabric loader
|
||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||
modCompileOnly "maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric"
|
||||
|
||||
modCompileOnly "org.quiltmc:quilt-loader:${rootProject.quilt_loader_version}"
|
||||
modCompileOnlyApi "org.quiltmc.quilted-fabric-api:quilted-fabric-api:${rootProject.quilt_fabric_api_version}"
|
||||
modCompileOnlyApi ("org.aperlambda:lambdajcommon:1.8.1") {
|
||||
exclude group: 'com.google.code.gson'
|
||||
exclude group: 'com.google.guava'
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenCommon(MavenPublication) {
|
||||
artifactId = rootProject.archives_base_name
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
|
||||
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||
repositories {
|
||||
// Add repositories to publish to here.
|
||||
}
|
||||
}
|
||||
32
common/src/main/java/net/puzzlemc/core/PuzzleCore.java
Executable file
32
common/src/main/java/net/puzzlemc/core/PuzzleCore.java
Executable file
@@ -0,0 +1,32 @@
|
||||
package net.puzzlemc.core;
|
||||
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.SynchronousResourceReloader;
|
||||
import net.puzzlemc.core.config.PuzzleConfig;
|
||||
import net.puzzlemc.gui.PuzzleGui;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
import net.puzzlemc.splashscreen.PuzzleSplashScreen;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class PuzzleCore {
|
||||
public final static String MOD_ID = "puzzle";
|
||||
private static final List<PuzzleModule> MODULES = new ArrayList<>();
|
||||
|
||||
public static void initModules() {
|
||||
PuzzleConfig.init(MOD_ID, PuzzleConfig.class);
|
||||
Collections.addAll(MODULES, PuzzleGui.INSTANCE, PuzzleSplashScreen.INSTANCE, PuzzlePredicates.INSTANCE);
|
||||
|
||||
MODULES.forEach(PuzzleModule::init);
|
||||
}
|
||||
|
||||
public static class PuzzleResourceManager implements SynchronousResourceReloader {
|
||||
public static PuzzleResourceManager INSTANCE = new PuzzleResourceManager();
|
||||
@Override
|
||||
public void reload(ResourceManager manager) {
|
||||
MODULES.forEach(module -> module.reloadResources(manager));
|
||||
}
|
||||
}
|
||||
}
|
||||
13
common/src/main/java/net/puzzlemc/core/PuzzleModule.java
Normal file
13
common/src/main/java/net/puzzlemc/core/PuzzleModule.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package net.puzzlemc.core;
|
||||
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public interface PuzzleModule {
|
||||
default void init() {}
|
||||
default void reloadResources(ResourceManager manager) {}
|
||||
String getModuleId();
|
||||
|
||||
default Logger getLogger() {return LoggerFactory.getLogger("puzzle/"+getModuleId());}
|
||||
}
|
||||
0
src/main/java/net/puzzlemc/core/config/PuzzleConfig.java → common/src/main/java/net/puzzlemc/core/config/PuzzleConfig.java
Normal file → Executable file
0
src/main/java/net/puzzlemc/core/config/PuzzleConfig.java → common/src/main/java/net/puzzlemc/core/config/PuzzleConfig.java
Normal file → Executable file
@@ -0,0 +1,50 @@
|
||||
package net.puzzlemc.core.mixin;
|
||||
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PuzzleMixinPlugin implements IMixinConfigPlugin {
|
||||
private String mixinPackage;
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
this.mixinPackage = mixinPackage + ".";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
final String mixinName = mixinClassName.substring(this.mixinPackage.length());
|
||||
final String packageName = mixinName.substring(0, mixinName.lastIndexOf('.'));
|
||||
|
||||
if (packageName.startsWith("sodium") && !PlatformFunctions.isModLoaded("sodium")) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
}
|
||||
}
|
||||
10
src/main/java/net/puzzlemc/gui/PuzzleApi.java → common/src/main/java/net/puzzlemc/gui/PuzzleApi.java
Normal file → Executable file
10
src/main/java/net/puzzlemc/gui/PuzzleApi.java → common/src/main/java/net/puzzlemc/gui/PuzzleApi.java
Normal file → Executable file
@@ -6,8 +6,6 @@ import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.puzzlemc.core.PuzzleCore.LOGGER;
|
||||
|
||||
public class PuzzleApi {
|
||||
public static List<PuzzleWidget> GRAPHICS_OPTIONS = new ArrayList<>();
|
||||
public static List<PuzzleWidget> MISC_OPTIONS = new ArrayList<>();
|
||||
@@ -17,21 +15,21 @@ public class PuzzleApi {
|
||||
public static void addToGraphicsOptions(PuzzleWidget button) {
|
||||
GRAPHICS_OPTIONS.add(button);
|
||||
if (PuzzleConfig.debugMessages)
|
||||
LOGGER.info("{} -> Graphics Options", button.descriptionText.getContents().toString());
|
||||
PuzzleGui.logger().info("{} -> Graphics Options", button.descriptionText.getContent().toString());
|
||||
}
|
||||
public static void addToMiscOptions(PuzzleWidget button) {
|
||||
MISC_OPTIONS.add(button);
|
||||
if (PuzzleConfig.debugMessages)
|
||||
LOGGER.info("{} -> Misc Options", button.descriptionText.getContents().toString());
|
||||
PuzzleGui.logger().info("{} -> Misc Options", button.descriptionText.getContent().toString());
|
||||
}
|
||||
public static void addToPerformanceOptions(PuzzleWidget button) {
|
||||
PERFORMANCE_OPTIONS.add(button);
|
||||
if (PuzzleConfig.debugMessages)
|
||||
LOGGER.info("{}- > Performance Options", button.descriptionText.getContents().toString());
|
||||
PuzzleGui.logger().info("{}- > Performance Options", button.descriptionText.getContent().toString());
|
||||
}
|
||||
public static void addToResourceOptions(PuzzleWidget button) {
|
||||
RESOURCE_OPTIONS.add(button);
|
||||
if (PuzzleConfig.debugMessages)
|
||||
LOGGER.info("{} -> Resource Options", button.descriptionText.getContents().toString());
|
||||
PuzzleGui.logger().info("{} -> Resource Options", button.descriptionText.getContent().toString());
|
||||
}
|
||||
}
|
||||
77
common/src/main/java/net/puzzlemc/gui/PuzzleGui.java
Executable file
77
common/src/main/java/net/puzzlemc/gui/PuzzleGui.java
Executable file
@@ -0,0 +1,77 @@
|
||||
package net.puzzlemc.gui;
|
||||
|
||||
import eu.midnightdust.core.MidnightLib;
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.puzzlemc.core.PuzzleModule;
|
||||
import net.puzzlemc.core.config.PuzzleConfig;
|
||||
import net.puzzlemc.gui.compat.*;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.puzzlemc.splashscreen.PuzzleSplashScreen;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class PuzzleGui implements PuzzleModule {
|
||||
public static final PuzzleGui INSTANCE = new PuzzleGui();
|
||||
public final static String id = "puzzle";
|
||||
public static final Text YES = Text.translatable("gui.yes").formatted(Formatting.GREEN);
|
||||
public static final Text NO = Text.translatable("gui.no").formatted(Formatting.RED);
|
||||
public static final Identifier PUZZLE_BUTTON = Identifier.of(id, "icon/button");
|
||||
|
||||
@Override
|
||||
public String getModuleId() {
|
||||
return "gui";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
MidnightLib.hiddenMods.add("puzzle");
|
||||
PuzzleApi.addToMiscOptions(new PuzzleWidget(Text.of("\uD83E\uDDE9 Puzzle")));
|
||||
PuzzleApi.addToMiscOptions(new PuzzleWidget(Text.translatable("puzzle.midnightconfig.title"), (button) -> button.setMessage(Text.of("OPEN")), (button) -> {
|
||||
MinecraftClient.getInstance().setScreen(PuzzleConfig.getScreen(MinecraftClient.getInstance().currentScreen, "puzzle"));
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("\uD83E\uDDE9 Puzzle")));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("puzzle.option.resourcepack_splash_screen"), (button) -> button.setMessage(PuzzleConfig.resourcepackSplashScreen ? YES : NO), (button) -> {
|
||||
PuzzleConfig.resourcepackSplashScreen = !PuzzleConfig.resourcepackSplashScreen;
|
||||
PuzzleSplashScreen.resetColors();
|
||||
PuzzleConfig.write(id);
|
||||
MinecraftClient.getInstance().getTextureManager().registerTexture(PuzzleSplashScreen.LOGO, new PuzzleSplashScreen.LogoTexture(PuzzleSplashScreen.LOGO));
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("puzzle.option.unlimited_model_rotations"), (button) -> button.setMessage(PuzzleConfig.unlimitedRotations ? YES : NO), (button) -> {
|
||||
PuzzleConfig.unlimitedRotations = !PuzzleConfig.unlimitedRotations;
|
||||
PuzzleConfig.write(id);
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("puzzle.option.bigger_custom_models"), (button) -> button.setMessage(PuzzleConfig.biggerModels ? YES : NO), (button) -> {
|
||||
PuzzleConfig.biggerModels = !PuzzleConfig.biggerModels;
|
||||
PuzzleConfig.write(id);
|
||||
}));
|
||||
if (isActive("cullleaves")) CullLeavesCompat.init();
|
||||
if (isActive("colormatic")) ColormaticCompat.init();
|
||||
if (isActive("borderlessmining")) BorderlessMiningCompat.init();
|
||||
if (isActive("iris")) IrisCompat.init();
|
||||
}
|
||||
|
||||
public static boolean lateInitDone = false;
|
||||
public static void lateInit() { // Some mods are initialized after Puzzle, so we can't access them in our ClientModInitializer
|
||||
if (isActive("lambdynlights")) LDLCompat.init();
|
||||
if (isActive("citresewn")) CITRCompat.init();
|
||||
if (isActive("lambdabettergrass")) LBGCompat.init();
|
||||
if (isActive("continuity")) ContinuityCompat.init();
|
||||
try {
|
||||
if (isActive("entity_texture_features")) ETFCompat.init();
|
||||
if (isActive("entity_model_features")) EMFCompat.init();
|
||||
} catch (Exception e) {
|
||||
INSTANCE.getLogger().error("ETF/EMF config structure changed. Again...", e);
|
||||
}
|
||||
|
||||
lateInitDone = true;
|
||||
}
|
||||
public static boolean isActive(String modid) {
|
||||
return PlatformFunctions.isModLoaded(modid) && !PuzzleConfig.disabledIntegrations.contains(modid);
|
||||
}
|
||||
public static Logger logger() {
|
||||
return INSTANCE.getLogger();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package net.puzzlemc.gui.compat;
|
||||
|
||||
import com.mojang.text2speech.OperatingSystem;
|
||||
import link.infra.borderlessmining.config.ConfigHandler;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
|
||||
@@ -11,14 +11,14 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
|
||||
|
||||
public class BorderlessMiningCompat {
|
||||
public static void init() {
|
||||
PuzzleApi.addToMiscOptions(new PuzzleWidget(Component.literal("\uD83E\uDE9F Borderless Mining")));
|
||||
PuzzleApi.addToMiscOptions(new PuzzleWidget(Text.of("\uD83E\uDE9F Borderless Mining")));
|
||||
ConfigHandler bmConfig = ConfigHandler.getInstance();
|
||||
PuzzleApi.addToMiscOptions(new PuzzleWidget(Component.translatable("config.borderlessmining.general.enabled"), (button) -> button.setMessage(bmConfig.isEnabledOrPending() ? YES : NO), (button) -> {
|
||||
PuzzleApi.addToMiscOptions(new PuzzleWidget(Text.translatable("config.borderlessmining.general.enabled"), (button) -> button.setMessage(bmConfig.isEnabledOrPending() ? YES : NO), (button) -> {
|
||||
bmConfig.setEnabledPending(!bmConfig.isEnabledOrPending());
|
||||
bmConfig.save();
|
||||
}));
|
||||
if (OperatingSystem.get() == OperatingSystem.MAC_OS) {
|
||||
PuzzleApi.addToMiscOptions(new PuzzleWidget(Component.translatable("config.borderlessmining.general.enabledmac"), (button) -> button.setMessage(bmConfig.enableMacOS ? YES : NO), (button) -> {
|
||||
if (MinecraftClient.IS_SYSTEM_MAC) {
|
||||
PuzzleApi.addToMiscOptions(new PuzzleWidget(Text.translatable("config.borderlessmining.general.enabledmac"), (button) -> button.setMessage(bmConfig.enableMacOS ? YES : NO), (button) -> {
|
||||
bmConfig.enableMacOS = !bmConfig.enableMacOS;
|
||||
bmConfig.setEnabledPending(bmConfig.isEnabled());
|
||||
bmConfig.save();
|
||||
60
common/src/main/java/net/puzzlemc/gui/compat/CITRCompat.java
Normal file
60
common/src/main/java/net/puzzlemc/gui/compat/CITRCompat.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package net.puzzlemc.gui.compat;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig;
|
||||
|
||||
import static net.minecraft.screen.ScreenTexts.NO;
|
||||
import static net.minecraft.screen.ScreenTexts.YES;
|
||||
|
||||
public class CITRCompat {
|
||||
public static void init() {
|
||||
if (CITResewnConfig.INSTANCE != null) {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("⛏ CIT Resewn")));
|
||||
CITResewnConfig citConfig = CITResewnConfig.INSTANCE;
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.citresewn.enabled.title"), (button) -> button.setMessage(citConfig.enabled ? YES : NO), (button) -> {
|
||||
citConfig.enabled = !citConfig.enabled;
|
||||
citConfig.write();
|
||||
MinecraftClient.getInstance().reloadResources();
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.citresewn.mute_errors.title"), (button) -> button.setMessage(citConfig.mute_errors ? YES : NO), (button) -> {
|
||||
citConfig.mute_errors = !citConfig.mute_errors;
|
||||
citConfig.write();
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.citresewn.mute_warns.title"), (button) -> button.setMessage(citConfig.mute_warns ? YES : NO), (button) -> {
|
||||
citConfig.mute_warns = !citConfig.mute_warns;
|
||||
citConfig.write();
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.citresewn.broken_paths.title"), (button) -> button.setMessage(citConfig.broken_paths ? YES : NO), (button) -> {
|
||||
citConfig.broken_paths = !citConfig.broken_paths;
|
||||
citConfig.write();
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(0, 100, Text.translatable("config.citresewn.cache_ms.title"), () -> citConfig.cache_ms,
|
||||
(button) -> button.setMessage(message(citConfig)),
|
||||
(slider) -> {
|
||||
try {
|
||||
citConfig.cache_ms = slider.getInt();
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
citConfig.write();
|
||||
}));
|
||||
}
|
||||
}
|
||||
public static Text message(CITResewnConfig config) {
|
||||
int ticks = config.cache_ms;
|
||||
if (ticks <= 1) {
|
||||
return (Text.translatable("config.citresewn.cache_ms.ticks." + ticks)).formatted(Formatting.AQUA);
|
||||
} else {
|
||||
Formatting color = Formatting.DARK_RED;
|
||||
if (ticks <= 40) color = Formatting.RED;
|
||||
if (ticks <= 20) color = Formatting.GOLD;
|
||||
if (ticks <= 10) color = Formatting.DARK_GREEN;
|
||||
if (ticks <= 5) color = Formatting.GREEN;
|
||||
|
||||
return (Text.translatable("config.citresewn.cache_ms.ticks.any", ticks)).formatted(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package net.puzzlemc.gui.compat;
|
||||
import io.github.kvverti.colormatic.Colormatic;
|
||||
import io.github.kvverti.colormatic.ColormaticConfig;
|
||||
import io.github.kvverti.colormatic.ColormaticConfigController;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
|
||||
@@ -12,30 +12,29 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
|
||||
|
||||
public class ColormaticCompat {
|
||||
public static void init() {
|
||||
//? if fabric {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Component.literal("\uD83C\uDF08 Colormatic")));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("\uD83C\uDF08 Colormatic")));
|
||||
ColormaticConfig colormaticConfig = Colormatic.config();
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Component.translatable("colormatic.config.option.clearSky"), (button) -> button.setMessage(colormaticConfig.clearSky ? YES : NO), (button) -> {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("colormatic.config.option.clearSky"), (button) -> button.setMessage(colormaticConfig.clearSky ? YES : NO), (button) -> {
|
||||
colormaticConfig.clearSky = !colormaticConfig.clearSky;
|
||||
ColormaticConfigController.persist(colormaticConfig);
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Component.translatable("colormatic.config.option.clearVoid"), (button) -> button.setMessage(colormaticConfig.clearVoid ? YES : NO), (button) -> {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("colormatic.config.option.clearVoid"), (button) -> button.setMessage(colormaticConfig.clearVoid ? YES : NO), (button) -> {
|
||||
colormaticConfig.clearVoid = !colormaticConfig.clearVoid;
|
||||
ColormaticConfigController.persist(colormaticConfig);
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Component.translatable("colormatic.config.option.blendSkyLight"), (button) -> button.setMessage(colormaticConfig.blendSkyLight ? YES : NO), (button) -> {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("colormatic.config.option.blendSkyLight"), (button) -> button.setMessage(colormaticConfig.blendSkyLight ? YES : NO), (button) -> {
|
||||
colormaticConfig.blendSkyLight = !colormaticConfig.blendSkyLight;
|
||||
ColormaticConfigController.persist(colormaticConfig);
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Component.translatable("colormatic.config.option.flickerBlockLight"), (button) -> button.setMessage(colormaticConfig.flickerBlockLight ? YES : NO), (button) -> {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("colormatic.config.option.flickerBlockLight"), (button) -> button.setMessage(colormaticConfig.flickerBlockLight ? YES : NO), (button) -> {
|
||||
colormaticConfig.flickerBlockLight = !colormaticConfig.flickerBlockLight;
|
||||
ColormaticConfigController.persist(colormaticConfig);
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(0, 100, Component.translatable("colormatic.config.option.relativeBlockLightIntensity"),
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(0, 100, Text.translatable("colormatic.config.option.relativeBlockLightIntensity"),
|
||||
() -> (int) (100*(1.0 - colormaticConfig.relativeBlockLightIntensityExponent / -16.0)),
|
||||
(button) -> button.setMessage(Component.translatable("colormatic.config.option.relativeBlockLightIntensity")
|
||||
(button) -> button.setMessage(Text.translatable("colormatic.config.option.relativeBlockLightIntensity")
|
||||
.append(": ")
|
||||
.append(Component.literal(String.valueOf((int)(100 * Math.exp(ColormaticConfig.scaled(colormaticConfig.relativeBlockLightIntensityExponent))))).append("%"))),
|
||||
.append(Text.literal(String.valueOf((int)(100 * Math.exp(ColormaticConfig.scaled(colormaticConfig.relativeBlockLightIntensityExponent))))).append("%"))),
|
||||
(slider) -> {
|
||||
try {
|
||||
colormaticConfig.relativeBlockLightIntensityExponent = ((1.00 - ((slider.getInt())/100f)) * -16.0);
|
||||
@@ -43,6 +42,5 @@ public class ColormaticCompat {
|
||||
}
|
||||
catch (NumberFormatException ignored) {}
|
||||
}));
|
||||
//?}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package net.puzzlemc.gui.compat;
|
||||
|
||||
import me.pepperbell.continuity.client.config.ContinuityConfig;
|
||||
import me.pepperbell.continuity.client.config.Option;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
|
||||
@@ -11,13 +11,13 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
|
||||
|
||||
public class ContinuityCompat {
|
||||
public static void init() {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Component.literal("▒ Continuity")));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("▒ Continuity")));
|
||||
ContinuityConfig contConfig = ContinuityConfig.INSTANCE;
|
||||
contConfig.getOptionMapView().forEach((s, option) -> {
|
||||
if (s.equals("use_manual_culling")) return;
|
||||
try {
|
||||
Option.BooleanOption booleanOption = ((Option.BooleanOption)option);
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Component.translatable("options.continuity."+s), (button) -> button.setMessage(booleanOption.get() ? YES : NO), (button) -> {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("options.continuity."+s), (button) -> button.setMessage(booleanOption.get() ? YES : NO), (button) -> {
|
||||
booleanOption.set(!booleanOption.get());
|
||||
contConfig.save();
|
||||
}));
|
||||
@@ -1,8 +1,8 @@
|
||||
package net.puzzlemc.gui.compat;
|
||||
|
||||
import eu.midnightdust.cullleaves.config.CullLeavesConfig;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
|
||||
@@ -11,11 +11,11 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
|
||||
|
||||
public class CullLeavesCompat {
|
||||
public static void init() {
|
||||
PuzzleApi.addToPerformanceOptions(new PuzzleWidget(Component.literal("\uD83C\uDF43 Cull Leaves")));
|
||||
PuzzleApi.addToPerformanceOptions(new PuzzleWidget(Component.translatable("cullleaves.puzzle.option.enabled"), (button) -> button.setMessage(CullLeavesConfig.enabled ? YES : NO), (button) -> {
|
||||
PuzzleApi.addToPerformanceOptions(new PuzzleWidget(Text.of("\uD83C\uDF43 Cull Leaves")));
|
||||
PuzzleApi.addToPerformanceOptions(new PuzzleWidget(Text.translatable("cullleaves.puzzle.option.enabled"), (button) -> button.setMessage(CullLeavesConfig.enabled ? YES : NO), (button) -> {
|
||||
CullLeavesConfig.enabled = !CullLeavesConfig.enabled;
|
||||
CullLeavesConfig.write("cullleaves");
|
||||
Minecraft.getInstance().levelRenderer.needsUpdate();
|
||||
MinecraftClient.getInstance().worldRenderer.reload();
|
||||
}));
|
||||
}
|
||||
}
|
||||
32
common/src/main/java/net/puzzlemc/gui/compat/EMFCompat.java
Normal file
32
common/src/main/java/net/puzzlemc/gui/compat/EMFCompat.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package net.puzzlemc.gui.compat;
|
||||
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import net.minecraft.screen.ScreenTexts;
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
import traben.entity_model_features.EMF;
|
||||
import traben.entity_model_features.config.EMFConfig;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class EMFCompat {
|
||||
public static void init() {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.literal("\uD83D\uDC37 ").append(Text.translatable("entity_model_features.title"))));
|
||||
EMFConfig emfConfig = EMF.config().getConfig();
|
||||
if (PlatformFunctions.isModLoaded("physicsmod")) {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("entity_model_features.config.physics"), (button) -> button.setMessage(emfConfig.attemptPhysicsModPatch_2 != EMFConfig.PhysicsModCompatChoice.OFF ?
|
||||
Text.translatable("entity_model_features.config." + (emfConfig.attemptPhysicsModPatch_2 == EMFConfig.PhysicsModCompatChoice.VANILLA ? "physics.1" : "physics.2")) : ScreenTexts.OFF), (button) -> {
|
||||
final NavigableSet<EMFConfig.PhysicsModCompatChoice> set =
|
||||
new TreeSet<>(EnumSet.allOf(EMFConfig.PhysicsModCompatChoice.class));
|
||||
|
||||
emfConfig.attemptPhysicsModPatch_2 = Objects.requireNonNullElseGet(
|
||||
set.higher(emfConfig.attemptPhysicsModPatch_2), set::first);
|
||||
EMF.config().saveToFile();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
47
common/src/main/java/net/puzzlemc/gui/compat/ETFCompat.java
Normal file
47
common/src/main/java/net/puzzlemc/gui/compat/ETFCompat.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package net.puzzlemc.gui.compat;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
import traben.entity_texture_features.ETFApi;
|
||||
import traben.entity_texture_features.config.ETFConfig;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import static net.puzzlemc.gui.PuzzleGui.NO;
|
||||
import static net.puzzlemc.gui.PuzzleGui.YES;
|
||||
|
||||
public class ETFCompat {
|
||||
public static void init() {
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.literal("\uD83D\uDC2E ").append(Text.translatable("config.entity_texture_features.title"))));
|
||||
ETFConfig etfConfig = ETFApi.getETFConfigObject();
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.entity_texture_features.enable_custom_textures.title"), (button) -> button.setMessage(etfConfig.enableCustomTextures ? YES : NO), (button) -> {
|
||||
etfConfig.enableCustomTextures = !etfConfig.enableCustomTextures;
|
||||
ETFApi.saveETFConfigChangesAndResetETF();
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.entity_texture_features.enable_emissive_textures.title"), (button) -> button.setMessage(etfConfig.enableEmissiveTextures ? YES : NO), (button) -> {
|
||||
etfConfig.enableEmissiveTextures = !etfConfig.enableEmissiveTextures;
|
||||
ETFApi.saveETFConfigChangesAndResetETF();
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.entity_texture_features.emissive_mode.title"), (button) -> button.setMessage(
|
||||
Text.literal(etfConfig.emissiveRenderMode.toString())), (button) -> {
|
||||
final NavigableSet<ETFConfig.EmissiveRenderModes> set =
|
||||
new TreeSet<>(EnumSet.allOf(ETFConfig.EmissiveRenderModes.class));
|
||||
|
||||
etfConfig.emissiveRenderMode = Objects.requireNonNullElseGet(
|
||||
set.higher(etfConfig.emissiveRenderMode), set::first);
|
||||
ETFApi.saveETFConfigChangesAndResetETF();
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.entity_texture_features.blinking_mob_settings.title"), (button) -> button.setMessage(etfConfig.enableBlinking ? YES : NO), (button) -> {
|
||||
etfConfig.enableBlinking = !etfConfig.enableBlinking;
|
||||
ETFApi.saveETFConfigChangesAndResetETF();
|
||||
}));
|
||||
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.entity_texture_features.player_skin_features.title"), (button) -> button.setMessage(etfConfig.skinFeaturesEnabled ? YES : NO), (button) -> {
|
||||
etfConfig.skinFeaturesEnabled = !etfConfig.skinFeaturesEnabled;
|
||||
ETFApi.saveETFConfigChangesAndResetETF();
|
||||
}));
|
||||
}
|
||||
}
|
||||
25
common/src/main/java/net/puzzlemc/gui/compat/IrisCompat.java
Normal file
25
common/src/main/java/net/puzzlemc/gui/compat/IrisCompat.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package net.puzzlemc.gui.compat;
|
||||
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.irisshaders.iris.api.v0.IrisApiConfig;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.PuzzleGui;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
|
||||
public class IrisCompat {
|
||||
public static void init() {
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.of("\uD83D\uDC41 Iris")));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.translatable("iris.puzzle.option.enableShaders"), (button) -> button.setMessage(IrisApi.getInstance().getConfig().areShadersEnabled() ? PuzzleGui.YES : PuzzleGui.NO), (button) -> {
|
||||
IrisApiConfig irisConfig = IrisApi.getInstance().getConfig();
|
||||
irisConfig.setShadersEnabledAndApply(!irisConfig.areShadersEnabled());
|
||||
}));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.translatable("options.iris.shaderPackSelection.title"), (button) -> button.setMessage(Text.literal("➥ ").append(Text.translatable("iris.puzzle.option.open").formatted(Formatting.GOLD))), (button) -> {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
client.setScreen((Screen) IrisApi.getInstance().openMainIrisScreenObj(client.currentScreen));
|
||||
}));
|
||||
}
|
||||
}
|
||||
19
common/src/main/java/net/puzzlemc/gui/compat/LBGCompat.java
Normal file
19
common/src/main/java/net/puzzlemc/gui/compat/LBGCompat.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package net.puzzlemc.gui.compat;
|
||||
|
||||
import dev.lambdaurora.lambdabettergrass.LBGConfig;
|
||||
import dev.lambdaurora.lambdabettergrass.LambdaBetterGrass;
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
|
||||
import static net.puzzlemc.gui.PuzzleGui.NO;
|
||||
import static net.puzzlemc.gui.PuzzleGui.YES;
|
||||
|
||||
public class LBGCompat {
|
||||
public static void init() {
|
||||
LBGConfig lbgConfig = LambdaBetterGrass.get().config;
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.of("\uD83C\uDF31 LambdaBetterGrass")));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.translatable("lambdabettergrass.option.mode"), (button) -> button.setMessage(lbgConfig.getMode().getTranslatedText()), (button) -> lbgConfig.setMode(lbgConfig.getMode().next())));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.translatable("lambdabettergrass.option.better_snow"), (button) -> button.setMessage(lbgConfig.hasBetterLayer() ? YES : NO), (button) -> lbgConfig.setBetterLayer(!lbgConfig.hasBetterLayer())));
|
||||
}
|
||||
}
|
||||
23
common/src/main/java/net/puzzlemc/gui/compat/LDLCompat.java
Normal file
23
common/src/main/java/net/puzzlemc/gui/compat/LDLCompat.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package net.puzzlemc.gui.compat;
|
||||
|
||||
import dev.lambdaurora.lambdynlights.DynamicLightsConfig;
|
||||
import dev.lambdaurora.lambdynlights.LambDynLights;
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
|
||||
|
||||
import static net.puzzlemc.gui.PuzzleGui.NO;
|
||||
import static net.puzzlemc.gui.PuzzleGui.YES;
|
||||
|
||||
public class LDLCompat {
|
||||
public static void init() {
|
||||
DynamicLightsConfig ldlConfig = LambDynLights.get().config;
|
||||
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.of("\uD83D\uDCA1 LambDynamicLights")));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.translatable("lambdynlights.option.mode"), (button) -> button.setMessage(ldlConfig.getDynamicLightsMode().getTranslatedText()), (button) -> ldlConfig.setDynamicLightsMode(ldlConfig.getDynamicLightsMode().next())));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.empty().append("DynLights: ").append(Text.translatable("lambdynlights.option.light_sources.entities")), (button) -> button.setMessage(ldlConfig.getEntitiesLightSource().get() ? YES : NO), (button) -> ldlConfig.getEntitiesLightSource().set(!ldlConfig.getEntitiesLightSource().get())));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.empty().append("DynLights: ").append(Text.translatable("entity.minecraft.creeper")), (button) -> button.setMessage(ldlConfig.getCreeperLightingMode().getTranslatedText()), (button) -> ldlConfig.setCreeperLightingMode(ldlConfig.getCreeperLightingMode().next())));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.empty().append("DynLights: ").append(Text.translatable("block.minecraft.tnt")), (button) -> button.setMessage(ldlConfig.getTntLightingMode().getTranslatedText()), (button) -> ldlConfig.setTntLightingMode(ldlConfig.getTntLightingMode().next())));
|
||||
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.empty().append("DynLights: ").append(Text.translatable("lambdynlights.option.light_sources.water_sensitive_check")), (button) -> button.setMessage(ldlConfig.getWaterSensitiveCheck().get() ? YES : NO), (button) -> ldlConfig.getWaterSensitiveCheck().set(!ldlConfig.getWaterSensitiveCheck().get())));
|
||||
}
|
||||
}
|
||||
52
common/src/main/java/net/puzzlemc/gui/mixin/MixinOptionsScreen.java
Executable file
52
common/src/main/java/net/puzzlemc/gui/mixin/MixinOptionsScreen.java
Executable file
@@ -0,0 +1,52 @@
|
||||
package net.puzzlemc.gui.mixin;
|
||||
|
||||
import eu.midnightdust.core.config.MidnightLibConfig;
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
||||
import net.minecraft.client.gui.widget.ThreePartsLayoutWidget;
|
||||
import net.puzzlemc.core.config.PuzzleConfig;
|
||||
import net.puzzlemc.gui.PuzzleGui;
|
||||
import net.puzzlemc.gui.screen.PuzzleOptionsScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.option.OptionsScreen;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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 java.util.Objects;
|
||||
|
||||
@Mixin(OptionsScreen.class)
|
||||
public abstract class MixinOptionsScreen extends Screen {
|
||||
@Shadow @Final private ThreePartsLayoutWidget layout;
|
||||
@Unique TextIconButtonWidget puzzle$button = TextIconButtonWidget.builder(Text.translatable("puzzle.screen.title"), (buttonWidget) ->
|
||||
(Objects.requireNonNull(this.client)).setScreen(new PuzzleOptionsScreen(this)), true)
|
||||
.dimension(20, 20).texture(PuzzleGui.PUZZLE_BUTTON, 20, 20).build();
|
||||
|
||||
private MixinOptionsScreen(Text title) {super(title);}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "init")
|
||||
public void puzzle$onInit(CallbackInfo ci) {
|
||||
if (PuzzleConfig.enablePuzzleButton) {
|
||||
this.puzzle$setButtonPos();
|
||||
this.addDrawableChild(puzzle$button);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "refreshWidgetPositions")
|
||||
public void puzzle$onResize(CallbackInfo ci) {
|
||||
if (PuzzleConfig.enablePuzzleButton) this.puzzle$setButtonPos();
|
||||
}
|
||||
|
||||
@Unique
|
||||
public void puzzle$setButtonPos() {
|
||||
int i = 0;
|
||||
if (PlatformFunctions.isModLoaded("lod")) i = i + 358;
|
||||
if (MidnightLibConfig.config_screen_list.equals(MidnightLibConfig.ConfigButton.FALSE)) i = i - 25;
|
||||
puzzle$button.setPosition(this.width / 2 - 178 + i, layout.getY() + layout.getFooterHeight() - 4);
|
||||
}
|
||||
}
|
||||
92
common/src/main/java/net/puzzlemc/gui/screen/PuzzleOptionsScreen.java
Executable file
92
common/src/main/java/net/puzzlemc/gui/screen/PuzzleOptionsScreen.java
Executable file
@@ -0,0 +1,92 @@
|
||||
package net.puzzlemc.gui.screen;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.minecraft.client.gui.tab.GridScreenTab;
|
||||
import net.minecraft.client.gui.tab.Tab;
|
||||
import net.minecraft.client.gui.tab.TabManager;
|
||||
import net.minecraft.client.gui.widget.TabNavigationWidget;
|
||||
import net.minecraft.screen.ScreenTexts;
|
||||
import net.minecraft.text.Text;
|
||||
import net.puzzlemc.gui.PuzzleApi;
|
||||
import net.puzzlemc.gui.PuzzleGui;
|
||||
import net.puzzlemc.gui.screen.widget.*;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PuzzleOptionsScreen extends Screen {
|
||||
public PuzzleOptionListWidget list;
|
||||
public List<Text> tooltip = null;
|
||||
public TabManager tabManager = new TabManager(a -> {}, a -> {});
|
||||
public Tab prevTab;
|
||||
public TabNavigationWidget tabNavigation;
|
||||
public static Text graphicsTab = Text.translatable("puzzle.page.graphics");
|
||||
public static Text miscTab = Text.translatable("puzzle.page.misc");
|
||||
public static Text performanceTab = Text.translatable("puzzle.page.performance");
|
||||
public static Text resourcesTab = Text.translatable("puzzle.page.resources");
|
||||
|
||||
public PuzzleOptionsScreen(Screen parent) {
|
||||
super(Text.translatable("puzzle.screen.title"));
|
||||
this.parent = parent;
|
||||
}
|
||||
private final Screen parent;
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
if (!PuzzleGui.lateInitDone) PuzzleGui.lateInit();
|
||||
|
||||
List<Tab> tabs = Lists.newArrayList();
|
||||
if (!PuzzleApi.GRAPHICS_OPTIONS.isEmpty()) tabs.add(new GridScreenTab(graphicsTab));
|
||||
if (!PuzzleApi.RESOURCE_OPTIONS.isEmpty()) tabs.add(new GridScreenTab(resourcesTab));
|
||||
if (!PuzzleApi.PERFORMANCE_OPTIONS.isEmpty()) tabs.add(new GridScreenTab(performanceTab));
|
||||
if (!PuzzleApi.MISC_OPTIONS.isEmpty()) tabs.add(new GridScreenTab(miscTab));
|
||||
|
||||
tabNavigation = TabNavigationWidget.builder(tabManager, this.width).tabs(tabs.toArray(new Tab[0])).build();
|
||||
tabNavigation.selectTab(0, false);
|
||||
tabNavigation.init();
|
||||
prevTab = tabManager.getCurrentTab();
|
||||
|
||||
this.list = new PuzzleOptionListWidget(this.client, this.width, this.height - 57, 24, 25);
|
||||
fillList();
|
||||
|
||||
if (tabs.size() > 1) {
|
||||
this.addDrawableChild(tabNavigation);
|
||||
list.renderHeaderSeparator = false;
|
||||
}
|
||||
|
||||
this.addDrawableChild(list);
|
||||
|
||||
super.init();
|
||||
this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> Objects.requireNonNull(client).setScreen(parent)).dimensions(this.width / 2 - 100, this.height - 26, 200, 20).build());
|
||||
}
|
||||
private void fillList() {
|
||||
List<PuzzleWidget> options = List.of();
|
||||
if (tabManager.getCurrentTab() == null) return;
|
||||
else {
|
||||
Text title = tabManager.getCurrentTab().getTitle();
|
||||
if (title.equals(graphicsTab)) options = PuzzleApi.GRAPHICS_OPTIONS;
|
||||
else if (title.equals(miscTab)) options = PuzzleApi.MISC_OPTIONS;
|
||||
else if (title.equals(performanceTab))
|
||||
options = PuzzleApi.PERFORMANCE_OPTIONS;
|
||||
else if (title.equals(resourcesTab)) options = PuzzleApi.RESOURCE_OPTIONS;
|
||||
}
|
||||
list.addAll(options);
|
||||
}
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (this.tabNavigation.trySwitchTabsWithKey(keyCode)) return true;
|
||||
return super.keyPressed(keyCode, scanCode, modifiers);
|
||||
}
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (prevTab != null && prevTab != tabManager.getCurrentTab()) {
|
||||
prevTab = tabManager.getCurrentTab();
|
||||
this.list.clear();
|
||||
fillList();
|
||||
list.setScrollY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
package net.puzzlemc.gui.screen.widget;
|
||||
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PuzzleButtonWidget extends Button {
|
||||
public class PuzzleButtonWidget extends ButtonWidget {
|
||||
private final PuzzleWidget.TextAction title;
|
||||
|
||||
public PuzzleButtonWidget(int x, int y, int width, int height, PuzzleWidget.TextAction title, OnPress onPress) {
|
||||
super(x, y, width, height, Component.empty(), onPress, Supplier::get);
|
||||
public PuzzleButtonWidget(int x, int y, int width, int height, PuzzleWidget.TextAction title, PressAction onPress) {
|
||||
super(x, y, width, height, Text.of(""), onPress, Supplier::get);
|
||||
this.title = title;
|
||||
}
|
||||
@Override
|
||||
public void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) {
|
||||
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
try { title.setTitle(this);
|
||||
} catch (Exception e) {e.fillInStackTrace(); this.visible = false;}
|
||||
super.renderWidget(context, mouseX, mouseY, delta);
|
||||
@@ -0,0 +1,96 @@
|
||||
package net.puzzlemc.gui.screen.widget;
|
||||
|
||||
import eu.midnightdust.lib.config.MidnightConfig;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableTextContent;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.puzzlemc.gui.PuzzleGui;
|
||||
import net.puzzlemc.gui.screen.PuzzleOptionsScreen;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class PuzzleOptionListWidget extends MidnightConfig.MidnightConfigListWidget {
|
||||
TextRenderer textRenderer;
|
||||
|
||||
public PuzzleOptionListWidget(MinecraftClient minecraftClient, int i, int j, int k, int l) {
|
||||
super(minecraftClient, i, j, k, l);
|
||||
this.centerListVertically = false;
|
||||
textRenderer = minecraftClient.textRenderer;
|
||||
}
|
||||
|
||||
public void addAll(List<PuzzleWidget> buttons) {
|
||||
int buttonX = this.width - 160;
|
||||
for (PuzzleWidget button : buttons) {
|
||||
try {
|
||||
if (button.buttonType == ButtonType.TEXT)
|
||||
this.addButton(List.of(), Text.literal("").append(button.descriptionText).formatted(Formatting.BOLD));
|
||||
else if (button.buttonType == ButtonType.BUTTON)
|
||||
this.addButton(List.of(new PuzzleButtonWidget(buttonX, 0, 150, 20, button.buttonTextAction, button.onPress)), button.descriptionText);
|
||||
else if (button.buttonType == ButtonType.SLIDER)
|
||||
this.addButton(List.of(new PuzzleSliderWidget(button.min, button.max, buttonX, 0, 150, 20, button.defaultSliderValue.getAsInt(), button.buttonTextAction, button.changeSliderValue)), button.descriptionText);
|
||||
else if (button.buttonType == ButtonType.TEXT_FIELD)
|
||||
this.addButton(List.of(new PuzzleTextFieldWidget(textRenderer, buttonX, 0, 150, 20, button.setTextValue, button.changeTextValue)), button.descriptionText);
|
||||
else
|
||||
PuzzleGui.logger().warn("Button {} is missing the buttonType variable. This shouldn't happen!", button);
|
||||
}
|
||||
catch (Exception e) {
|
||||
PuzzleGui.logger().error("Failed to add button {}. Likely caused by an update of the specific mod.", button.descriptionText);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public void addButton(List<ClickableWidget> buttons, Text text) {
|
||||
MidnightConfig.EntryInfo info = new MidnightConfig.EntryInfo(null, "puzzle");
|
||||
if (buttons.isEmpty()) info.comment = new MidnightConfig.Comment(){
|
||||
public Class<? extends Annotation> annotationType() {return null;}
|
||||
public boolean centered() {return true;}
|
||||
public String category() {return "";}
|
||||
public String name() {return "";}
|
||||
public String requiredMod() {return "";}
|
||||
};
|
||||
var entry = new MidnightConfig.ButtonEntry(buttons, text, info);
|
||||
this.addEntry(entry);
|
||||
}
|
||||
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
super.renderWidget(context, mouseX, mouseY, delta);
|
||||
MidnightConfig.ButtonEntry e = this.getHoveredEntry();
|
||||
if (client.currentScreen instanceof PuzzleOptionsScreen page && e != null && !e.buttons.isEmpty() &&
|
||||
e.text.getContent() instanceof TranslatableTextContent content) {
|
||||
ClickableWidget button = e.buttons.getFirst();
|
||||
String key = null;
|
||||
if (I18n.hasTranslation(content.getKey() + ".tooltip")) key = content.getKey() + ".tooltip";
|
||||
else if (I18n.hasTranslation(content.getKey() + ".desc")) key = content.getKey() + ".desc";
|
||||
if (key == null && content.getKey().endsWith(".title")) {
|
||||
String strippedContent = content.getKey().substring(0, content.getKey().length()-6);
|
||||
if (I18n.hasTranslation(strippedContent + ".tooltip")) key = strippedContent + ".tooltip";
|
||||
else if (I18n.hasTranslation(strippedContent + ".desc")) key = strippedContent + ".desc";
|
||||
}
|
||||
|
||||
if (key != null) {
|
||||
List<Text> list = new ArrayList<>();
|
||||
for (String str : I18n.translate(key).split("\n"))
|
||||
list.add(Text.literal(str));
|
||||
page.tooltip = list;
|
||||
if (!button.isMouseOver(mouseX, mouseY)) {
|
||||
context.drawTooltip(textRenderer, list, button.getX(), button.getY() + (button.getHeight() * 2));
|
||||
}
|
||||
else context.drawTooltip(textRenderer, list, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MidnightConfig.ButtonEntry getHoveredEntry() {
|
||||
return super.getHoveredEntry();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,21 @@
|
||||
package net.puzzlemc.gui.screen.widget;
|
||||
|
||||
import net.minecraft.client.gui.widget.SliderWidget;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import net.minecraft.client.gui.components.AbstractSliderButton;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class PuzzleSliderWidget extends AbstractSliderButton {
|
||||
public class PuzzleSliderWidget extends SliderWidget {
|
||||
private final int min;
|
||||
private final int max;
|
||||
private final PuzzleWidget.TextAction setComponentAction;
|
||||
private final PuzzleWidget.TextAction setTextAction;
|
||||
private final PuzzleWidget.ChangeSliderValueAction changeAction;
|
||||
|
||||
public PuzzleSliderWidget(int min, int max, int x, int y, int width, int height, float defaultValue, PuzzleWidget.TextAction setComponentAction, PuzzleWidget.ChangeSliderValueAction changeAction) {
|
||||
super(x,y,width,height, Component.empty(),(defaultValue-min) / (max - min));
|
||||
public PuzzleSliderWidget(int min, int max, int x, int y, int width, int height, float defaultValue, PuzzleWidget.TextAction setTextAction, PuzzleWidget.ChangeSliderValueAction changeAction) {
|
||||
super(x,y,width,height,Text.of(""),(defaultValue-min) / (max - min));
|
||||
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
|
||||
this.setComponentAction = setComponentAction;
|
||||
this.setTextAction = setTextAction;
|
||||
this.changeAction = changeAction;
|
||||
try {
|
||||
this.updateMessage();
|
||||
@@ -33,7 +32,7 @@ public class PuzzleSliderWidget extends AbstractSliderButton {
|
||||
|
||||
@Override
|
||||
protected void updateMessage() {
|
||||
this.setComponentAction.setTitle(this);
|
||||
this.setTextAction.setTitle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.puzzlemc.gui.screen.widget;
|
||||
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class PuzzleTextFieldWidget extends TextFieldWidget {
|
||||
private final PuzzleWidget.SetTextValueAction setValueAction;
|
||||
private final PuzzleWidget.ChangeTextValueAction change;
|
||||
|
||||
public PuzzleTextFieldWidget(TextRenderer textRenderer, int x, int y, int width, int height, PuzzleWidget.SetTextValueAction setValue, PuzzleWidget.ChangeTextValueAction change) {
|
||||
super(textRenderer, x, y, width, height, Text.of(""));
|
||||
this.setValueAction = setValue;
|
||||
this.change = change;
|
||||
try {
|
||||
setValueAction.setTextValue(this);
|
||||
} catch (Exception e) {e.fillInStackTrace(); this.setVisible(false);}
|
||||
}
|
||||
@Override
|
||||
public void write(String text) {
|
||||
super.write(text);
|
||||
this.change.onChange(this);
|
||||
setValueAction.setTextValue(this);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package net.puzzlemc.gui.screen.widget;
|
||||
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
@@ -11,9 +11,9 @@ public class PuzzleWidget {
|
||||
public ButtonType buttonType;
|
||||
public int min;
|
||||
public int max;
|
||||
public Component descriptionText;
|
||||
public Text descriptionText;
|
||||
public TextAction buttonTextAction;
|
||||
public Button.OnPress onPress;
|
||||
public ButtonWidget.PressAction onPress;
|
||||
public PuzzleWidget.SetTextValueAction setTextValue;
|
||||
public IntSupplier defaultSliderValue;
|
||||
public PuzzleWidget.ChangeTextValueAction changeTextValue;
|
||||
@@ -23,7 +23,7 @@ public class PuzzleWidget {
|
||||
* Puzzle Text Widget Container
|
||||
* @param descriptionText The text you want to display.
|
||||
*/
|
||||
public PuzzleWidget(Component descriptionText) {
|
||||
public PuzzleWidget(Text descriptionText) {
|
||||
this.buttonType = ButtonType.TEXT;
|
||||
this.descriptionText = descriptionText;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public class PuzzleWidget {
|
||||
* @param getTitle Function to set the text on the button.
|
||||
* @param onPress Function to call when the user presses the button.
|
||||
*/
|
||||
public PuzzleWidget(Component descriptionText, PuzzleWidget.TextAction getTitle, Button.OnPress onPress) {
|
||||
public PuzzleWidget(Text descriptionText, PuzzleWidget.TextAction getTitle, ButtonWidget.PressAction onPress) {
|
||||
this.buttonType = ButtonType.BUTTON;
|
||||
this.descriptionText = descriptionText;
|
||||
this.buttonTextAction = getTitle;
|
||||
@@ -43,7 +43,7 @@ public class PuzzleWidget {
|
||||
/**
|
||||
* Puzzle Slider Widget Container
|
||||
*/
|
||||
public PuzzleWidget(int min, int max, Component descriptionText, IntSupplier defaultSliderValue, PuzzleWidget.TextAction setTextAction, PuzzleWidget.ChangeSliderValueAction changeAction) {
|
||||
public PuzzleWidget(int min, int max, Text descriptionText, IntSupplier defaultSliderValue, PuzzleWidget.TextAction setTextAction, PuzzleWidget.ChangeSliderValueAction changeAction) {
|
||||
this.buttonType = ButtonType.SLIDER;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
@@ -55,7 +55,7 @@ public class PuzzleWidget {
|
||||
/**
|
||||
* Puzzle Text Field Widget Container (WIP - Doesn't work)
|
||||
*/
|
||||
public PuzzleWidget(int min, int max, Component descriptionText, PuzzleWidget.SetTextValueAction setValue, ChangeTextValueAction changeAction) {
|
||||
public PuzzleWidget(int min, int max, Text descriptionText, PuzzleWidget.SetTextValueAction setValue, ChangeTextValueAction changeAction) {
|
||||
this.buttonType = ButtonType.TEXT_FIELD;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
@@ -64,15 +64,15 @@ public class PuzzleWidget {
|
||||
this.changeTextValue = changeAction;
|
||||
}
|
||||
public interface ChangeTextValueAction {
|
||||
void onChange(EditBox textField);
|
||||
void onChange(TextFieldWidget textField);
|
||||
}
|
||||
public interface ChangeSliderValueAction {
|
||||
void onChange(PuzzleSliderWidget slider);
|
||||
}
|
||||
public interface SetTextValueAction {
|
||||
void setTextValue(EditBox textField);
|
||||
void setTextValue(TextFieldWidget textField);
|
||||
}
|
||||
public interface TextAction {
|
||||
void setTitle(AbstractWidget button);
|
||||
void setTitle(ClickableWidget button);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@ package net.puzzlemc.models.mixin;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import net.minecraft.client.renderer.block.model.BlockElement;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.client.render.model.json.ModelElement;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.puzzlemc.core.config.PuzzleConfig;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -12,21 +12,21 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(BlockElement.Deserializer.class)
|
||||
@Mixin(ModelElement.Deserializer.class)
|
||||
public abstract class MixinModelElementDeserializer {
|
||||
@Shadow protected abstract Vector3f getVector3f(JsonObject jsonObject, String string);
|
||||
@Shadow protected abstract Vector3f deserializeVec3f(JsonObject object, String name);
|
||||
|
||||
@Inject(at = @At("HEAD"),method = "getAngle", cancellable = true)
|
||||
@Inject(at = @At("HEAD"),method = "deserializeRotationAngle", cancellable = true)
|
||||
private void puzzle$deserializeRotationAngle(JsonObject object, CallbackInfoReturnable<Float> cir) {
|
||||
if (PuzzleConfig.unlimitedRotations) {
|
||||
float angle = GsonHelper.getAsFloat(object, "angle");
|
||||
float angle = JsonHelper.getFloat(object, "angle");
|
||||
cir.setReturnValue(angle);
|
||||
}
|
||||
}
|
||||
@Inject(at = @At("HEAD"),method = "getTo", cancellable = true)
|
||||
@Inject(at = @At("HEAD"),method = "deserializeTo", cancellable = true)
|
||||
private void puzzle$deserializeTo(JsonObject object, CallbackInfoReturnable<Vector3f> cir) {
|
||||
if (PuzzleConfig.biggerModels) {
|
||||
Vector3f vec3f = this.getVector3f(object, "to");
|
||||
Vector3f vec3f = this.deserializeVec3f(object, "to");
|
||||
if (!(vec3f.x < -32.0F) && !(vec3f.y < -32.0F) && !(vec3f.z < -32.0F) && !(vec3f.x > 48.0F) && !(vec3f.y > 48.0F) && !(vec3f.z > 48.0F)) {
|
||||
cir.setReturnValue(vec3f);
|
||||
} else {
|
||||
@@ -34,10 +34,10 @@ public abstract class MixinModelElementDeserializer {
|
||||
}
|
||||
}
|
||||
}
|
||||
@Inject(at = @At("HEAD"),method = "getFrom", cancellable = true)
|
||||
@Inject(at = @At("HEAD"),method = "deserializeFrom", cancellable = true)
|
||||
private void puzzle$deserializeFrom(JsonObject object, CallbackInfoReturnable<Vector3f> cir) {
|
||||
if (PuzzleConfig.biggerModels) {
|
||||
Vector3f vec3f = this.getVector3f(object, "from");
|
||||
Vector3f vec3f = this.deserializeVec3f(object, "from");
|
||||
if (!(vec3f.x < -32.0F) && !(vec3f.y < -32.0F) && !(vec3f.z < -32.0F) && !(vec3f.x > 48.0F) && !(vec3f.y > 48.0F) && !(vec3f.z > 48.0F)) {
|
||||
cir.setReturnValue(vec3f);
|
||||
} else {
|
||||
@@ -0,0 +1,14 @@
|
||||
package net.puzzlemc.predicates;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.puzzlemc.predicates.mixin.StateAccessor;
|
||||
|
||||
public class BlockStateOverride extends BlockState {
|
||||
public final Identifier overrideId;
|
||||
public BlockStateOverride(BlockState baseState, Identifier overrideId) {
|
||||
super(baseState.getBlock(), ((StateAccessor<?, ?>)baseState).getPropertyMap(), (MapCodec<BlockState>) ((StateAccessor<?, ?>)baseState).getCodec());
|
||||
this.overrideId = overrideId;
|
||||
}
|
||||
}
|
||||
29
common/src/main/java/net/puzzlemc/predicates/MBPData.java
Normal file
29
common/src/main/java/net/puzzlemc/predicates/MBPData.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package net.puzzlemc.predicates;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.logic.When;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MBPData {
|
||||
public static final HashMap<Block, List<When>> PREDICATES = new HashMap<>();
|
||||
|
||||
public static Optional<BlockStateOverride> meetsPredicate(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
if (PREDICATES.containsKey(state.getBlock())) {
|
||||
for (When when : PREDICATES.get(state.getBlock())) {
|
||||
if (when.meetsCondition(world, pos, state, renderContext)) {
|
||||
long seed = pos.hashCode();
|
||||
return Optional.of(new BlockStateOverride(state, when.getModel(seed)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package net.puzzlemc.predicates;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class MBPMixinPlugin implements IMixinConfigPlugin {
|
||||
public static boolean HAS_SODIUM = false;
|
||||
public static boolean HAS_WORLDMESHER = false;
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
HAS_SODIUM = FabricLoader.getInstance().isModLoaded("sodium");
|
||||
HAS_WORLDMESHER = FabricLoader.getInstance().isModLoaded("worldmesher");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (HAS_SODIUM) {
|
||||
builder.append("sodium, ");
|
||||
}
|
||||
if (HAS_WORLDMESHER) {
|
||||
builder.append("worldmesher, ");
|
||||
}
|
||||
String str = "Starting MBP";
|
||||
if (builder.length() > 0) {
|
||||
str = str + " with " + builder.substring(0, builder.length()-2);
|
||||
}
|
||||
PuzzlePredicates.logger().debug(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
if (mixinClassName.equals("compat.sodium.ChunkBuilderMeshingTaskMixin"))
|
||||
return HAS_SODIUM;
|
||||
//if (mixinClassName.equals("BlockRenderManagerMixin"))
|
||||
// return !HAS_SODIUM;
|
||||
//if (mixinClassName.equals("WorldMeshMixin"))
|
||||
//return HAS_WORLDMESHER;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return List.of("compat.sodium.ChunkBuilderMeshingTaskMixin");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package net.puzzlemc.predicates;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.render.entity.state.EntityRenderState;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.puzzlemc.core.PuzzleModule;
|
||||
import net.puzzlemc.predicates.data.logic.When;
|
||||
import net.puzzlemc.predicates.util.Utils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PuzzlePredicates implements PuzzleModule {
|
||||
public static final PuzzlePredicates INSTANCE = new PuzzlePredicates();
|
||||
public static EntityRenderState currentEntityRenderState;
|
||||
|
||||
@Override
|
||||
public String getModuleId() {
|
||||
return "predicates";
|
||||
}
|
||||
|
||||
public static Logger logger() {
|
||||
return INSTANCE.getLogger();
|
||||
}
|
||||
|
||||
public static Identifier id(String path) {
|
||||
return Identifier.of("mbp", path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
// TODO
|
||||
//ModelLoadingPluginManager.registerPlugin(new MBPModelLoadingPlugin.ModelIdLoader(), new MBPModelLoadingPlugin());
|
||||
}
|
||||
@Override
|
||||
public void reloadResources(ResourceManager manager) {
|
||||
MBPData.PREDICATES.clear();
|
||||
|
||||
Map<Identifier, Resource> map = manager.findResources("mbp", id -> id.getPath().endsWith(".json"));
|
||||
for (Identifier id : map.keySet()) {
|
||||
getLogger().info("Loading MBP: " + id);
|
||||
try {
|
||||
Identifier blockTarget = Identifier.of(id.toString().substring(0,id.toString().length()-5).replace("mbp/", ""));
|
||||
JsonObject asset = JsonParser.parseReader(map.get(id).getReader()).getAsJsonObject();
|
||||
|
||||
Optional<Block> block = Utils.getBlock(blockTarget);
|
||||
|
||||
if (block.isPresent()) {
|
||||
JsonArray overrides = asset.getAsJsonArray("overrides");
|
||||
List<When> whenList = new ArrayList<>();
|
||||
for(JsonElement overrideEntry : overrides) {
|
||||
When when = When.parse(overrideEntry);
|
||||
whenList.add(when);
|
||||
}
|
||||
MBPData.PREDICATES.put(block.get(), Collections.unmodifiableList(whenList));
|
||||
getLogger().info(MBPData.PREDICATES.toString());
|
||||
} else {
|
||||
getLogger().error("Block entry not found in file %s: %s ".formatted(id, blockTarget));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
getLogger().error("Error in file: %s".formatted(id));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.puzzlemc.predicates.accessor;
|
||||
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.render.entity.state.BlockDisplayEntityRenderState;
|
||||
|
||||
public interface BlockRenderManagerAccess {
|
||||
void moreBlockPredicates$setContextEntity(BlockDisplayEntityRenderState renderState);
|
||||
|
||||
static BlockRenderManagerAccess of(BlockRenderManager manager) {
|
||||
return (BlockRenderManagerAccess) manager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.puzzlemc.predicates.accessor;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModelManager;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.puzzlemc.predicates.BlockStateOverride;
|
||||
|
||||
public interface BlockStateModelManagerAccess {
|
||||
BlockStateModel reallyGetModel(BlockStateOverride override);
|
||||
|
||||
static BlockStateModelManagerAccess of(BakedModelManager manager) {
|
||||
return (BlockStateModelManagerAccess) manager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package net.puzzlemc.predicates.common;
|
||||
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.block.BlockModels;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.puzzlemc.predicates.BlockStateOverride;
|
||||
import net.puzzlemc.predicates.MBPData;
|
||||
import net.puzzlemc.predicates.accessor.BlockStateModelManagerAccess;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BlockRendering {
|
||||
|
||||
public static BlockStateModel tryModelOverride(BlockModels models, BlockRenderView world, BlockState state, BlockPos pos, Identifier renderContext) {
|
||||
BlockRenderType blockRenderType = state.getRenderType();
|
||||
if (blockRenderType == BlockRenderType.MODEL) {
|
||||
Optional<BlockStateOverride> override = MBPData.meetsPredicate(world, pos, state, renderContext);
|
||||
if (override.isPresent()) {
|
||||
BlockStateModel model;
|
||||
BlockStateModelManagerAccess manager = ((BlockStateModelManagerAccess) models.getModelManager());
|
||||
model = manager.reallyGetModel(override.get());
|
||||
if (model == models.getModelManager().getMissingModel()) {
|
||||
var overId = override.get();
|
||||
model = models.getModelManager().getBlockModels().getModel((BlockState) model);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package net.puzzlemc.predicates.common;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static net.puzzlemc.predicates.PuzzlePredicates.id;
|
||||
|
||||
public final class ContextIdentifiers {
|
||||
public static final Identifier PISTON_PUSHING = id("pushed_by_piston");
|
||||
public static final Identifier FALLING_BLOCK = id("falling_block");
|
||||
public static final Identifier MARKER_PARTICLE = id("marker_particle");
|
||||
public static final Identifier ITEM = id("item");
|
||||
public static final Identifier ITEM_HELD = id("item_held");
|
||||
public static final Identifier MISC = id("misc");
|
||||
public static final Identifier CHUNK_MESH = id("chunk_mesh");
|
||||
public static final Identifier ENTITY = id("entity");
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package net.puzzlemc.predicates.data;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
import net.puzzlemc.predicates.data.conditions.*;
|
||||
import net.puzzlemc.predicates.data.logic.Not;
|
||||
import net.puzzlemc.predicates.data.logic.Or;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public abstract class BlockModelPredicate implements WorldViewCondition {
|
||||
private static final HashMap<String, Function<JsonElement, BlockModelPredicate>> HANDLERS = new HashMap<>() {{
|
||||
// Logical operators
|
||||
put("or", Or::parse);
|
||||
put("not", Not::parse);
|
||||
|
||||
// Actual conditions
|
||||
put("adjacent_block", AdjacentBlock::parse);
|
||||
put("coordinate_range", CoordinateRange::parse);
|
||||
put("biome", InBiome::parse);
|
||||
put("state", IsBlockState::parse);
|
||||
put("light_range", LightRange::parse);
|
||||
put("is_context", IsContext::parse);
|
||||
}};
|
||||
|
||||
public static ArrayList<BlockModelPredicate> parseFromJson(JsonElement element) {
|
||||
ArrayList<JsonObject> objects = new ArrayList<>();
|
||||
if (element.isJsonArray()) {
|
||||
JsonArray arr = element.getAsJsonArray();
|
||||
for (JsonElement obj : arr) {
|
||||
objects.add(obj.getAsJsonObject());
|
||||
}
|
||||
} else {
|
||||
objects.add(element.getAsJsonObject());
|
||||
}
|
||||
|
||||
ArrayList<BlockModelPredicate> predicates = new ArrayList<>();
|
||||
for(JsonObject curObject : objects) {
|
||||
for (Map.Entry<String, JsonElement> entries : curObject.entrySet()) {
|
||||
if (HANDLERS.containsKey(entries.getKey())) {
|
||||
try {
|
||||
predicates.add(HANDLERS.get(entries.getKey()).apply(entries.getValue()));
|
||||
} catch (JsonParseException e) {
|
||||
PuzzlePredicates.logger().warn(String.format("Failed to load predicate \"%s\"! Reason: %s", entries.getKey(), e.getMessage()));
|
||||
}
|
||||
} else {
|
||||
PuzzlePredicates.logger().warn(String.format("Unhandled predicate \"%s\"!", entries.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return predicates;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.puzzlemc.predicates.data;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import net.minecraft.predicate.NumberRange;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public final class DataHelper {
|
||||
|
||||
public static NumberRange.IntRange parseIntRange(JsonElement arg) {
|
||||
JsonObject object = arg.getAsJsonObject();
|
||||
|
||||
boolean hasMin = object.has("min"), hasMax = object.has("max");
|
||||
if (hasMin && hasMax) {
|
||||
return NumberRange.IntRange.between(object.get("min").getAsInt(), object.get("max").getAsInt());
|
||||
} else if (hasMin) {
|
||||
return NumberRange.IntRange.atLeast(object.get("min").getAsInt());
|
||||
} else if (hasMax) {
|
||||
return NumberRange.IntRange.atMost(object.get("max").getAsInt());
|
||||
} else {
|
||||
// none?!?!??!?!?!?!?!?!
|
||||
throw new JsonParseException("No min or max defined for range!");
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockPos parseBlockPos(JsonObject offset) {
|
||||
int x = offset.get("x").getAsInt();
|
||||
int y = offset.get("y").getAsInt();
|
||||
int z = offset.get("z").getAsInt();
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.puzzlemc.predicates.data;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
public interface WorldViewCondition {
|
||||
boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package net.puzzlemc.predicates.data.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
import net.puzzlemc.predicates.data.DataHelper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AdjacentBlock extends BlockModelPredicate {
|
||||
|
||||
private final @Nullable IsBlockState stateCondition;
|
||||
private final BlockPos offset;
|
||||
private final boolean checkFullCube;
|
||||
private final boolean checkTransparent;
|
||||
public AdjacentBlock(@Nullable IsBlockState stateCondition, BlockPos offset, boolean checkFullCube, boolean checkTransparent) {
|
||||
this.stateCondition = stateCondition;
|
||||
this.offset = offset;
|
||||
this.checkFullCube = checkFullCube;
|
||||
this.checkTransparent = checkTransparent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
BlockState block = world.getBlockState(pos);
|
||||
boolean b = true;
|
||||
if (checkFullCube) b = block.isFullCube(world, pos);
|
||||
if (checkTransparent) b &= block.isTransparent();
|
||||
if (stateCondition != null) b &= stateCondition.meetsCondition(world, pos.add(offset), state, renderContext);
|
||||
return b;
|
||||
}
|
||||
|
||||
public static AdjacentBlock parse(JsonElement arg) {
|
||||
JsonObject obj = arg.getAsJsonObject();
|
||||
IsBlockState stateCondition = null;
|
||||
if (obj.has("state")) {
|
||||
stateCondition = IsBlockState.parse(obj.get("state"));
|
||||
}
|
||||
|
||||
boolean checkFullCube = false;
|
||||
boolean checkTransparent = false;
|
||||
if (obj.has("is_full_cube")) checkFullCube = obj.get("is_full_cube").getAsBoolean();
|
||||
if (obj.has("is_transparent")) checkTransparent = obj.get("is_transparent").getAsBoolean();
|
||||
|
||||
return new AdjacentBlock(stateCondition, DataHelper.parseBlockPos(obj.getAsJsonObject("offset")), checkFullCube, checkTransparent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package net.puzzlemc.predicates.data.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.predicate.NumberRange;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
import net.puzzlemc.predicates.data.DataHelper;
|
||||
|
||||
public class CoordinateRange extends BlockModelPredicate {
|
||||
|
||||
public final NumberRange.IntRange range;
|
||||
public final Direction.Axis axis;
|
||||
|
||||
public CoordinateRange(NumberRange.IntRange range, Direction.Axis axis) {
|
||||
this.range = range;
|
||||
this.axis = axis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
return range.test(pos.getComponentAlongAxis(this.axis));
|
||||
}
|
||||
|
||||
public static CoordinateRange parse(JsonElement arg) {
|
||||
JsonObject object = arg.getAsJsonObject();
|
||||
|
||||
Direction.Axis axis = Direction.Axis.fromId(object.get("axis").getAsString());
|
||||
return new CoordinateRange(DataHelper.parseIntRange(arg), axis);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package net.puzzlemc.predicates.data.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
|
||||
public class InBiome extends BlockModelPredicate {
|
||||
|
||||
final Identifier biomeID;
|
||||
|
||||
public InBiome(Identifier biomeID) {
|
||||
this.biomeID = biomeID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
World w = MinecraftClient.getInstance().world;;
|
||||
assert w != null;
|
||||
return w.getBiome(pos).matchesId(biomeID);
|
||||
}
|
||||
|
||||
public static InBiome parse(JsonElement arg) {
|
||||
return new InBiome(Identifier.of(arg.getAsString()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package net.puzzlemc.predicates.data.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.pattern.CachedBlockPosition;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.command.argument.BlockArgumentParser;
|
||||
import net.minecraft.command.argument.BlockPredicateArgumentType;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class IsBlockState extends BlockModelPredicate {
|
||||
|
||||
final @Nullable BlockPredicateImpl blockStatePredicate;
|
||||
public IsBlockState(@Nullable BlockPredicateImpl blockStatePredicate) {
|
||||
this.blockStatePredicate = blockStatePredicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
if (blockStatePredicate == null) return true;
|
||||
return blockStatePredicate.test(new CachedBlockPosition(MinecraftClient.getInstance().world, pos, false));
|
||||
}
|
||||
|
||||
public static IsBlockState parse(JsonElement arg) {
|
||||
try {
|
||||
String str = arg.getAsString();
|
||||
|
||||
if (str != null) {
|
||||
return new IsBlockState(new BlockPredicateImpl(str));
|
||||
}
|
||||
|
||||
return null; // explode
|
||||
} catch (CommandSyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class BlockPredicateImpl implements BlockPredicateArgumentType.BlockPredicate {
|
||||
final BlockArgumentParser.BlockResult res;
|
||||
public final String stateString;
|
||||
public final boolean fuzzy;
|
||||
|
||||
public BlockPredicateImpl(String stateString) throws CommandSyntaxException {
|
||||
this.stateString = stateString;
|
||||
fuzzy = !stateString.contains("[");
|
||||
res = BlockArgumentParser.block(Registries.BLOCK, stateString, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNbt() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(CachedBlockPosition cachedBlockPosition) {
|
||||
if (fuzzy) return cachedBlockPosition.getBlockState().getBlock() == res.blockState().getBlock();
|
||||
return cachedBlockPosition.getBlockState().equals(res.blockState());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package net.puzzlemc.predicates.data.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
|
||||
public class IsContext extends BlockModelPredicate {
|
||||
|
||||
final Identifier expectedContext;
|
||||
|
||||
public IsContext(Identifier expectedContext) {
|
||||
this.expectedContext = expectedContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
return expectedContext.equals(renderContext);
|
||||
}
|
||||
|
||||
public static IsContext parse(JsonElement arg) {
|
||||
return new IsContext(Identifier.of(arg.getAsString()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package net.puzzlemc.predicates.data.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.predicate.NumberRange;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
import net.puzzlemc.predicates.data.DataHelper;
|
||||
|
||||
public class LightRange extends BlockModelPredicate {
|
||||
|
||||
public final NumberRange.IntRange range;
|
||||
|
||||
public LightRange(NumberRange.IntRange range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView _unused, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
World world = MinecraftClient.getInstance().world;
|
||||
|
||||
// ;-;
|
||||
return range.test(world.getLightLevel(pos))
|
||||
|| range.test(world.getLightLevel(pos.up()))
|
||||
|| range.test(world.getLightLevel(pos.down()))
|
||||
|| range.test(world.getLightLevel(pos.north()))
|
||||
|| range.test(world.getLightLevel(pos.south()))
|
||||
|| range.test(world.getLightLevel(pos.east()))
|
||||
|| range.test(world.getLightLevel(pos.west()));
|
||||
}
|
||||
|
||||
public static LightRange parse(JsonElement arg) {
|
||||
return new LightRange(DataHelper.parseIntRange(arg));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package net.puzzlemc.predicates.data.logic;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonElement;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class And extends BlockModelPredicate {
|
||||
|
||||
final List<BlockModelPredicate> predicates;
|
||||
|
||||
public And(List<BlockModelPredicate> predicates) {
|
||||
this.predicates = predicates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
for (BlockModelPredicate action : predicates) {
|
||||
if (!action.meetsCondition(world, pos, state, renderContext)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static And parse(JsonElement arg) {
|
||||
return new And(ImmutableList.copyOf(BlockModelPredicate.parseFromJson(arg)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.puzzlemc.predicates.data.logic;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
|
||||
public class Not extends BlockModelPredicate {
|
||||
|
||||
final And condition;
|
||||
|
||||
public Not(And condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
return !condition.meetsCondition(world, pos, state, renderContext);
|
||||
}
|
||||
|
||||
public static Not parse(JsonElement arg) {
|
||||
return new Not(And.parse(arg));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package net.puzzlemc.predicates.data.logic;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Or extends BlockModelPredicate {
|
||||
|
||||
final List<And> conditions;
|
||||
|
||||
public Or(List<And> conditions) {
|
||||
this.conditions = conditions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
for (And action : conditions) {
|
||||
if (action.meetsCondition(world, pos, state, renderContext)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Or parse(JsonElement arg) {
|
||||
ArrayList<And> conditionsList = new ArrayList<>();
|
||||
JsonArray entryArray = arg.getAsJsonArray();
|
||||
for (JsonElement entry : entryArray) {
|
||||
conditionsList.add(And.parse(entry));
|
||||
}
|
||||
return new Or(ImmutableList.copyOf(conditionsList));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package net.puzzlemc.predicates.data.logic;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.puzzlemc.predicates.data.BlockModelPredicate;
|
||||
import net.puzzlemc.predicates.data.WorldViewCondition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class When implements WorldViewCondition {
|
||||
|
||||
final And conditions;
|
||||
private final List<Identifier> applyModelList;
|
||||
|
||||
public When(And conditions, List<Identifier> applyModelList) {
|
||||
this.conditions = conditions;
|
||||
this.applyModelList = Collections.unmodifiableList(applyModelList);
|
||||
}
|
||||
|
||||
public Identifier getModel(long seed) {
|
||||
return applyModelList.get((int) (Math.abs(seed) % applyModelList.size()));
|
||||
}
|
||||
|
||||
public List<Identifier> getModels() {
|
||||
return applyModelList;
|
||||
}
|
||||
|
||||
public static When parse(JsonElement arg) {
|
||||
JsonObject object = arg.getAsJsonObject();
|
||||
List<BlockModelPredicate> conditions = BlockModelPredicate.parseFromJson(object.get("when"));
|
||||
|
||||
List<Identifier> applyModelList;
|
||||
JsonElement apply = object.get("apply");
|
||||
if (apply.isJsonArray()) {
|
||||
applyModelList = new ArrayList<>();
|
||||
for (JsonElement entry : apply.getAsJsonArray()) {
|
||||
String applyId;
|
||||
int weight = 1;
|
||||
if (entry.isJsonObject()) {
|
||||
JsonObject obj = entry.getAsJsonObject();
|
||||
applyId = obj.get("model").getAsString();
|
||||
if (obj.has("weight")) weight = obj.get("weight").getAsInt();
|
||||
} else {
|
||||
applyId = entry.getAsString();
|
||||
}
|
||||
|
||||
String[] id = applyId.split(":");
|
||||
Identifier currentModelID = Identifier.of(id[0], "block/" + id[1]);
|
||||
for (int i = 0; i < weight; i++) {
|
||||
applyModelList.add(currentModelID);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String[] id = apply.getAsString().split(":");
|
||||
applyModelList = List.of(Identifier.of(id[0], "block/" + id[1]));
|
||||
}
|
||||
|
||||
return new When(new And(conditions), applyModelList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsCondition(BlockView world, BlockPos pos, BlockState state, Identifier renderContext) {
|
||||
return conditions.meetsCondition(world, pos, state, renderContext);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import net.minecraft.client.render.block.BlockModels;
|
||||
import net.minecraft.client.render.model.BakedModelManager;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.puzzlemc.predicates.BlockStateOverride;
|
||||
import net.puzzlemc.predicates.accessor.BlockStateModelManagerAccess;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
@Mixin(BakedModelManager.class)
|
||||
public abstract class BakedModelManagerMixin implements BlockStateModelManagerAccess {
|
||||
|
||||
//@Shadow private Map<Identifier, BlockStateModel> models;
|
||||
|
||||
@Shadow public abstract BlockStateModel getMissingModel();
|
||||
|
||||
@Shadow public abstract BlockModels getBlockModels();
|
||||
|
||||
@Override @Unique
|
||||
public BlockStateModel reallyGetModel(BlockStateOverride override) {
|
||||
return getBlockModels().getModel(override);
|
||||
//return models.getOrDefault(model, this.getMissingModel());
|
||||
}
|
||||
|
||||
|
||||
// ITEMS (originally from ItemRendererMixin)
|
||||
|
||||
// @Inject(method = "getModel", at = @At(value = "HEAD"))
|
||||
// private void getHeldItemModelVariableStealerLol(ItemStack stack, World world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
|
||||
// this.world = world;
|
||||
// this.entity = entity;
|
||||
// }
|
||||
//
|
||||
// @Redirect(method = "getModel", at = @At(value = "INVOKE",target = "Lnet/minecraft/client/render/item/ItemModels;getModel(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/client/render/model/BakedModel;"))
|
||||
// private BakedModel getHeldItemModelMixin(ItemModels itemModels, ItemStack stack) {
|
||||
// if (world == null || entity == null) return itemModels.getModel(stack);
|
||||
//
|
||||
// BlockPos targetPos = entity.getBlockPos();
|
||||
// if (entity instanceof PlayerEntity player) {
|
||||
// HitResult hit = player.raycast(8, MinecraftClient.getInstance().getTickDelta(), false);
|
||||
// if (hit instanceof BlockHitResult blockHitResult) {
|
||||
// targetPos = blockHitResult.getBlockPos().add(blockHitResult.getSide().getVector());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Optional<Identifier> identifier = MBPData.meetsPredicate(world, targetPos, Block.getBlockFromItem(stack.getItem()).getDefaultState(), ContextIdentifiers.ITEM_HELD);
|
||||
//
|
||||
// if (identifier.isPresent()) {
|
||||
// BlockStateModelManagerAccess access = BlockStateModelManagerAccess.of(itemModels.getModelManager());
|
||||
// return access.reallyGetModel(identifier.get());
|
||||
// }
|
||||
//
|
||||
// world = null;
|
||||
// entity = null;
|
||||
// return itemModels.getModel(stack);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.render.entity.DisplayEntityRenderer;
|
||||
import net.minecraft.client.render.entity.state.BlockDisplayEntityRenderState;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.puzzlemc.predicates.accessor.BlockRenderManagerAccess;
|
||||
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;
|
||||
|
||||
@Mixin(DisplayEntityRenderer.BlockDisplayEntityRenderer.class)
|
||||
public class BlockDisplayEntityRendererMixin {
|
||||
@Shadow @Final private BlockRenderManager blockRenderManager;
|
||||
|
||||
@Inject(method = "render(Lnet/minecraft/client/render/entity/state/BlockDisplayEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IF)V", at = @At("HEAD"))
|
||||
public void getContext(BlockDisplayEntityRenderState blockDisplayEntityRenderState, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, float f, CallbackInfo ci) {
|
||||
BlockRenderManagerAccess.of(blockRenderManager).moreBlockPredicates$setContextEntity(blockDisplayEntityRenderState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.particle.BlockDustParticle;
|
||||
import net.minecraft.client.particle.SpriteBillboardParticle;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.puzzlemc.predicates.BlockStateOverride;
|
||||
import net.puzzlemc.predicates.MBPData;
|
||||
import net.puzzlemc.predicates.accessor.BlockStateModelManagerAccess;
|
||||
import net.puzzlemc.predicates.common.ContextIdentifiers;
|
||||
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;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(BlockDustParticle.class)
|
||||
public abstract class BlockDustParticleMixin extends SpriteBillboardParticle {
|
||||
|
||||
protected BlockDustParticleMixin(ClientWorld clientWorld, double d, double e, double f) {
|
||||
super(clientWorld, d, e, f);
|
||||
}
|
||||
|
||||
@Inject(at = @At(value = "TAIL"), method = "<init>(Lnet/minecraft/client/world/ClientWorld;DDDDDDLnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;)V")
|
||||
public void init(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, BlockState state, BlockPos blockPos, CallbackInfo ci) {
|
||||
Optional<BlockStateOverride> identifier = MBPData.meetsPredicate(world, blockPos, state, ContextIdentifiers.FALLING_BLOCK);
|
||||
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (identifier.isPresent()) {
|
||||
BlockStateModelManagerAccess access = BlockStateModelManagerAccess.of(client.getBakedModelManager());
|
||||
setSprite(access.reallyGetModel(identifier.get()).particleSprite());
|
||||
} else {
|
||||
this.setSprite(client.getBlockRenderManager().getModels().getModelParticleSprite(state));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.particle.BlockMarkerParticle;
|
||||
import net.minecraft.client.particle.SpriteBillboardParticle;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.puzzlemc.predicates.BlockStateOverride;
|
||||
import net.puzzlemc.predicates.MBPData;
|
||||
import net.puzzlemc.predicates.accessor.BlockStateModelManagerAccess;
|
||||
import net.puzzlemc.predicates.common.ContextIdentifiers;
|
||||
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;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(BlockMarkerParticle.class)
|
||||
public abstract class BlockMarkerParticleMixin extends SpriteBillboardParticle {
|
||||
|
||||
protected BlockMarkerParticleMixin(ClientWorld clientWorld, double d, double e, double f) {
|
||||
super(clientWorld, d, e, f);
|
||||
|
||||
}
|
||||
|
||||
@Inject(at = @At(value = "TAIL"), method = "<init>")
|
||||
public void init(ClientWorld world, double x, double y, double z, BlockState state, CallbackInfo ci) {
|
||||
Optional<BlockStateOverride> identifier = MBPData.meetsPredicate(world, BlockPos.ofFloored(x, y, z), state, ContextIdentifiers.MARKER_PARTICLE);
|
||||
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (identifier.isPresent()) {
|
||||
BlockStateModelManagerAccess access = BlockStateModelManagerAccess.of(client.getBakedModelManager());
|
||||
setSprite(access.reallyGetModel(identifier.get()).particleSprite());
|
||||
} else {
|
||||
this.setSprite(client.getBlockRenderManager().getModels().getModelParticleSprite(state));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.block.BlockModelRenderer;
|
||||
import net.minecraft.client.render.model.BlockModelPart;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(BlockModelRenderer.class)
|
||||
public class BlockModelRendererMixin {
|
||||
|
||||
@WrapMethod(method = "render(Lnet/minecraft/world/BlockRenderView;Ljava/util/List;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;ZI)V")
|
||||
public void renderBlock(BlockRenderView world, List<BlockModelPart> parts, BlockState state, BlockPos pos, MatrixStack matrices, VertexConsumer vertexConsumer, boolean cull, int overlay, Operation<Void> original) {
|
||||
BlockRenderType blockRenderType = state.getRenderType();
|
||||
System.out.println("B");
|
||||
if (blockRenderType == BlockRenderType.MODEL) {
|
||||
if (state.getBlock() == Blocks.SPRUCE_LEAVES) PuzzlePredicates.logger().info(":( Should be activated now");
|
||||
// BlockStateModel newModel = BlockRendering.tryModelOverride(BlockModels, world, state, pos, ContextIdentifiers.MISC);
|
||||
// if (newModel != null) {
|
||||
// PuzzlePredicates.logger().info(":) Replacing "+state.getBlock().toString());
|
||||
// // TODO: Don't create an instance of Random here
|
||||
// original.call(world, newModel.getParts(Random.create()), state, pos, matrices, vertexConsumer, cull, OverlayTexture.DEFAULT_UV);
|
||||
// //this.blockModelRenderer.render(world, newModel.getParts(random), state, pos, matrices, vertexConsumer, cull, OverlayTexture.DEFAULT_UV);
|
||||
// //ci.cancel();
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
original.call(world, parts, state, pos, matrices, vertexConsumer, cull, overlay);
|
||||
}
|
||||
|
||||
@WrapMethod(method = "render(Lnet/minecraft/client/util/math/MatrixStack$Entry;Lnet/minecraft/client/render/VertexConsumer;Lnet/minecraft/client/render/model/BlockStateModel;FFFII)V")
|
||||
private static void c(MatrixStack.Entry entry, VertexConsumer vertexConsumer, BlockStateModel model, float red, float green, float blue, int light, int overlay, Operation<Void> original) {
|
||||
System.out.println("c");
|
||||
original.call(entry, vertexConsumer, model, red, green, blue, light, overlay);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.render.OverlayTexture;
|
||||
import net.minecraft.client.render.RenderLayers;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.BlockModelRenderer;
|
||||
import net.minecraft.client.render.block.BlockModels;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.render.entity.state.BlockDisplayEntityRenderState;
|
||||
import net.minecraft.client.render.model.BlockModelPart;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.puzzlemc.predicates.BlockStateOverride;
|
||||
import net.puzzlemc.predicates.MBPData;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
import net.puzzlemc.predicates.accessor.BlockStateModelManagerAccess;
|
||||
import net.puzzlemc.predicates.accessor.BlockRenderManagerAccess;
|
||||
import net.puzzlemc.predicates.common.BlockRendering;
|
||||
import net.puzzlemc.predicates.common.ContextIdentifiers;
|
||||
import net.puzzlemc.predicates.util.Utils;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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 java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(value = BlockRenderManager.class, priority = 2000)
|
||||
public class BlockRenderManagerMixin implements BlockRenderManagerAccess {
|
||||
|
||||
@Shadow @Final private BlockModelRenderer blockModelRenderer;
|
||||
@Shadow @Final private BlockModels models;
|
||||
@Shadow @Final private BlockColors blockColors;
|
||||
@Shadow @Final private Random random;
|
||||
|
||||
@Unique private BlockDisplayEntityRenderState mbp$contextRenderState;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "renderBlock", cancellable = true)
|
||||
public void renderBlock(BlockState state, BlockPos pos, BlockRenderView world, MatrixStack matrices, VertexConsumer vertexConsumer, boolean cull, List<BlockModelPart> parts, CallbackInfo ci) {
|
||||
BlockRenderType blockRenderType = state.getRenderType();
|
||||
System.out.println("a");
|
||||
if (blockRenderType == BlockRenderType.MODEL) {
|
||||
if (state.getBlock() == Blocks.SPRUCE_LEAVES) PuzzlePredicates.logger().info(":( Should be activated now");
|
||||
BlockStateModel newModel = BlockRendering.tryModelOverride(this.models, world, state, pos, ContextIdentifiers.MISC);
|
||||
if (newModel != null) {
|
||||
PuzzlePredicates.logger().info(":) Replacing "+state.getBlock().toString());
|
||||
this.blockModelRenderer.render(world, newModel.getParts(random), state, pos, matrices, vertexConsumer, cull, OverlayTexture.DEFAULT_UV);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "renderBlockAsEntity", cancellable = true)
|
||||
public void renderBlockAsEntity(BlockState state, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, CallbackInfo ci) {
|
||||
if (state.getRenderType() == BlockRenderType.MODEL) {
|
||||
BlockPos pos = mbp$contextRenderState == null ? BlockPos.ORIGIN : Utils.posFromRenderState(mbp$contextRenderState);
|
||||
mbp$contextRenderState = null;
|
||||
Optional<BlockStateOverride> id = MBPData.meetsPredicate(MinecraftClient.getInstance().world, pos, state, ContextIdentifiers.ENTITY);
|
||||
if (id.isEmpty()) return;
|
||||
|
||||
BlockStateModel bakedModel = ((BlockStateModelManagerAccess) this.models.getModelManager()).reallyGetModel(id.get());
|
||||
int i = this.blockColors.getColor(state, null, null, 0);
|
||||
float f = (float) (i >> 16 & 0xFF) / 255.0F;
|
||||
float g = (float) (i >> 8 & 0xFF) / 255.0F;
|
||||
float h = (float) (i & 0xFF) / 255.0F;
|
||||
BlockModelRenderer
|
||||
.render(
|
||||
matrices.peek(),
|
||||
vertexConsumers.getBuffer(RenderLayers.getEntityBlockLayer(state)),
|
||||
bakedModel,
|
||||
f,
|
||||
g,
|
||||
h,
|
||||
light,
|
||||
overlay
|
||||
);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moreBlockPredicates$setContextEntity(BlockDisplayEntityRenderState renderState) {
|
||||
mbp$contextRenderState = renderState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.render.entity.FallingBlockEntityRenderer;
|
||||
import net.minecraft.client.render.entity.state.FallingBlockEntityRenderState;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.puzzlemc.predicates.BlockStateOverride;
|
||||
import net.puzzlemc.predicates.MBPData;
|
||||
import net.puzzlemc.predicates.accessor.BlockStateModelManagerAccess;
|
||||
import net.puzzlemc.predicates.common.ContextIdentifiers;
|
||||
import net.puzzlemc.predicates.util.Utils;
|
||||
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 java.util.Optional;
|
||||
|
||||
@Mixin(value = FallingBlockEntityRenderer.class, priority = 1100)
|
||||
public class FallingBlockEntityRendererMixin {
|
||||
|
||||
@Unique private FallingBlockEntityRenderState mbp$fallingBlockEntityRenderState;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/client/render/entity/state/FallingBlockEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V")
|
||||
public void render(FallingBlockEntityRenderState fallingBlockEntityRenderState, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo ci) {
|
||||
this.mbp$fallingBlockEntityRenderState = fallingBlockEntityRenderState;
|
||||
}
|
||||
|
||||
@WrapOperation(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BlockStateModel;"),method = "render(Lnet/minecraft/client/render/entity/state/FallingBlockEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V")
|
||||
public BlockStateModel render(BlockRenderManager instance, BlockState state, Operation<BlockStateModel> original) {
|
||||
Optional<BlockStateOverride> identifier = MBPData.meetsPredicate(mbp$fallingBlockEntityRenderState.world, Utils.posFromRenderState(mbp$fallingBlockEntityRenderState), state, ContextIdentifiers.FALLING_BLOCK);
|
||||
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (identifier.isPresent()) {
|
||||
BlockStateModelManagerAccess access = BlockStateModelManagerAccess.of(client.getBakedModelManager());
|
||||
return access.reallyGetModel(identifier.get());
|
||||
} else {
|
||||
return original.call(instance, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.ItemEntityRenderer;
|
||||
import net.minecraft.client.render.entity.state.ItemEntityRenderState;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
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(ItemEntityRenderer.class)
|
||||
public class ItemEntityRendererMixin {
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/client/render/entity/state/ItemEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V")
|
||||
private void beforeRender(ItemEntityRenderState itemEntityRenderState, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo ci) {
|
||||
PuzzlePredicates.currentEntityRenderState = itemEntityRenderState;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.ItemFrameEntityRenderer;
|
||||
import net.minecraft.client.render.entity.state.ItemFrameEntityRenderState;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.decoration.ItemFrameEntity;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
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(ItemFrameEntityRenderer.class)
|
||||
public class ItemFrameEntityRendererMixin<T extends ItemFrameEntity> {
|
||||
|
||||
@Inject(method = "render(Lnet/minecraft/client/render/entity/state/ItemFrameEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At("HEAD"))
|
||||
public void renderMixin(ItemFrameEntityRenderState itemFrameEntityRenderState, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo ci) {
|
||||
PuzzlePredicates.currentEntityRenderState = itemFrameEntityRenderState;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.puzzlemc.predicates.MBPData;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
import net.puzzlemc.predicates.accessor.BlockStateModelManagerAccess;
|
||||
import net.puzzlemc.predicates.common.ContextIdentifiers;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(ItemRenderer.class)
|
||||
public abstract class ItemRendererMixin {
|
||||
//@Shadow @Final private ItemModels models;
|
||||
@Unique private World world;
|
||||
@Unique private Entity entity;
|
||||
|
||||
|
||||
|
||||
//@Redirect(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformation$Mode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemRenderer;renderBakedItemModel(Lnet/minecraft/client/render/model/BakedModel;Lnet/minecraft/item/ItemStack;IILnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;)V"))
|
||||
// @Redirect(
|
||||
// method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V",
|
||||
// at = @At(
|
||||
// value = "INVOKE",
|
||||
// target = "Lnet/minecraft/client/render/item/ItemRenderer;renderBakedItemModel(Lnet/minecraft/client/render/model/BakedModel;Lnet/minecraft/item/ItemStack;IILnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;)V"
|
||||
// )
|
||||
// )
|
||||
// private void renderBakedModelMixin(ItemRenderer instance, BakedModel model, ItemStack stack, int light, int overlay, MatrixStack matrices, VertexConsumer vertices) {
|
||||
// if (world == null) world = MinecraftClient.getInstance().world;
|
||||
// if (entity == null) entity = MBPClient.currentEntity;
|
||||
// if (entity == null) entity = MinecraftClient.getInstance().player;
|
||||
//
|
||||
// if (entity != null) {
|
||||
// BlockPos targetPos = entity.getBlockPos();
|
||||
// if (entity instanceof PlayerEntity player) {
|
||||
// HitResult hit = player.raycast(8, MinecraftClient.getInstance().getTickDelta(), false);
|
||||
// if (hit instanceof BlockHitResult blockHitResult) {
|
||||
// targetPos = blockHitResult.getBlockPos().add(blockHitResult.getSide().getVector());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Optional<Identifier> identifier = MBPData.meetsPredicate(world, targetPos, Block.getBlockFromItem(stack.getItem()).getDefaultState(), ContextIdentifiers.ITEM);
|
||||
// if (identifier.isPresent()) {
|
||||
// BlockStateModelManagerAccess access = BlockStateModelManagerAccess.of(models.getModelManager());
|
||||
// model = access.reallyGetModel(identifier.get());
|
||||
// }
|
||||
// PuzzlePredicates.currentEntityRenderState = null;
|
||||
// }
|
||||
//
|
||||
// this.renderBakedItemModel(model, stack, light, overlay, matrices, vertices);
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.render.block.entity.PistonBlockEntityRenderer;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.puzzlemc.predicates.BlockStateOverride;
|
||||
import net.puzzlemc.predicates.MBPData;
|
||||
import net.puzzlemc.predicates.accessor.BlockStateModelManagerAccess;
|
||||
import net.puzzlemc.predicates.common.ContextIdentifiers;
|
||||
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 java.util.Optional;
|
||||
|
||||
@Mixin(value = PistonBlockEntityRenderer.class, priority = 1100)
|
||||
public class PistonBlockEntityRendererMixin {
|
||||
@Unique private BlockPos mbp$tempBlockPos;
|
||||
@Unique private World mbp$tempWorld;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "renderModel")
|
||||
public void renderModel(BlockPos pos, BlockState state, MatrixStack matrices, VertexConsumerProvider vertexConsumers, World world, boolean cull, int overlay, CallbackInfo ci) {
|
||||
this.mbp$tempBlockPos = pos;
|
||||
this.mbp$tempWorld = world;
|
||||
}
|
||||
|
||||
@WrapOperation(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BlockStateModel;"), method = "renderModel")
|
||||
public BlockStateModel renderModel(BlockRenderManager instance, BlockState state, Operation<BlockStateModel> original) {
|
||||
Optional<BlockStateOverride> identifier = MBPData.meetsPredicate(mbp$tempWorld, mbp$tempBlockPos, state, ContextIdentifiers.PISTON_PUSHING);
|
||||
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (identifier.isPresent()) {
|
||||
BlockStateModelManagerAccess access = BlockStateModelManagerAccess.of(client.getBakedModelManager());
|
||||
return access.reallyGetModel(identifier.get());
|
||||
} else {
|
||||
return original.call(instance, state);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.puzzlemc.predicates.mixin;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import net.minecraft.state.State;
|
||||
import net.minecraft.state.property.Property;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(State.class)
|
||||
public interface StateAccessor<O, S> {
|
||||
@Accessor
|
||||
Reference2ObjectArrayMap<Property<?>, Comparable<?>> getPropertyMap();
|
||||
|
||||
@Accessor
|
||||
MapCodec<S> getCodec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package net.puzzlemc.predicates.mixin.compat.sodium;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.block.BlockModels;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.puzzlemc.predicates.common.BlockRendering;
|
||||
import net.puzzlemc.predicates.common.ContextIdentifiers;
|
||||
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.Redirect;
|
||||
|
||||
|
||||
//@Mixin(value = ChunkBuilderMeshingTask.class)
|
||||
public class ChunkBuilderMeshingTaskMixin {
|
||||
|
||||
@Unique private int x = 0;
|
||||
@Unique private int y = 0;
|
||||
@Unique private int z = 0;
|
||||
|
||||
// @Redirect(method = "execute(Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lme/jellysquid/mods/sodium/client/util/task/CancellationToken;)Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/world/WorldSlice;getBlockState(III)Lnet/minecraft/block/BlockState;"))
|
||||
// public BlockState getBlockStateRedirect(WorldSlice worldSlice, int x, int y, int z) {
|
||||
// this.x = x;
|
||||
// this.y = y;
|
||||
// this.z = z;
|
||||
// return worldSlice.getBlockState(x,y,z);
|
||||
// }
|
||||
//
|
||||
// @Redirect(method = "execute(Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lme/jellysquid/mods/sodium/client/util/task/CancellationToken;)Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockModels;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;"))
|
||||
// public BlockStateModel getModelRedirect(BlockModels models, BlockState state) {
|
||||
// BakedModel newModel = BlockRendering.tryModelOverride(models, MinecraftClient.getInstance().world, state, new BlockPos(x, y, z), ContextIdentifiers.CHUNK_MESH);
|
||||
// if (newModel != null)
|
||||
// return newModel;
|
||||
//
|
||||
// // If failed return original method call
|
||||
// return models.getModel(state);
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package net.puzzlemc.predicates.resources;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
import net.puzzlemc.predicates.data.logic.When;
|
||||
import net.puzzlemc.predicates.util.Utils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
|
||||
//public class MBPModelLoadingPlugin implements PreparableModelLoadingPlugin<HashSet<Identifier>> {
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public void onInitializeModelLoader(HashSet<Identifier> data, ModelLoadingPlugin.Context pluginContext) {
|
||||
// pluginContext.addModels(data);
|
||||
// }
|
||||
//
|
||||
// public static class ModelIdLoader implements PreparableModelLoadingPlugin.DataLoader<HashSet<Identifier>> {
|
||||
// @Override
|
||||
// public CompletableFuture<HashSet<Identifier>> load(ResourceManager manager, Executor executor) {
|
||||
//
|
||||
// return CompletableFuture.supplyAsync(() -> {
|
||||
// HashSet<Identifier> wantedModels = new HashSet<>();
|
||||
//
|
||||
// Map<Identifier, Resource> map = manager.findResources("mbp", id -> id.getPath().endsWith(".json"));
|
||||
// for (Identifier id : map.keySet()) {
|
||||
//
|
||||
// try {
|
||||
// Identifier blockTarget = Identifier.of(id.toString().substring(0,id.toString().length()-5).replace("mbp/", ""));
|
||||
// JsonObject asset = JsonParser.parseReader(map.get(id).getReader()).getAsJsonObject();
|
||||
//
|
||||
// Optional<Block> block = Utils.getBlock(blockTarget);
|
||||
//
|
||||
// if (block.isPresent()) {
|
||||
// JsonArray overrides = asset.getAsJsonArray("overrides");
|
||||
// for(JsonElement overrideEntry : overrides) {
|
||||
// When when = When.parse(overrideEntry);
|
||||
//
|
||||
// wantedModels.addAll(when.getModels());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// PuzzlePredicates.logger().error("Error found in file: " + id, e);
|
||||
// }
|
||||
// }
|
||||
// return wantedModels;
|
||||
// }, executor);
|
||||
//
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
50
common/src/main/java/net/puzzlemc/predicates/util/Utils.java
Normal file
50
common/src/main/java/net/puzzlemc/predicates/util/Utils.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package net.puzzlemc.predicates.util;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.entity.state.EntityRenderState;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Utils {
|
||||
private static DynamicRegistryManager getRegistryManager() {
|
||||
MinecraftClient instance = MinecraftClient.getInstance();
|
||||
return instance != null && instance.world != null ? instance.world.getRegistryManager() : null;
|
||||
}
|
||||
|
||||
public static final Supplier<Optional<Registry<Biome>>> BIOME_REGISTRY = () -> {
|
||||
DynamicRegistryManager drm = getRegistryManager();
|
||||
if (drm != null) return drm.getOptional(RegistryKeys.BIOME);
|
||||
|
||||
return Optional.empty();
|
||||
};
|
||||
|
||||
public static Optional<Biome> getBiome(Identifier biomeId) {
|
||||
Optional<Registry<Biome>> registry = BIOME_REGISTRY.get();
|
||||
if (registry.isPresent()) {
|
||||
return registry.get().getOptionalValue(biomeId);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static Optional<Identifier> getBiome(Biome biome) {
|
||||
Optional<Registry<Biome>> registry = BIOME_REGISTRY.get();
|
||||
return registry.map(biomes -> biomes.getId(biome));
|
||||
}
|
||||
|
||||
public static Optional<Block> getBlock(Identifier blockId) {
|
||||
return Registries.BLOCK.getOptionalValue(blockId);
|
||||
}
|
||||
|
||||
public static BlockPos posFromRenderState(EntityRenderState state) {
|
||||
return BlockPos.ofFloored(state.x, state.y, state.z);
|
||||
}
|
||||
}
|
||||
227
common/src/main/java/net/puzzlemc/splashscreen/PuzzleSplashScreen.java
Executable file
227
common/src/main/java/net/puzzlemc/splashscreen/PuzzleSplashScreen.java
Executable file
@@ -0,0 +1,227 @@
|
||||
package net.puzzlemc.splashscreen;
|
||||
|
||||
import com.mojang.blaze3d.pipeline.BlendFunction;
|
||||
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||
import com.mojang.blaze3d.platform.DepthTestFunction;
|
||||
import com.mojang.blaze3d.platform.DestFactor;
|
||||
import com.mojang.blaze3d.platform.SourceFactor;
|
||||
import eu.midnightdust.lib.util.MidnightColorUtil;
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import net.minecraft.client.gui.screen.SplashOverlay;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.RenderPhase;
|
||||
import net.minecraft.client.texture.NativeImageBackedTexture;
|
||||
import net.minecraft.client.texture.TextureContents;
|
||||
import net.minecraft.resource.*;
|
||||
import net.minecraft.util.TriState;
|
||||
import net.minecraft.util.Util;
|
||||
import net.puzzlemc.core.PuzzleModule;
|
||||
import net.puzzlemc.core.config.PuzzleConfig;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.resource.metadata.TextureResourceMetadata;
|
||||
import net.minecraft.client.texture.NativeImage;
|
||||
import net.minecraft.client.texture.ResourceTexture;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.puzzlemc.splashscreen.mixin.RenderPipelinesAccessor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static net.puzzlemc.core.PuzzleCore.MOD_ID;
|
||||
|
||||
public class PuzzleSplashScreen implements PuzzleModule {
|
||||
public static final PuzzleSplashScreen INSTANCE = new PuzzleSplashScreen();
|
||||
public static final Identifier LOGO = Identifier.of("textures/gui/title/mojangstudios.png");
|
||||
public static final Identifier BACKGROUND = Identifier.of("puzzle/splash_background.png");
|
||||
public static File CONFIG_PATH = new File(String.valueOf(PlatformFunctions.getConfigDirectory().resolve(".puzzle_cache")));
|
||||
public static Path LOGO_TEXTURE = Paths.get(CONFIG_PATH + "/mojangstudios.png");
|
||||
public static Path BACKGROUND_TEXTURE = Paths.get(CONFIG_PATH + "/splash_background.png");
|
||||
private static MinecraftClient client = MinecraftClient.getInstance();
|
||||
private static boolean keepBackground = false;
|
||||
private static RenderLayer CUSTOM_LOGO_LAYER;
|
||||
|
||||
@Override
|
||||
public String getModuleId() {
|
||||
return "splashscreen";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
// When config directory is nonexistent, create it and set the folder as hidden on Windows systems //
|
||||
if (!CONFIG_PATH.exists() && CONFIG_PATH.mkdir() && Util.getOperatingSystem().equals(Util.OperatingSystem.WINDOWS)) {
|
||||
try { Files.setAttribute(CONFIG_PATH.toPath(), "dos:hidden", true);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
buildRenderLayer();
|
||||
}
|
||||
|
||||
public static RenderLayer getCustomLogoRenderLayer() {
|
||||
return CUSTOM_LOGO_LAYER;
|
||||
}
|
||||
|
||||
public void buildRenderLayer() {
|
||||
if (PuzzleConfig.resourcepackSplashScreen) {
|
||||
BlendFunction blendFunction = new BlendFunction(SourceFactor.SRC_ALPHA, DestFactor.ONE);
|
||||
if (PuzzleConfig.disableBlend) blendFunction = null;
|
||||
else if (PuzzleConfig.customBlendFunction.size() == 4) {
|
||||
try {
|
||||
blendFunction = new BlendFunction(
|
||||
SourceFactor.valueOf(PuzzleConfig.customBlendFunction.get(0)),
|
||||
DestFactor.valueOf(PuzzleConfig.customBlendFunction.get(1)),
|
||||
SourceFactor.valueOf(PuzzleConfig.customBlendFunction.get(2)),
|
||||
DestFactor.valueOf(PuzzleConfig.customBlendFunction.get(3)));
|
||||
} catch (Exception e) {
|
||||
getLogger().error("Incorrect blend function defined in color.properties: {}{}", PuzzleConfig.customBlendFunction, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
var CUSTOM_LOGO_PIPELINE_BUILDER = RenderPipeline.builder(RenderPipelinesAccessor.getPOSITION_TEX_COLOR_SNIPPET())
|
||||
.withLocation("pipeline/mojang_logo_puzzle")
|
||||
.withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
|
||||
.withDepthWrite(false);
|
||||
CUSTOM_LOGO_PIPELINE_BUILDER = blendFunction != null ? CUSTOM_LOGO_PIPELINE_BUILDER.withBlend(blendFunction) : CUSTOM_LOGO_PIPELINE_BUILDER.withoutBlend();
|
||||
|
||||
CUSTOM_LOGO_LAYER = RenderLayer.of("mojang_logo_puzzle", 786432, CUSTOM_LOGO_PIPELINE_BUILDER.build(),
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture(new RenderPhase.Texture(SplashOverlay.LOGO, TriState.DEFAULT, false))
|
||||
.build(false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void reloadResources(ResourceManager manager) {
|
||||
client = MinecraftClient.getInstance();
|
||||
if (PuzzleConfig.resourcepackSplashScreen) {
|
||||
PuzzleSplashScreen.resetColors();
|
||||
client.getTextureManager().registerTexture(LOGO, new LogoTexture(LOGO));
|
||||
client.getTextureManager().registerTexture(BACKGROUND, new LogoTexture(BACKGROUND));
|
||||
|
||||
manager.findResources("optifine", path -> path.getPath().contains("color.properties")).forEach((id, resource) -> {
|
||||
try (InputStream stream = resource.getInputStream()) {
|
||||
Properties properties = new Properties();
|
||||
properties.load(stream);
|
||||
|
||||
if (properties.get("screen.loading") != null) {
|
||||
PuzzleConfig.backgroundColor = MidnightColorUtil.hex2Rgb(properties.get("screen.loading").toString()).getRGB();
|
||||
PuzzleConfig.hasCustomSplashScreen = true;
|
||||
}
|
||||
if (properties.get("screen.loading.bar") != null) {
|
||||
PuzzleConfig.progressBarBackgroundColor = MidnightColorUtil.hex2Rgb(properties.get("screen.loading.bar").toString()).getRGB();
|
||||
PuzzleConfig.hasCustomSplashScreen = true;
|
||||
}
|
||||
if (properties.get("screen.loading.progress") != null) {
|
||||
PuzzleConfig.progressBarColor = MidnightColorUtil.hex2Rgb(properties.get("screen.loading.progress").toString()).getRGB();
|
||||
PuzzleConfig.hasCustomSplashScreen = true;
|
||||
}
|
||||
if (properties.get("screen.loading.outline") != null) {
|
||||
PuzzleConfig.progressFrameColor = MidnightColorUtil.hex2Rgb(properties.get("screen.loading.outline").toString()).getRGB();
|
||||
PuzzleConfig.hasCustomSplashScreen = true;
|
||||
}
|
||||
if (properties.get("screen.loading.blend") != null) {
|
||||
// Recommended blend: SRC_ALPHA ONE_MINUS_SRC_ALPHA ONE ZERO
|
||||
PuzzleConfig.disableBlend = properties.get("screen.loading.blend").toString().equals("off");
|
||||
PuzzleConfig.customBlendFunction = new ArrayList<>(Arrays.stream(properties.get("screen.loading.blend").toString().split(" ")).toList());
|
||||
PuzzleConfig.hasCustomSplashScreen = true;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
getLogger().error("Error occurred while loading color.properties {}", id.toString(), e);
|
||||
}
|
||||
});
|
||||
AtomicInteger logoCount = new AtomicInteger();
|
||||
manager.findResources("textures", path -> path.getPath().contains("mojangstudios.png")).forEach((id, resource) -> {
|
||||
try (InputStream stream = resource.getInputStream()) {
|
||||
Files.copy(stream, LOGO_TEXTURE, StandardCopyOption.REPLACE_EXISTING);
|
||||
client.getTextureManager().registerTexture(LOGO, new DynamicLogoTexture());
|
||||
if (logoCount.get() > 0) PuzzleConfig.hasCustomSplashScreen = true;
|
||||
logoCount.getAndIncrement();
|
||||
} catch (Exception e) {
|
||||
getLogger().error("Error occurred while loading custom minecraft logo {}", id.toString(), e);
|
||||
}
|
||||
});
|
||||
manager.findResources(MOD_ID, path -> path.getPath().contains("splash_background.png")).forEach((id, resource) -> {
|
||||
try (InputStream stream = resource.getInputStream()) {
|
||||
Files.copy(stream, BACKGROUND_TEXTURE, StandardCopyOption.REPLACE_EXISTING);
|
||||
InputStream input = new FileInputStream(String.valueOf(PuzzleSplashScreen.BACKGROUND_TEXTURE));
|
||||
client.getTextureManager().registerTexture(BACKGROUND, new NativeImageBackedTexture(() -> "splash_screen_background", NativeImage.read(input)));
|
||||
keepBackground = true;
|
||||
PuzzleConfig.hasCustomSplashScreen = true;
|
||||
} catch (Exception e) {
|
||||
getLogger().error("Error occurred while loading custom splash background {}", id.toString(), e);
|
||||
}
|
||||
});
|
||||
if (!keepBackground) {
|
||||
try {
|
||||
Files.delete(BACKGROUND_TEXTURE);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
keepBackground = false;
|
||||
PuzzleConfig.write(MOD_ID);
|
||||
buildRenderLayer();
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetColors() {
|
||||
PuzzleConfig.backgroundColor = 15675965;
|
||||
PuzzleConfig.progressBarColor = 16777215;
|
||||
PuzzleConfig.progressBarBackgroundColor = 15675965;
|
||||
PuzzleConfig.progressFrameColor = 16777215;
|
||||
PuzzleConfig.disableBlend = false;
|
||||
PuzzleConfig.customBlendFunction = new ArrayList<>();
|
||||
PuzzleConfig.hasCustomSplashScreen = false;
|
||||
}
|
||||
|
||||
public static class LogoTexture extends ResourceTexture {
|
||||
public LogoTexture(Identifier logo) { super(logo); }
|
||||
|
||||
@Override
|
||||
public TextureContents loadContents(ResourceManager resourceManager) {
|
||||
MinecraftClient minecraftClient = MinecraftClient.getInstance();
|
||||
DefaultResourcePack defaultResourcePack = minecraftClient.getDefaultResourcePack();
|
||||
try {
|
||||
InputStream inputStream = Objects.requireNonNull(defaultResourcePack.open(ResourceType.CLIENT_RESOURCES, LOGO)).get();
|
||||
TextureContents var6;
|
||||
try {
|
||||
var6 = new TextureContents(NativeImage.read(inputStream), new TextureResourceMetadata(true, true));
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
return var6;
|
||||
} catch (IOException var18) {
|
||||
return TextureContents.createMissing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class DynamicLogoTexture extends ResourceTexture {
|
||||
public DynamicLogoTexture() {
|
||||
super(LOGO);
|
||||
}
|
||||
@Override
|
||||
public TextureContents loadContents(ResourceManager resourceManager) {
|
||||
try {
|
||||
InputStream input = new FileInputStream(String.valueOf(PuzzleSplashScreen.LOGO_TEXTURE));
|
||||
return new TextureContents(NativeImage.read(input), new TextureResourceMetadata(true, true));
|
||||
} catch (IOException e) {
|
||||
INSTANCE.getLogger().error("Encountered an error during logo loading: ", e);
|
||||
try {
|
||||
return TextureContents.load(resourceManager, LOGO);
|
||||
} catch (IOException ex) {
|
||||
return TextureContents.createMissing();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
108
common/src/main/java/net/puzzlemc/splashscreen/mixin/MixinSplashScreen.java
Executable file
108
common/src/main/java/net/puzzlemc/splashscreen/mixin/MixinSplashScreen.java
Executable file
@@ -0,0 +1,108 @@
|
||||
package net.puzzlemc.splashscreen.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Overlay;
|
||||
import net.minecraft.client.gui.screen.SplashOverlay;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.texture.NativeImage;
|
||||
import net.minecraft.client.texture.NativeImageBackedTexture;
|
||||
import net.minecraft.client.texture.TextureManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.ColorHelper;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.puzzlemc.core.config.PuzzleConfig;
|
||||
import net.puzzlemc.splashscreen.PuzzleSplashScreen;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.*;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
import static net.puzzlemc.splashscreen.PuzzleSplashScreen.BACKGROUND;
|
||||
|
||||
@Mixin(value = SplashOverlay.class, priority = 2000)
|
||||
public abstract class MixinSplashScreen extends Overlay {
|
||||
@Shadow @Final public static Identifier LOGO;
|
||||
@Shadow private long reloadCompleteTime;
|
||||
@Shadow @Final private MinecraftClient client;
|
||||
@Shadow @Final private boolean reloading;
|
||||
@Shadow private long reloadStartTime;
|
||||
@Shadow
|
||||
private static int withAlpha(int color, int alpha) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("TAIL"))
|
||||
private static void puzzle$initSplashscreen(TextureManager textureManager, CallbackInfo ci) { // Load our custom textures at game start //
|
||||
if (PuzzleConfig.resourcepackSplashScreen) {
|
||||
if (PuzzleSplashScreen.LOGO_TEXTURE.toFile().exists()) {
|
||||
textureManager.registerTexture(LOGO, new PuzzleSplashScreen.DynamicLogoTexture());
|
||||
}
|
||||
if (PuzzleSplashScreen.BACKGROUND_TEXTURE.toFile().exists()) {
|
||||
try {
|
||||
InputStream input = new FileInputStream(String.valueOf(PuzzleSplashScreen.BACKGROUND_TEXTURE));
|
||||
textureManager.registerTexture(BACKGROUND, new NativeImageBackedTexture(() -> "splash_screen_background", NativeImage.read(input)));
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Ljava/util/function/IntSupplier;getAsInt()I"))
|
||||
private int puzzle$modifyBackground(IntSupplier instance) { // Set the Progress Bar Frame Color to our configured value //
|
||||
return (!PuzzleConfig.resourcepackSplashScreen || PuzzleConfig.progressBarBackgroundColor == 15675965) ? instance.getAsInt() : PuzzleConfig.backgroundColor | 255 << 24;
|
||||
}
|
||||
|
||||
@WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIFFIIIIIII)V"))
|
||||
private void puzzle$modifyRenderLayer(DrawContext instance, Function<Identifier, RenderLayer> renderLayers, Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWidth, int regionHeight, int textureWidth, int textureHeight, int color, Operation<Void> original) {
|
||||
if (PuzzleConfig.resourcepackSplashScreen)
|
||||
instance.drawTexture(id -> PuzzleSplashScreen.getCustomLogoRenderLayer(), sprite, x, y, u, v, width, height, regionWidth, regionHeight, textureWidth, textureHeight, color);
|
||||
else instance.drawTexture(renderLayers, sprite, x, y, u, v, width, height, textureWidth, textureHeight, color);
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;getScaledWindowWidth()I", ordinal = 2))
|
||||
private void puzzle$renderSplashBackground(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||
if (Files.exists(PuzzleSplashScreen.BACKGROUND_TEXTURE) && PuzzleConfig.resourcepackSplashScreen) {
|
||||
int width = client.getWindow().getScaledWidth();
|
||||
int height = client.getWindow().getScaledHeight();
|
||||
long l = Util.getMeasuringTimeMs();
|
||||
float f = this.reloadCompleteTime > -1L ? (float)(l - this.reloadCompleteTime) / 1000.0F : -1.0F;
|
||||
float g = this.reloadStartTime> -1L ? (float)(l - this.reloadStartTime) / 500.0F : -1.0F;
|
||||
float s;
|
||||
if (f >= 1.0F) s = 1.0F - MathHelper.clamp(f - 1.0F, 0.0F, 1.0F);
|
||||
else if (reloading) s = MathHelper.clamp(g, 0.0F, 1.0F);
|
||||
else s = 1.0F;
|
||||
context.getMatrices().translate(0, 0, 1f);
|
||||
context.drawTexture(RenderLayer::getGuiTextured, BACKGROUND, 0, 0, 0, 0, width, height, width, height, ColorHelper.getWhite(s));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "renderProgressBar", at = @At("HEAD"))
|
||||
private void puzzle$addProgressBarBackground(DrawContext context, int minX, int minY, int maxX, int maxY, float opacity, CallbackInfo ci) {
|
||||
context.getMatrices().translate(0, 0, 1f);
|
||||
if (!PuzzleConfig.resourcepackSplashScreen || PuzzleConfig.progressBarBackgroundColor == 15675965) return;
|
||||
long l = Util.getMeasuringTimeMs();
|
||||
float f = this.reloadCompleteTime > -1L ? (float)(l - this.reloadCompleteTime) / 1000.0F : -1.0F;
|
||||
int m = MathHelper.ceil((1.0F - MathHelper.clamp(f - 1.0F, 0.0F, 1.0F)) * 255.0F);
|
||||
context.fill(minX, minY, maxX, maxY, withAlpha(PuzzleConfig.progressBarBackgroundColor, m));
|
||||
}
|
||||
|
||||
@ModifyArg(method = "renderProgressBar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;fill(IIIII)V"), index = 4)
|
||||
private int puzzle$modifyProgressFrame(int color) { // Set the Progress Bar Frame Color to our configured value //
|
||||
return (!PuzzleConfig.resourcepackSplashScreen || PuzzleConfig.progressFrameColor == 16777215) ? color : PuzzleConfig.progressFrameColor | 255 << 24;
|
||||
}
|
||||
@ModifyArg(method = "renderProgressBar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;fill(IIIII)V", ordinal = 0), index = 4)
|
||||
private int puzzle$modifyProgressColor(int color) { // Set the Progress Bar Color to our configured value //
|
||||
return (!PuzzleConfig.resourcepackSplashScreen || PuzzleConfig.progressBarColor == 16777215) ? color : PuzzleConfig.progressBarColor | 255 << 24;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package net.puzzlemc.splashscreen.mixin;
|
||||
|
||||
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||
import net.minecraft.client.gl.RenderPipelines;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(RenderPipelines.class)
|
||||
public interface RenderPipelinesAccessor {
|
||||
@Accessor
|
||||
static RenderPipeline.Snippet getPOSITION_TEX_COLOR_SNIPPET() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
3
common/src/main/resources/architectury.puzzle.json
Normal file
3
common/src/main/resources/architectury.puzzle.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"accessWidener": "puzzle-models.accesswidener"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -5,7 +5,6 @@
|
||||
"puzzle.page.resources":"Resource",
|
||||
"puzzle.page.performance":"Performance",
|
||||
"puzzle.page.misc":"Miscellaneous",
|
||||
"puzzle.action.open_config_screen":"Open config screen",
|
||||
"puzzle.option.check_for_updates":"Check for Updates",
|
||||
"puzzle.option.check_for_updates.tooltip":"Enables Puzzle's built-in update checker",
|
||||
"puzzle.option.show_version_info":"Show Puzzle version info",
|
||||
|
Before Width: | Height: | Size: 152 B After Width: | Height: | Size: 152 B |
@@ -1,5 +1,5 @@
|
||||
accessWidener v1 named
|
||||
accessible class net/minecraft/client/renderer/block/model/BlockElement$Deserializer
|
||||
accessible class net/minecraft/client/render/model/json/ModelElement$Deserializer
|
||||
accessible method net/minecraft/client/render/RenderLayer of (Ljava/lang/String;ILcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/client/render/RenderLayer$MultiPhaseParameters;)Lnet/minecraft/client/render/RenderLayer$MultiPhase;
|
||||
accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters
|
||||
accessible class net/minecraft/client/render/RenderPhase$Texture
|
||||
24
common/src/main/resources/puzzle-predicates.mixins.json
Normal file
24
common/src/main/resources/puzzle-predicates.mixins.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "net.puzzlemc.predicates.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"client": [
|
||||
"BakedModelManagerMixin",
|
||||
"BlockDisplayEntityRendererMixin",
|
||||
"BlockDustParticleMixin",
|
||||
"BlockMarkerParticleMixin",
|
||||
"BlockModelRendererMixin",
|
||||
"BlockRenderManagerMixin",
|
||||
"FallingBlockEntityRendererMixin",
|
||||
"ItemEntityRendererMixin",
|
||||
"ItemFrameEntityRendererMixin",
|
||||
"ItemRendererMixin",
|
||||
"PistonBlockEntityRendererMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"mixins": [
|
||||
"StateAccessor"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "net.puzzlemc.predicates.mixin.compat",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"plugin": "net.puzzlemc.core.mixin.PuzzleMixinPlugin",
|
||||
"client": [
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
109
fabric/build.gradle
Normal file
109
fabric/build.gradle
Normal file
@@ -0,0 +1,109 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
id "me.shedaniel.unified-publishing"
|
||||
}
|
||||
repositories {
|
||||
maven { url "https://maven.terraformersmc.com/releases" }
|
||||
}
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
fabric()
|
||||
}
|
||||
|
||||
configurations {
|
||||
common
|
||||
shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files.
|
||||
compileClasspath.extendsFrom common
|
||||
runtimeClasspath.extendsFrom common
|
||||
developmentFabric.extendsFrom common
|
||||
archivesBaseName = rootProject.archives_base_name + "-fabric"
|
||||
version = rootProject.mod_version + "+" + rootProject.minecraft_version
|
||||
}
|
||||
|
||||
dependencies {
|
||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
|
||||
modImplementation include ("maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric")
|
||||
|
||||
modImplementation ("com.terraformersmc:modmenu:${project.modmenu_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
|
||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", rootProject.version
|
||||
|
||||
filesMatching("fabric.mod.json") {
|
||||
expand "version": rootProject.version
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
exclude "architectury.common.json"
|
||||
|
||||
configurations = [project.configurations.shadowCommon]
|
||||
archiveClassifier = "dev-shadow"
|
||||
}
|
||||
|
||||
remapJar {
|
||||
input.set shadowJar.archiveFile
|
||||
dependsOn shadowJar
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
def commonSources = project(":common").sourcesJar
|
||||
dependsOn commonSources
|
||||
from commonSources.archiveFile.map { zipTree(it) }
|
||||
}
|
||||
|
||||
components.java {
|
||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
|
||||
unifiedPublishing {
|
||||
project {
|
||||
displayName = "Puzzle $rootProject.version - Fabric $project.minecraft_version"
|
||||
releaseType = "$project.release_type"
|
||||
changelog = releaseChangelog()
|
||||
gameVersions = []
|
||||
gameLoaders = ["fabric","quilt"]
|
||||
mainPublication remapJar
|
||||
relations {
|
||||
depends {
|
||||
curseforge = "fabric-api"
|
||||
modrinth = "fabric-api"
|
||||
}
|
||||
includes {
|
||||
curseforge = "midnightlib"
|
||||
modrinth = "midnightlib"
|
||||
}
|
||||
}
|
||||
|
||||
var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN")
|
||||
if (CURSEFORGE_TOKEN != null) {
|
||||
curseforge {
|
||||
token = CURSEFORGE_TOKEN
|
||||
id = rootProject.curseforge_id
|
||||
gameVersions.addAll "Java 21", project.minecraft_version
|
||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
||||
}
|
||||
}
|
||||
|
||||
var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN")
|
||||
if (MODRINTH_TOKEN != null) {
|
||||
modrinth {
|
||||
token = MODRINTH_TOKEN
|
||||
id = rootProject.modrinth_id
|
||||
version = "$rootProject.version-$project.name"
|
||||
gameVersions.addAll project.minecraft_version
|
||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package net.puzzlemc.fabric;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin;
|
||||
import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.puzzlemc.predicates.PuzzlePredicates;
|
||||
import net.puzzlemc.predicates.data.logic.When;
|
||||
import net.puzzlemc.predicates.util.Utils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
|
||||
public class MBPModelLoadingPlugin implements PreparableModelLoadingPlugin<HashSet<Identifier>> {
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(HashSet<Identifier> data, ModelLoadingPlugin.Context pluginContext) {
|
||||
//pluginContext.addModels(data);
|
||||
}
|
||||
|
||||
public static class ModelIdLoader implements DataLoader<HashSet<Identifier>> {
|
||||
@Override
|
||||
public CompletableFuture<HashSet<Identifier>> load(ResourceManager manager, Executor executor) {
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
HashSet<Identifier> wantedModels = new HashSet<>();
|
||||
|
||||
Map<Identifier, Resource> map = manager.findResources("mbp", id -> id.getPath().endsWith(".json"));
|
||||
for (Identifier id : map.keySet()) {
|
||||
|
||||
try {
|
||||
Identifier blockTarget = Identifier.of(id.toString().substring(0,id.toString().length()-5).replace("mbp/", ""));
|
||||
JsonObject asset = JsonParser.parseReader(map.get(id).getReader()).getAsJsonObject();
|
||||
|
||||
Optional<Block> block = Utils.getBlock(blockTarget);
|
||||
|
||||
if (block.isPresent()) {
|
||||
JsonArray overrides = asset.getAsJsonArray("overrides");
|
||||
PuzzlePredicates.logger().info("* Model Loader: "+blockTarget+ " " + overrides);
|
||||
for(JsonElement overrideEntry : overrides) {
|
||||
When when = When.parse(overrideEntry);
|
||||
|
||||
wantedModels.addAll(when.getModels());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
PuzzlePredicates.logger().error("Error found in file: " + id, e);
|
||||
}
|
||||
}
|
||||
return wantedModels;
|
||||
}, executor);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
29
fabric/src/main/java/net/puzzlemc/fabric/PuzzleFabric.java
Normal file
29
fabric/src/main/java/net/puzzlemc/fabric/PuzzleFabric.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package net.puzzlemc.fabric;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
||||
import net.fabricmc.fabric.impl.client.model.loading.ModelLoadingPluginManager;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourceType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.puzzlemc.core.PuzzleCore;
|
||||
|
||||
public class PuzzleFabric implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
PuzzleCore.initModules();
|
||||
ModelLoadingPluginManager.registerPlugin(new MBPModelLoadingPlugin.ModelIdLoader(), new MBPModelLoadingPlugin());
|
||||
|
||||
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() {
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return Identifier.of("puzzle", "splash_screen");
|
||||
}
|
||||
@Override
|
||||
public void reload(ResourceManager manager) {
|
||||
PuzzleCore.PuzzleResourceManager.INSTANCE.reload(manager);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.puzzlemc.fabric.modmenu;
|
||||
|
||||
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||
import net.puzzlemc.gui.screen.PuzzleOptionsScreen;
|
||||
|
||||
public class ModMenuIntegration implements ModMenuApi {
|
||||
@Override
|
||||
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||
return PuzzleOptionsScreen::new;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "${id}",
|
||||
"id": "puzzle",
|
||||
"version": "${version}",
|
||||
|
||||
"name": "Puzzle",
|
||||
@@ -22,25 +22,23 @@
|
||||
|
||||
"entrypoints": {
|
||||
"client": [
|
||||
"net.puzzlemc.core.PuzzleClient"
|
||||
"net.puzzlemc.fabric.PuzzleFabric"
|
||||
],
|
||||
"modmenu": [
|
||||
"net.puzzlemc.core.PuzzleClient"
|
||||
"net.puzzlemc.fabric.modmenu.ModMenuIntegration"
|
||||
]
|
||||
},
|
||||
|
||||
"mixins": [
|
||||
"puzzle-gui.mixins.json",
|
||||
"puzzle-models.mixins.json",
|
||||
"puzzle-splashscreen.mixins.json"
|
||||
"puzzle-splashscreen.mixins.json",
|
||||
"puzzle-predicates.mixins.json",
|
||||
"puzzle-predicates_compat.mixins.json"
|
||||
],
|
||||
|
||||
"depends": {
|
||||
"fabric": "*",
|
||||
"minecraft": "${minecraft}"
|
||||
},
|
||||
"breaks": {
|
||||
"entity_texture_features": "<7.0.0",
|
||||
"entity_model_features": "<3.0.0"
|
||||
"minecraft": ">=1.21"
|
||||
}
|
||||
}
|
||||
89
gradle.properties
Normal file → Executable file
89
gradle.properties
Normal file → Executable file
@@ -1,56 +1,47 @@
|
||||
# Done to increase the memory available to gradle.
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
#org.gradle.parallel=true
|
||||
org.gradle.caching=false
|
||||
org.gradle.caching.debug=false
|
||||
org.gradle.parallel=false
|
||||
#org.gradle.configureondemand=true
|
||||
org.gradle.jvmargs=-Xmx2G
|
||||
|
||||
# Mod properties
|
||||
mod.version=2.2.0
|
||||
mod.group=eu.midnightdust
|
||||
mod.id=puzzle
|
||||
mod.name=Puzzle
|
||||
minecraft_version=1.21.5
|
||||
supported_versions=
|
||||
yarn_mappings=1.21.5+build.1
|
||||
enabled_platforms=fabric,neoforge
|
||||
|
||||
# Used for the mod metadata
|
||||
mod.mc_dep_fabric=[VERSIONED]
|
||||
mod.mc_dep_forgelike=[VERSIONED]
|
||||
# Used for the release title. I.e. '1.20.x'
|
||||
mod.mc_title=[VERSIONED]
|
||||
# Space separated versions for publishing. I.e. '1.20, 1.20.1'
|
||||
mod.mc_targets=[VERSIONED]
|
||||
# Mod Properties
|
||||
mod_version = 2.1.0
|
||||
maven_group = net.puzzlemc
|
||||
archives_base_name = puzzle
|
||||
release_type=release
|
||||
curseforge_id=563977
|
||||
modrinth_id=3IuO68q1
|
||||
|
||||
# Mod setup
|
||||
deps.fabric_loader=0.17.3
|
||||
deps.fabric_version=[VERSIONED]
|
||||
# Modloaders
|
||||
fabric_loader_version=0.16.10
|
||||
fabric_api_version=0.119.5+1.21.5
|
||||
|
||||
deps.forge_loader=[VERSIONED]
|
||||
deps.neoforge_loader=[VERSIONED]
|
||||
deps.neoforge_patch=[VERSIONED]
|
||||
neoforge_version=21.5.3-beta
|
||||
yarn_mappings_patch_neoforge_version = 1.21+build.4
|
||||
|
||||
# Mod dependencies
|
||||
deps.yarn_build=[VERSIONED]
|
||||
deps.modmenu_version=[VERSIONED]
|
||||
deps.midnightlib_version=1.9.0
|
||||
# Libraries
|
||||
midnightlib_version = 1.7.0+1.21.4
|
||||
modmenu_version = 13.0.0-beta.1
|
||||
|
||||
# Mod integrations
|
||||
jigsaws.cull_leaves_version = 3.0.2-fabric
|
||||
jigsaws.ldl_version = 4.8.6+1.21.10
|
||||
jigsaws.lbg_version = 2.5.0+1.21.9
|
||||
jigsaws.iris_version = 1.9.6+1.21.10-fabric
|
||||
jigsaws.continuity_version = 3.0.0-beta.5+1.21
|
||||
jigsaws.animatica_version = 0.6.1+1.21
|
||||
jigsaws.colormatic_version = 3.1.2
|
||||
jigsaws.borderless_mining_version = 1.1.8+1.20.1
|
||||
jigsaws.dynamic_fps_version = 3.6.3
|
||||
jigsaws.toml4j_version = 0.7.2
|
||||
jigsaws.cit_resewn_version = 1.1.3+1.20
|
||||
jigsaws.complete_config_version = 2.3.0
|
||||
jigsaws.spruceui_version=5.0.0+1.20
|
||||
jigsaws.emf_version=[VERSIONED]
|
||||
jigsaws.etf_version=[VERSIONED]
|
||||
jigsaws.exordium_version=1.2.1-1.20.2
|
||||
|
||||
# Publishing
|
||||
publish.modrinth=3IuO68q1
|
||||
publish.curseforge=563977
|
||||
# Mod Integrations
|
||||
cull_leaves_version = 3.0.2-fabric
|
||||
ldl_version = 4.0.0+1.21.4
|
||||
lbg_version = 1.5.2+1.20.1
|
||||
iris_version = 1.8.0-beta.3+1.21-fabric
|
||||
continuity_version = 3.0.0-beta.5+1.21
|
||||
animatica_version = 0.6.1+1.21
|
||||
colormatic_version = 3.1.2
|
||||
borderless_mining_version = 1.1.8+1.20.1
|
||||
dynamic_fps_version = 3.6.3
|
||||
toml4j_version = 0.7.2
|
||||
cit_resewn_version = 1.1.3+1.20
|
||||
complete_config_version = 2.3.0
|
||||
spruceui_version=5.0.0+1.20
|
||||
emf_version=2.4.1
|
||||
etf_version=6.2.10
|
||||
exordium_version=1.2.1-1.20.2
|
||||
# Required for LBG
|
||||
quilt_loader_version=0.19.0-beta.18
|
||||
quilt_fabric_api_version=7.0.1+0.83.0-1.20
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
115
neoforge/build.gradle
Normal file
115
neoforge/build.gradle
Normal file
@@ -0,0 +1,115 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
id "me.shedaniel.unified-publishing"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = 'NeoForged'
|
||||
url = 'https://maven.neoforged.net/releases'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
neoForge()
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = project(":common").loom.accessWidenerPath
|
||||
}
|
||||
|
||||
configurations {
|
||||
common {
|
||||
canBeResolved = true
|
||||
canBeConsumed = false
|
||||
}
|
||||
compileClasspath.extendsFrom common
|
||||
runtimeClasspath.extendsFrom common
|
||||
developmentNeoForge.extendsFrom common
|
||||
|
||||
// Files in this configuration will be bundled into your mod using the Shadow plugin.
|
||||
// Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files.
|
||||
shadowBundle {
|
||||
canBeResolved = true
|
||||
canBeConsumed = false
|
||||
}
|
||||
archivesBaseName = rootProject.archives_base_name + "-neoforge"
|
||||
version = rootProject.mod_version + "+" + rootProject.minecraft_version
|
||||
}
|
||||
|
||||
dependencies {
|
||||
neoForge "net.neoforged:neoforge:$rootProject.neoforge_version"
|
||||
modImplementation ("maven.modrinth:midnightlib:${rootProject.midnightlib_version}-neoforge")
|
||||
|
||||
common(project(path: ':common', configuration: 'namedElements')) { transitive false }
|
||||
shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge')
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property 'version', rootProject.version
|
||||
|
||||
filesMatching('META-INF/neoforge.mods.toml') {
|
||||
expand version: rootProject.version
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadowBundle]
|
||||
archiveClassifier = 'dev-shadow'
|
||||
}
|
||||
|
||||
remapJar {
|
||||
input.set shadowJar.archiveFile
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
def commonSources = project(":common").sourcesJar
|
||||
dependsOn commonSources
|
||||
from commonSources.archiveFile.map { zipTree(it) }
|
||||
}
|
||||
|
||||
components.java {
|
||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
|
||||
unifiedPublishing {
|
||||
project {
|
||||
displayName = "Puzzle $rootProject.version - NeoForge $project.minecraft_version"
|
||||
releaseType = "alpha"
|
||||
changelog = releaseChangelog()
|
||||
gameVersions = []
|
||||
gameLoaders = ["neoforge"]
|
||||
mainPublication remapJar
|
||||
relations {
|
||||
depends {
|
||||
curseforge = "midnightlib"
|
||||
modrinth = "midnightlib"
|
||||
}
|
||||
}
|
||||
|
||||
var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN")
|
||||
if (CURSEFORGE_TOKEN != null) {
|
||||
curseforge {
|
||||
token = CURSEFORGE_TOKEN
|
||||
id = rootProject.curseforge_id
|
||||
gameVersions.addAll "Java 21", project.minecraft_version
|
||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
||||
}
|
||||
}
|
||||
|
||||
var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN")
|
||||
if (MODRINTH_TOKEN != null) {
|
||||
modrinth {
|
||||
token = MODRINTH_TOKEN
|
||||
id = rootProject.modrinth_id
|
||||
version = "$rootProject.version-$project.name"
|
||||
gameVersions.addAll project.minecraft_version
|
||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user