60 Commits

Author SHA1 Message Date
Martin Prokoph
99a450e395 feat: integrate MBP – Part I
I received permission from the author of MoreBlockPredicates to integrate their mod's functionality into Puzzle. Thanks again :)

This is far from ready yet. The MBP codebase is stuck on 1.20.1 and only for Fabric, so I'm basically porting it to 1.21.5 and multiloader at the same time. (There have been LOTS of changes related to block models, too)
2025-06-17 19:23:29 +02:00
Martin Prokoph
ee274fcefd Merge pull request #94 from seriousfreezing/1.21.5
Update pt_br.json
2025-06-17 19:17:42 +02:00
SeriousFreezing
74de5ba33c Update pt_br.json 2025-06-13 18:24:53 -03:00
Martin Prokoph
7caadedcf1 fix: get logo blending working again 2025-03-29 16:53:02 +01:00
Martin Prokoph
16f5c08011 fix: NeoForge 1.21.5 compat
Why tf does NeoForge change the MinecraftClient instance...
2025-03-29 15:02:39 +01:00
Martin Prokoph
eac8b24617 Merge pull request #92 from PuzzleMC/temp
port: recent 1.21.4 progress to 1.21.5
2025-03-29 14:42:36 +01:00
Martin Prokoph
c930b778b6 Merge branch '1.21.5' into temp 2025-03-29 14:42:13 +01:00
Martin Prokoph
cd33715e70 Merge pull request #87 from notlin4/patch-2
Update traditional Chinese translation
2025-03-29 14:39:33 +01:00
Martin Prokoph
2db5e05342 feat: add icons for mod titles 2025-03-29 14:38:32 +01:00
Martin Prokoph
a39a17b878 fix: compat with MidnightLib 1.7.0 2025-03-29 13:12:31 +01:00
Martin Prokoph
b73c28d48d port: Spring to Life (1.21.5) 2025-03-26 19:48:18 +01:00
Martin Prokoph
fbac443231 fix: crash related to EMF compat 2025-03-26 19:45:34 +01:00
notlin4
edbf42b1bc Update traditional Chinese translation 2024-12-14 15:24:17 +08:00
notlin4
1c3daeb08e Update traditional Chinese translation 2024-12-14 15:14:33 +08:00
notlin4
93b0b47e0e Update traditional Chinese translation 2024-12-14 15:13:03 +08:00
notlin4
31e91c5a93 Update traditional Chinese translation 2024-12-14 15:12:37 +08:00
Martin Prokoph
cbdc1750bc Fix compilation 2024-12-06 20:37:19 +01:00
Martin Prokoph
77b7b35f6d Port to 1.21.4
- Improved error handling
- Update LambDynamicLights
- Fix splash screen background blending once again
2024-12-06 20:33:15 +01:00
Martin Prokoph
ab83b2744a Fix mixin apply error 2024-11-05 19:10:09 +01:00
Martin Prokoph
9ee7ab1b89 Update to 1.21.3 2024-11-05 10:29:04 +01:00
Martin Prokoph
07af46da3c Handle incorrectly defined blend functions
- Now logs a warning instead of crashing
2024-09-24 23:40:12 +02:00
Martin Prokoph
f230cf3a4e Merge pull request #81 from C4BR3R4/patch-1
Create es_es.json
2024-09-24 23:37:10 +02:00
C4BR3R4
8646efb161 Create es_es.json
Changelog: http://c4br3r4.es/index.php?topic=1234.0
2024-09-07 14:17:47 +02:00
Martin Prokoph
fb1852dc2b Actually disable blending & Update example pack
- Blending will now be disabled when set to "off" instead of using the default blend function
2024-09-07 12:33:28 +02:00
Martin Prokoph
9dbe28242a Publishing: Add MidnightLib to the relations 2024-09-06 18:52:10 +02:00
Martin Prokoph
35c613a536 Puzzle 2.0.0 - Multiplatform & Cleaner code
- Removed intrusive branding (previously visible on Title screen and F3 menu)
- De-modularized: Previously, Puzzle was split into multiple modules which complicated the development process and was just unnecessary
- Experimental NeoForge support
- Many small improvements
- puzzle-splashscreen: Improved  background image blending
- puzzle-splashscreen: Added support for custom blend functions for full OptiFine parity
2024-09-06 18:44:27 +02:00
Martin Prokoph
651483af22 Update to 1.21 2024-06-16 18:53:43 +02:00
Martin Prokoph
b3b49cb8b8 Port to 1.20.6
- Port to 1.20.6
- Move compatibility code into individual classes
2024-05-04 19:55:04 +02:00
Martin Prokoph
39261272bf Puzzle 1.6.1 for 1.20.4
- Update to 1.20.4
- Re-Use MidnightConfig's list widget -> prettier background
2023-12-11 21:33:54 +01:00
Motschen
bc01662cda Puzzle 1.6.0 - 1.20.2 & Stability improvements
- Port to 1.20.2
- Improve stability by skipping outdated compat entries
- Update EMF integration
2023-09-24 21:18:45 +02:00
Martin Prokoph
1dc7245a99 Merge pull request #72 from Gazmanovich/1.20-1
Create be_by.json
2023-09-23 12:24:59 +02:00
Martin Prokoph
860d969c1d Merge pull request #69 from ImVietnam/patch-1
Create vi_vn.json
2023-09-23 12:24:37 +02:00
Alex Gazmanovich
acd3dbf9e2 Create be_by.json 2023-08-09 12:02:14 +03:00
I_am_Vietnam
cbd48603d2 Create vi_vn.json 2023-07-19 11:18:10 +07:00
Motschen
f91274dd90 Puzzle 1.5.2 - Fix crash without ModMenu
Fixes #67 & #68
2023-07-12 11:34:38 +02:00
Motschen
884ee8caf6 Puzzle 1.5.1 - 1.20 & Fixes
- Update to 1.20
- Fix version string behaving weirdly with ModMenu installed
- Integration for CEM replaced with EMF
2023-06-10 18:55:29 +02:00
Martin Prokoph
c921f3ff99 Update Traditional Chinese by @notlin4
Update Traditional Chinese by @notlin4
2023-06-10 16:52:45 +02:00
Martin Prokoph
8532a24b5e Merge pull request #59 from notlin4/patch-1
Update Traditional Chinese
2023-06-10 16:50:25 +02:00
Martin Prokoph
3a873df26a Merge pull request #60 from Felix14-v2/1.19.4
Update ru_ru.json
2023-06-10 16:49:57 +02:00
Martin Prokoph
e3615a79c4 Merge pull request #62 from Madis0/patch-2
Readme badges
2023-05-24 19:02:01 +02:00
Madis Otenurm
2704c2c80b Update README.md 2023-05-16 07:43:05 +03:00
Felix14-v2
83897109fe Update ru_ru.json
Oops
2023-04-21 15:41:08 +03:00
Felix14-v2
fc20a1b182 Update ru_ru.json 2023-04-21 15:29:29 +03:00
notlin4
927faea146 Update Traditional Chinese 2023-04-16 14:33:21 +08:00
Motschen
b979d5ac61 Puzzle 1.5.0 - 1.19.4, Options overhaul, Fixed splash screen
- Port to 1.19.4
- Overhaul the Puzzle Options screen
  - Categories are now displayed via tabs
- Fix #50 (Splash screen logo being pixelated)
- Add compatibility with Exordium
2023-03-15 18:54:29 +01:00
Martin Prokoph
12cdcba470 Merge pull request #54 from FITFC/1.19.3
Added lang/pt_br
2023-03-15 15:48:50 +01:00
FITFC
c9aa80f09f Added lang/pt_br 2022-12-24 12:45:21 -05:00
Motschen
12015d6ba4 Puzzle 1.4.2 - Update to 1.19.3
Here's a little Christmas present for y'all!
Puzzle now has 1.19.3 support.
2022-12-24 17:53:39 +01:00
Martin Prokoph
a8c89b11c7 Merge pull request #45 from Felix14-v2/1.19
Update ru_ru.json
2022-08-02 20:46:26 +00:00
Felix14-v2
f8ff656daa Update ru_ru.json 2022-08-02 23:35:50 +03:00
Motschen
f89fc08505 Puzzle 1.4.0 - Fixes, Integrations & Tooltip
- Fixed #41 (ETF 4.0+ crashing)
- Fixed #39 (Broken update checker)
- Fixed slider widgets being broken
- Hide buttons when options are empty (Closes #10)
- More mod integrations (Closes #20)
  - DynamicFPS
  - Borderless Mining
  - Colormatic
- Added tooltips for all Puzzle options
- Made everything translatable
- Improve German translations
2022-08-02 14:05:47 +02:00
Martin Prokoph
94afc8b0c0 Merge pull request #40 from Madis0/compress
Compress images
2022-08-01 17:41:00 +00:00
Martin Prokoph
64aa45a370 Merge pull request #43 from Traben-0/1.19
ETF 4.0 support added
2022-08-01 12:57:16 +00:00
Traben
05bea0aab1 ETF 4.0 support added 2022-08-01 15:01:16 +10:00
Madis
fbb368989e Compress images 2022-07-20 22:21:44 +03:00
Motschen
795759b4e5 Puzzle 1.3.4 - Custom splashscreen background & fixes
- Add the ability to use custom splash screen background images placed in a resourcepack under "assets/minecraft/puzzle/splash_background.png"
- Some more fixes regarding splash screen
2022-07-06 20:47:19 +02:00
Martin Prokoph
2410b8ff54 Merge pull request #35 from Felix14-v2/1.19
Update ru_ru.json
2022-07-06 18:42:27 +00:00
Martin Prokoph
d08889f186 Merge pull request #36 from gyular/ko_kr
create korean translation
2022-07-06 18:41:51 +00:00
gyular
2886fd509b create korean translation 2022-06-22 17:22:11 +09:00
Felix14-v2
8be9fc6872 Update ru_ru.json 2022-06-13 18:02:32 +03:00
146 changed files with 3698 additions and 1594 deletions

Binary file not shown.

View File

@@ -1,2 +1,4 @@
# Puzzle
Unites optifine replacement mods in a clean & vanilla-style gui
[![Download from Curseforge](https://cf.way2muchnoise.eu/full_563977_downloads%20on%20Curseforge.svg?badge_style=for_the_badge)](https://www.curseforge.com/minecraft/mc-mods/puzzle) [![Download from Modrinth](https://img.shields.io/modrinth/dt/puzzle?color=4&label=Download%20from%20Modrinth&style=for-the-badge)](https://modrinth.com/mod/puzzle)

View File

@@ -1,164 +1,119 @@
// Based on https://github.com/OnyxStudios/Cardinal-Components-API/blob/1.17/build.gradle
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
plugins {
id "fabric-loom" version "0.12-SNAPSHOT" apply false
id "com.matthewprenger.cursegradle" version "1.4.0"
id "maven-publish"
id "java-library"
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
}
group = "net.puzzlemc"
archivesBaseName = "puzzle"
architectury {
minecraft = rootProject.minecraft_version
}
subprojects {
apply plugin: 'fabric-loom'
apply plugin: 'com.matthewprenger.cursegradle'
apply plugin: 'maven-publish'
apply plugin: 'java-library'
archivesBaseName = project.name
group = "${rootProject.group}.${rootProject.archivesBaseName}"
}
allprojects {
apply plugin: "fabric-loom"
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
version = System.getenv("TRAVIS_TAG") ?: rootProject.mod_version
configurations {
dev
}
apply plugin: "dev.architectury.loom"
repositories {
maven { url 'https://jitpack.io' }
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}"
mappings "net.fabricmc:yarn:${rootProject.yarn_mappings}:v2"
modApi "net.fabricmc:fabric-loader:${rootProject.loader_version}"
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_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}"
}
}
processResources {
inputs.property "version", project.version
allprojects {
apply plugin: "java"
apply plugin: "architectury-plugin"
apply plugin: "maven-publish"
filesMatching("fabric.mod.json") {
expand "version": project.version
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()
}
}
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile).configureEach {
it.options.encoding = "UTF-8"
it.options.release = 17
processResources {
// Minify json resources
doLast {
fileTree(dir: outputs.files.asPath, include: "**/*.json").each {
File file -> file.text = JsonOutput.toJson(new JsonSlurper().parse(file))
}
}
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
jar {
}
afterEvaluate {
artifacts {
dev file: file("${project.buildDir}/libs/$archivesBaseName-${version}-dev.jar"), type: "jar", builtBy: sourcesJar
}
}
}
subprojects {
version = rootProject.version
}
subprojects.each { remapJar.dependsOn("${it.path}:remapJar") }
repositories {
maven {
name = "JitPack"
url = "https://jitpack.io"
}
maven {
name = "TerraformersMC"
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://api.modrinth.com/maven"
}
maven {
url "https://www.cursemaven.com"
content {
includeGroup "curse.maven"
}
}
maven {
name = 'JitPack'
url 'https://jitpack.io'
}
maven {
url "https://maven.shedaniel.me/"
}
}
dependencies {
modImplementation ("net.fabricmc.fabric-api:fabric-api:${project.fabric_version}")
modImplementation ("com.terraformersmc:modmenu:${project.mod_menu_version}") {
exclude group: "net.fabricmc.fabric-api"
}
modImplementation ("maven.modrinth:cull-leaves:${project.cull_leaves_version}")
modImplementation ("maven.modrinth:lambdynamiclights:${project.ldl_version}")
modImplementation ("maven.modrinth:lambdabettergrass:${project.lbg_version}")
modImplementation ("maven.modrinth:iris:${project.iris_version}")
modImplementation ("maven.modrinth:cit-resewn:${project.cit_resewn_version}")
modImplementation ("maven.modrinth:continuity:${project.continuity_version}")
modImplementation ("maven.modrinth:animatica:${project.animatica_version}")
modImplementation ("maven.modrinth:entitytexturefeatures:${project.entitytexturefeatures_version}")
modImplementation ("maven.modrinth:cem:${project.cem_version}")
modImplementation "com.gitlab.Lortseam:completeconfig:${project.complete_config_version}"
modImplementation("org.aperlambda:lambdajcommon:1.8.1") {
exclude group: 'com.google.code.gson'
exclude group: 'com.google.guava'
}
modImplementation "dev.lambdaurora:spruceui:${project.spruceui_version}"
modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}"
include "maven.modrinth:midnightlib:${project.midnightlib_version}"
subprojects.each {
api project(path: ":${it.name}", configuration: "dev")
include project(":${it.name}")
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact(file("${project.buildDir}/libs/${archivesBaseName}-${version}.jar")) {
builtBy(remapJar)
}
pom.withXml {
subprojects.each {
depNode.appendNode("groupId", it.group)
depNode.appendNode("artifactId", it.name)
depNode.appendNode("version", it.version)
depNode.appendNode("scope", "compile")
}
}
}
}
}

34
common/build.gradle Normal file
View 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.
}
}

View 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));
}
}
}

View 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());}
}

View File

@@ -0,0 +1,28 @@
package net.puzzlemc.core.config;
import eu.midnightdust.lib.config.MidnightConfig;
import java.util.ArrayList;
import java.util.List;
public class PuzzleConfig extends MidnightConfig {
private static final String GUI = "gui";
private static final String INTERNAL = "internal";
private static final String FEATURES = "features";
@Entry(category = GUI, name = "Disabled integrations") public static List<String> disabledIntegrations = new ArrayList<>();
@Entry(category = GUI, name = "Enable Puzzle button") public static boolean enablePuzzleButton = true;
@Entry(category = FEATURES, name = "puzzle.option.resourcepack_splash_screen") public static boolean resourcepackSplashScreen = true;
@Entry(category = FEATURES, name = "puzzle.option.unlimited_model_rotations") public static boolean unlimitedRotations = true;
@Entry(category = FEATURES, name = "puzzle.option.bigger_custom_models") public static boolean biggerModels = true;
@Entry(category = INTERNAL, name = "Enable debug messages") public static boolean debugMessages = false;
@Entry(category = INTERNAL, name = "Has custom splash screen") public static boolean hasCustomSplashScreen = false;
@Entry(category = INTERNAL, name = "Splash Background Color") public static int backgroundColor = 15675965;
@Entry(category = INTERNAL, name = "Splash Progress Bar Color") public static int progressBarColor = 16777215;
@Entry(category = INTERNAL, name = "Splash Progress Bar Background Color") public static int progressBarBackgroundColor = 15675965;
@Entry(category = INTERNAL, name = "Splash Progress Bar Frame Color") public static int progressFrameColor = 16777215;
@Entry(category = INTERNAL, name = "puzzle.option.better_splash_screen_blend") public static boolean disableBlend = false;
@Entry(category = INTERNAL, name = "Custom Blend Function") public static List<String> customBlendFunction = new ArrayList<>();
}

View 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) {
}
}

View File

@@ -2,15 +2,11 @@ package net.puzzlemc.gui;
import net.puzzlemc.core.config.PuzzleConfig;
import net.puzzlemc.gui.screen.widget.PuzzleWidget;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
public class PuzzleApi {
private static Logger LOGGER = LogManager.getLogger("puzzle-gui");
public static List<PuzzleWidget> GRAPHICS_OPTIONS = new ArrayList<>();
public static List<PuzzleWidget> MISC_OPTIONS = new ArrayList<>();
public static List<PuzzleWidget> PERFORMANCE_OPTIONS = new ArrayList<>();
@@ -18,18 +14,22 @@ public class PuzzleApi {
public static void addToGraphicsOptions(PuzzleWidget button) {
GRAPHICS_OPTIONS.add(button);
if (PuzzleConfig.debugMessages) LOGGER.info(button.descriptionText.getContent().toString() + " -> Graphics Options");
if (PuzzleConfig.debugMessages)
PuzzleGui.logger().info("{} -> Graphics Options", button.descriptionText.getContent().toString());
}
public static void addToMiscOptions(PuzzleWidget button) {
MISC_OPTIONS.add(button);
if (PuzzleConfig.debugMessages) LOGGER.info(button.descriptionText.getContent().toString() + " -> Misc Options");
if (PuzzleConfig.debugMessages)
PuzzleGui.logger().info("{} -> Misc Options", button.descriptionText.getContent().toString());
}
public static void addToPerformanceOptions(PuzzleWidget button) {
PERFORMANCE_OPTIONS.add(button);
if (PuzzleConfig.debugMessages) LOGGER.info(button.descriptionText.getContent().toString() + "- > Performance Options");
if (PuzzleConfig.debugMessages)
PuzzleGui.logger().info("{}- > Performance Options", button.descriptionText.getContent().toString());
}
public static void addToResourceOptions(PuzzleWidget button) {
RESOURCE_OPTIONS.add(button);
if (PuzzleConfig.debugMessages) LOGGER.info(button.descriptionText.getContent().toString() + " -> Resource Options");
if (PuzzleConfig.debugMessages)
PuzzleGui.logger().info("{} -> Resource Options", button.descriptionText.getContent().toString());
}
}

View 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();
}
}

View File

@@ -0,0 +1,28 @@
package net.puzzlemc.gui.compat;
import link.infra.borderlessmining.config.ConfigHandler;
import net.minecraft.client.MinecraftClient;
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 BorderlessMiningCompat {
public static void init() {
PuzzleApi.addToMiscOptions(new PuzzleWidget(Text.of("\uD83E\uDE9F Borderless Mining")));
ConfigHandler bmConfig = ConfigHandler.getInstance();
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 (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();
}));
}
}
}

View 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);
}
}
}

View File

@@ -0,0 +1,46 @@
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.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 ColormaticCompat {
public static void init() {
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("\uD83C\uDF08 Colormatic")));
ColormaticConfig colormaticConfig = Colormatic.config();
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(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(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(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, Text.translatable("colormatic.config.option.relativeBlockLightIntensity"),
() -> (int) (100*(1.0 - colormaticConfig.relativeBlockLightIntensityExponent / -16.0)),
(button) -> button.setMessage(Text.translatable("colormatic.config.option.relativeBlockLightIntensity")
.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);
ColormaticConfigController.persist(colormaticConfig);
}
catch (NumberFormatException ignored) {}
}));
}
}

View File

@@ -0,0 +1,27 @@
package net.puzzlemc.gui.compat;
import me.pepperbell.continuity.client.config.ContinuityConfig;
import me.pepperbell.continuity.client.config.Option;
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 ContinuityCompat {
public static void init() {
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(Text.translatable("options.continuity."+s), (button) -> button.setMessage(booleanOption.get() ? YES : NO), (button) -> {
booleanOption.set(!booleanOption.get());
contConfig.save();
}));
} catch (Exception ignored) {}
});
}
}

View File

@@ -0,0 +1,21 @@
package net.puzzlemc.gui.compat;
import eu.midnightdust.cullleaves.config.CullLeavesConfig;
import net.minecraft.client.MinecraftClient;
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 CullLeavesCompat {
public static void init() {
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");
MinecraftClient.getInstance().worldRenderer.reload();
}));
}
}

View 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();
}));
}
}
}

View 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();
}));
}
}

View 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));
}));
}
}

View 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())));
}
}

View 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())));
}
}

View 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);
}
}

View 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);
}
}
}

View File

@@ -0,0 +1,22 @@
package net.puzzlemc.gui.screen.widget;
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 ButtonWidget {
private final PuzzleWidget.TextAction title;
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(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);
}
}

View File

@@ -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();
}
}

View File

@@ -9,16 +9,17 @@ public class PuzzleSliderWidget extends SliderWidget {
private final PuzzleWidget.TextAction setTextAction;
private final PuzzleWidget.ChangeSliderValueAction changeAction;
public PuzzleSliderWidget(int min, int max, int x, int y, int width, int height, PuzzleWidget.SetSliderValueAction setValueAction, PuzzleWidget.TextAction setTextAction, PuzzleWidget.ChangeSliderValueAction changeAction) {
super(x,y,width,height,Text.of(""),0);
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;
setValueAction.setSliderValue(this);
this.setTextAction = setTextAction;
this.changeAction = changeAction;
this.updateMessage();
try {
this.updateMessage();
} catch (Exception e) {e.fillInStackTrace(); this.visible = false;}
}
public int getInt() {
int difference = max - min;

View File

@@ -12,7 +12,9 @@ public class PuzzleTextFieldWidget extends TextFieldWidget {
super(textRenderer, x, y, width, height, Text.of(""));
this.setValueAction = setValue;
this.change = change;
setValueAction.setTextValue(this);
try {
setValueAction.setTextValue(this);
} catch (Exception e) {e.fillInStackTrace(); this.setVisible(false);}
}
@Override
public void write(String text) {

View File

@@ -1,22 +1,21 @@
package net.puzzlemc.gui.screen.widget;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
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;
public class PuzzleWidget {
public ButtonType buttonType;
public int min;
public int max;
public Text descriptionText;
public Text buttonText;
public TextAction buttonTextAction;
public ButtonWidget.PressAction onPress;
public PuzzleWidget.SetTextValueAction setTextValue;
public PuzzleWidget.SetSliderValueAction setSliderValue;
public IntSupplier defaultSliderValue;
public PuzzleWidget.ChangeTextValueAction changeTextValue;
public PuzzleWidget.ChangeSliderValueAction changeSliderValue;
@@ -42,43 +41,37 @@ public class PuzzleWidget {
this.onPress = onPress;
}
/**
* Puzzle Slider Widget Container (WIP - Doesn't work)
* Puzzle Slider Widget Container
*/
public PuzzleWidget(int min, int max, Text descriptionText, PuzzleWidget.SetSliderValueAction setValueAction, 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;
this.descriptionText = descriptionText;
this.setSliderValue = setValueAction;
this.defaultSliderValue = defaultSliderValue;
this.buttonTextAction = setTextAction;
this.changeSliderValue = changeAction;
}
/**
* Puzzle Text Field Widget Container (WIP - Doesn't work)
*/
public PuzzleWidget(Text descriptionText, PuzzleWidget.SetTextValueAction setValue, ChangeTextValueAction changeAction, int a) {
public PuzzleWidget(int min, int max, Text descriptionText, PuzzleWidget.SetTextValueAction setValue, ChangeTextValueAction changeAction) {
this.buttonType = ButtonType.TEXT_FIELD;
this.min = min;
this.max = max;
this.descriptionText = descriptionText;
this.setTextValue = setValue;
this.changeTextValue = changeAction;
}
@Environment(EnvType.CLIENT)
public interface ChangeTextValueAction {
void onChange(TextFieldWidget textField);
}
@Environment(EnvType.CLIENT)
public interface ChangeSliderValueAction {
void onChange(PuzzleSliderWidget slider);
}
@Environment(EnvType.CLIENT)
public interface SetTextValueAction {
void setTextValue(TextFieldWidget textField);
}
@Environment(EnvType.CLIENT)
public interface SetSliderValueAction {
void setSliderValue(PuzzleSliderWidget slider);
}
@Environment(EnvType.CLIENT)
public interface TextAction {
void setTitle(ClickableWidget button);
}

View File

@@ -4,8 +4,8 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.client.render.model.json.ModelElement;
import net.minecraft.util.JsonHelper;
import net.minecraft.util.math.Vec3f;
import net.puzzlemc.core.config.PuzzleConfig;
import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ModelElement.Deserializer.class)
public abstract class MixinModelElementDeserializer {
@Shadow protected abstract Vec3f deserializeVec3f(JsonObject object, String name);
@Shadow protected abstract Vector3f deserializeVec3f(JsonObject object, String name);
@Inject(at = @At("HEAD"),method = "deserializeRotationAngle", cancellable = true)
private void puzzle$deserializeRotationAngle(JsonObject object, CallbackInfoReturnable<Float> cir) {
@@ -24,10 +24,10 @@ public abstract class MixinModelElementDeserializer {
}
}
@Inject(at = @At("HEAD"),method = "deserializeTo", cancellable = true)
private void puzzle$deserializeTo(JsonObject object, CallbackInfoReturnable<Vec3f> cir) {
private void puzzle$deserializeTo(JsonObject object, CallbackInfoReturnable<Vector3f> cir) {
if (PuzzleConfig.biggerModels) {
Vec3f vec3f = this.deserializeVec3f(object, "to");
if (!(vec3f.getX() < -32.0F) && !(vec3f.getY() < -32.0F) && !(vec3f.getZ() < -32.0F) && !(vec3f.getX() > 48.0F) && !(vec3f.getY() > 48.0F) && !(vec3f.getZ() > 48.0F)) {
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 {
throw new JsonParseException("'to' specifier exceeds the allowed boundaries: " + vec3f);
@@ -35,10 +35,10 @@ public abstract class MixinModelElementDeserializer {
}
}
@Inject(at = @At("HEAD"),method = "deserializeFrom", cancellable = true)
private void puzzle$deserializeFrom(JsonObject object, CallbackInfoReturnable<Vec3f> cir) {
private void puzzle$deserializeFrom(JsonObject object, CallbackInfoReturnable<Vector3f> cir) {
if (PuzzleConfig.biggerModels) {
Vec3f vec3f = this.deserializeVec3f(object, "from");
if (!(vec3f.getX() < -32.0F) && !(vec3f.getY() < -32.0F) && !(vec3f.getZ() < -32.0F) && !(vec3f.getX() > 48.0F) && !(vec3f.getY() > 48.0F) && !(vec3f.getZ() > 48.0F)) {
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 {
throw new JsonParseException("'from' specifier exceeds the allowed boundaries: " + vec3f);

View File

@@ -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;
}
}

View 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();
}
}

View File

@@ -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) {
}
}

View File

@@ -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();
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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");
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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()));
}
}

View File

@@ -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());
}
}
}

View File

@@ -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()));
}
}

View File

@@ -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));
}
}

View File

@@ -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)));
}
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}

View File

@@ -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);
// }
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
// }
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}

View File

@@ -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);
// }
}

View File

@@ -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);
//
//
// }
// }
//}

View 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);
}
}

View 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();
}
}
}
}
}

View 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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,3 @@
{
"accessWidener": "puzzle-models.accesswidener"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,42 @@
{
"puzzle.text.update_available":"Даступна абнаўленне!",
"puzzle.screen.title":"Налады Puzzle",
"puzzle.page.graphics":"Графіка",
"puzzle.page.resources":"Рэсурсы",
"puzzle.page.performance":"Прадукцыйнасць",
"puzzle.page.misc":"Рознае",
"puzzle.option.check_for_updates":"Праверыць абнаўленні",
"puzzle.option.check_for_updates.tooltip":"Уключае ўбудаваны правершчык абнаўленняў",
"puzzle.option.show_version_info":"Паказваць версію Puzzle",
"puzzle.option.show_version_info.tooltip":"Паказваць інфармацыю пра бягучую\nверсію Puzzle и наяўнасць абнаўленняў на\nтытульным экране і меню F3",
"puzzle.option.resourcepack_splash_screen":"Выкарыстанне пакетаў рэсурсаў для сплэшэй",
"puzzle.option.resourcepack_splash_screen.tooltip":"Уключае пакеты рэсурсаў, якія змяняюць\nзагрузачныя экраны/сплэшы\nMinecraft, якія выкарыстоўваюць фармат OptiFine",
"puzzle.option.better_splash_screen_blend":"Палепшанае спалучэнне сплэшэй і лагатыпу",
"puzzle.option.better_splash_screen_blend.tooltip":"Змяняе тып спалучэння\nлагатыпу і сплэшэй\nкаб палепшыць працу з лагатыпамі карыстальніцкіх колераў",
"puzzle.option.unlimited_model_rotations":"Неабмежаванае вярчэнне мадэлі",
"puzzle.option.unlimited_model_rotations.tooltip":"Дазваляе вярчэнне на 360° на карыстальніцкіх мадэляў блокаў/прадметаў",
"puzzle.option.bigger_custom_models":"Павялічаныя карыстальніцкія мадэлі",
"puzzle.option.bigger_custom_models.tooltip":"Павялічвае ліміт памеру\nкарыстальніцкіх мадэляў блокаў/прадметаў\nз 3x3x3 да 5x5x5",
"puzzle.midnightconfig.title":"Пашыраныя налады Puzzle",
"puzzle.midnightconfig.category.gui":"GUI",
"puzzle.midnightconfig.category.features":"Асаблівасці",
"puzzle.midnightconfig.category.debug":"Debug",
"puzzle.midnightconfig.tooltip":"Налады толькі для вопытных карыстальнікаў",
"cullleaves.puzzle.option.enabled": "Адбракоўваць лісце",
"cullleaves.puzzle.option.enabled.tooltip": "Уключыць адбракоўванне лісця, каб павялічыць прадукцыйнасць",
"iris.puzzle.option.enableShaders": "Уключыць шэйдэры",
"iris.puzzle.option.enableShaders.tooltip": "Дазваляе уключаць ці выключаць шэйдэры",
"iris.puzzle.option.open": "АДКРЫЦЬ",
"options.iris.shaderPackSelection.tooltip": "Адкрывае экран выбару\nшэйдэраў і іх налад",
"lambdabettergrass.option.mode.tooltip": "Робіць бакі\nзямлі з дзёрнам злучанымі з\nверхам гэтага блоку",
"lambdabettergrass.option.better_snow.tooltip": "Дадае крыху бачны слой снег/імху\nна непоўныя блокі, якія\nакружаны снегам/імхом",
"config.dynamicfps.reduce_when_unfocused.tooltip": "Зніжае FPS у Minecraft калі ён не актыўны\n(то бок калі іншая прагракма адчынена ці гульня згорнута)\nкаб захаваць рэсурсы сістэмы",
"config.dynamicfps.unfocused_fps.tooltip": "Колькасць кадраў у секунду, калі\nMinecraft згорнуты",
"config.dynamicfps.restore_when_hovered.tooltip": "Дазваляе скасаваць ці не\nабмежаванне FPS, калі Minecraft актыны\n(то бок актыўны ці наведзены курсорам з панелі задач)",
"config.dynamicfps.run_gc_on_unfocus.tooltip": "Запусціць збіральнік смецця калі\nMinecraft неактыўны,\n каб ачысціць крыху АЗУ",
"config.dynamicfps.unfocused_volume.tooltip": "Гучнасць прайгравальных гукаў\nкалі гульня не актыўна\n(то бок іншае акно абрана)",
"config.dynamicfps.hidden_volume.tooltip": "Гучнасць прайгравальных гукаў\nкали гульня не бачна\n(то бок згорнута, знаходзіцца пад іншымі вокнамі\nці на ішай віртуальнай машыне)",
"entity_texture_features.puzzle.emissive_type.brighter": "§eЯрчэй",
"entity_texture_features.puzzle.emissive_type.default": "§6Стандартна"
}

View File

@@ -0,0 +1,39 @@
{
"puzzle.text.update_available":"Ein Update ist verfügbar!",
"puzzle.screen.title":"Puzzle Einstellungen",
"puzzle.page.graphics":"Grafik",
"puzzle.page.resources":"Resourcen",
"puzzle.page.performance":"Performance",
"puzzle.page.misc":"Sonstiges",
"puzzle.option.check_for_updates":"Auf Updates überprüfen",
"puzzle.option.show_version_info":"Zeige Informationen über Puzzle's Version",
"puzzle.option.resourcepack_splash_screen":"Nutze Resourcepack-Ladebildschirm",
"puzzle.option.better_splash_screen_blend":"Verbessere das Blending des Splash-Screen-Logos",
"puzzle.option.unlimited_model_rotations":"Unbegrenzte Modellrotationen",
"puzzle.option.bigger_custom_models":"Größere benutzerdefinierte Modelle",
"puzzle.midnightconfig.title":"Erweiterte Puzzle Konfiguration",
"puzzle.option.check_for_updates.tooltip": "Aktiviert Puzzle's eingebauten Update-Checker",
"puzzle.option.show_version_info.tooltip": "Zeigt Informationen über die Version\nvon Puzzle und die Verfügbarkeit von Updates\nauf dem Titelbildschirm und im F3-Menü",
"puzzle.option.resourcepack_splash_screen.tooltip": "Ermöglicht Resourcepacks, das Aussehen\ndes Ladebildschirms mit dem\nOptiFine-Format zu verändern",
"puzzle.option.better_splash_screen_blend.tooltip": "Ändert die Art des Blending,\ndie für das Logo auf dem Ladebildschirm benutzt wird,\ndamit es besser mit farbigen Logos funktioniert.",
"puzzle.option.unlimited_model_rotations.tooltip": "Schaltet volle 360° Rotation für\nbenutzerdefinierte Item-/Blockmodelle frei",
"puzzle.option.bigger_custom_models.tooltip": "Erhöht das Größenlimit für\nbenutzerdefinierte Item-/Blockmodelle\nvon 3x3x3 auf 5x5x5",
"puzzle.midnightconfig.tooltip": "Optionen für fortgeschrittene Nutzer",
"cullleaves.puzzle.option.enabled": "Aktiviere Culling für Blätter",
"cullleaves.puzzle.option.enabled.tooltip": "Fügt Occlusion Culling für \nBlätter hinzu, was die Leistung des \nSpiels verbessert",
"iris.puzzle.option.enableShaders": "Shader aktivieren",
"iris.puzzle.option.enableShaders.tooltip": "Legt fest, ob Shader aktiviert werden sollen",
"iris.puzzle.option.open": "ÖFFNEN",
"options.iris.shaderPackSelection.tooltip": "Öffnet einen Bildschirm, um Shader\nauszuwählen und zu konfigurieren",
"lambdabettergrass.option.mode.tooltip": "Verbindet die Seiten von Grasblöcken\nmit anliegenden Grasblöcken",
"lambdabettergrass.option.better_snow.tooltip": "Fügt eine rein visuelle Schnee-/Moosschicht\nunter nicht-volle Blöcke hinzu,\nwelche von Schnee/Moos umgeben sind",
"config.dynamicfps.reduce_when_unfocused.tooltip": "Reduziert Minecraft's FPS,\nwährend das Spiel nicht im Fokus ist\n(z.B. wenn ein anderes Fenster fokussiert oder das Spiel versteckt ist)\num Strom und Systemressourcen zu sparen",
"config.dynamicfps.unfocused_fps.tooltip": "Die Anzahl der Bilder pro Sekunde (FPS)\nmit denen Minecraft rendern\ndarf, wenn es nicht im Fokus ist",
"config.dynamicfps.restore_when_hovered.tooltip": "Legt fest, ob die Limitierung\nder FPS aufgehoben werden soll, wenn Minecraft in der Vorschau erscheint\n(z.B. in der Taskleiste oder Dock überfahren wird)",
"config.dynamicfps.run_gc_on_unfocus.tooltip": "Lässt einen Garbage Collector laufen,\nwährend Minecraft nicht im Fokus ist\num etwas Arbeitsspeicher (RAM) freizumachen",
"config.dynamicfps.unfocused_volume.tooltip": "Die Lautstärke mit der Minecraft\nGeräusche wiedergeben kann, während es nicht im Fokus ist\n(z.B. wenn ein anderes Fenster fokussiert ist)",
"config.dynamicfps.hidden_volume.tooltip": "Die Lautstärke mit der Minecraft\nGeräusche wiedergeben kann, während es nicht im Fokus ist\n(z.B. wenn es minimiert, von anderen Fenstern verdeckt\noder auf einem anderen virtuellen Desktop ist)",
"entity_texture_features.puzzle.emissive_type.brighter": "§eHeller",
"entity_texture_features.puzzle.emissive_type.default": "§6Normal"
}

View File

@@ -1,10 +1,10 @@
{
"puzzle.text.update_available":"Μια καινούρια έκδοση είναι διαθέσιμη!",
"puzzle.screen.title":"Ρυθμίσεις του Puzzle",
"puzzle.page.graphics":"Ρυθμίσεις Γραφικών",
"puzzle.page.resources":"Ρυθμίσεις Πόρων",
"puzzle.page.performance":"Ρυθμίσεις Απόδοσης",
"puzzle.page.misc":"Διάφορες Ρυθμίσεις",
"puzzle.page.graphics":"Γραφικών",
"puzzle.page.resources":"Πόρων",
"puzzle.page.performance":"Απόδοσης",
"puzzle.page.misc":"Διάφορες",
"puzzle.option.check_for_updates":"Έλεγχος για αναβαθμίσεις",
"puzzle.option.show_version_info":"Εμφάνηση έκδοσης του Puzzle",
"puzzle.option.resourcepack_splash_screen":"Οθόνη φόρτωσης πακέτου πόρων",

View File

@@ -0,0 +1,42 @@
{
"puzzle.text.update_available":"An update is available!",
"puzzle.screen.title":"Puzzle Settings",
"puzzle.page.graphics":"Graphics",
"puzzle.page.resources":"Resource",
"puzzle.page.performance":"Performance",
"puzzle.page.misc":"Miscellaneous",
"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",
"puzzle.option.show_version_info.tooltip":"Show information about the current\nPuzzle version and update status on\nthe Title Screen and F3 Menu",
"puzzle.option.resourcepack_splash_screen":"Use resourcepack splash screen",
"puzzle.option.resourcepack_splash_screen.tooltip":"Enables resourcepacks to change the look\nof Minecraft's loading/splash\nscreen using the OptiFine format",
"puzzle.option.better_splash_screen_blend":"Better splash screen logo blending",
"puzzle.option.better_splash_screen_blend.tooltip":"Changes the type of blending used\nby the logo on the splash screen\nto work better with custom colored logos",
"puzzle.option.unlimited_model_rotations":"Unlimited Model Rotations",
"puzzle.option.unlimited_model_rotations.tooltip":"Unlocks full 360° rotation on custom block/item models",
"puzzle.option.bigger_custom_models":"Bigger Custom Models",
"puzzle.option.bigger_custom_models.tooltip":"Increases the limit of\ncustom block/item model sizes\nfrom 3x3x3 to 5x5x5",
"puzzle.midnightconfig.title":"Puzzle Advanced Config",
"puzzle.midnightconfig.category.gui":"GUI",
"puzzle.midnightconfig.category.features":"Features",
"puzzle.midnightconfig.category.internal":"Internal",
"puzzle.midnightconfig.tooltip":"Options for advanced users only",
"cullleaves.puzzle.option.enabled": "Cull Leaves",
"cullleaves.puzzle.option.enabled.tooltip": "Enable the culling of leaves to enhance performance",
"iris.puzzle.option.enableShaders": "Enable Shaders",
"iris.puzzle.option.enableShaders.tooltip": "Whether or not to enable shaderpacks",
"iris.puzzle.option.open": "OPEN",
"options.iris.shaderPackSelection.tooltip": "Open a screen to select\nshaderpacks and configure them",
"lambdabettergrass.option.mode.tooltip": "Makes the sides of\ngrass blocks connect to\nadjacent grass blocks",
"lambdabettergrass.option.better_snow.tooltip": "Adds a purely visual snow/moss layer\nto non-full blocks that\nare surrounded by snow/moss",
"config.dynamicfps.reduce_when_unfocused.tooltip": "Reduces Minecraft's FPS when unfocused\n(i.e. another window is focused or the game is hidden)\nto save power and system resources",
"config.dynamicfps.unfocused_fps.tooltip": "The amount of frames per second\nMinecraft is allowed to\nrender at while unfocused",
"config.dynamicfps.restore_when_hovered.tooltip": "Whether or not to stop the\nFPS limiting while Minecraft is previewed\n(i.e. hovered on task bar or dock)",
"config.dynamicfps.run_gc_on_unfocus.tooltip": "Run a garbage collector while\nMinecraft is not focused to\nfree up some RAM",
"config.dynamicfps.unfocused_volume.tooltip": "The volume the game should play\nsound at while unfocused\n(i.e. another window is selected)",
"config.dynamicfps.hidden_volume.tooltip": "The volume the game should play\nsound at while not visible\n(i.e. minimized, covered by other windows\nor on another virtual desktop)",
"entity_texture_features.puzzle.emissive_type.brighter": "§eBrighter",
"entity_texture_features.puzzle.emissive_type.default": "§6Default"
}

View File

@@ -0,0 +1,42 @@
{
"puzzle.text.update_available":"¡Hay una actualización disponible!",
"puzzle.screen.title":"Configuración de Puzzle",
"puzzle.page.graphics":"Gráficos",
"puzzle.page.resources":"Recursos",
"puzzle.page.performance":"Rendimiento",
"puzzle.page.misc":"Variado",
"puzzle.option.check_for_updates":"Comprobar Actualizaciones",
"puzzle.option.check_for_updates.tooltip":"Activa el comprobador de actualizaciones integrado de Puzzle.",
"puzzle.option.show_version_info":"Mostrar información de la versión Puzzle",
"puzzle.option.show_version_info.tooltip":"Muestra información sobre la versión actual\nde Puzzle y el estado de actualización\nen la pantalla de título y en el menú F3.",
"puzzle.option.resourcepack_splash_screen":"Usar la Pantalla de Carga del Paquete de Recursos [*]",
"puzzle.option.resourcepack_splash_screen.tooltip":"Permite que los paquetes de recursos\ncambien el aspecto de la pantalla de carga/principal\nde Minecraft utilizando el formato OptiFine.",
"puzzle.option.better_splash_screen_blend":"Mejor Mezcla del Logo de la Pantalla de Carga",
"puzzle.option.better_splash_screen_blend.tooltip":"Cambia el tipo de mezcla utilizada\npor el logotipo de la pantalla de carga\npara que funcione mejor con logotipos\nde colores personalizados.",
"puzzle.option.unlimited_model_rotations":"Rotaciones Ilimitadas de Modelos",
"puzzle.option.unlimited_model_rotations.tooltip":"Desbloquea la rotación completa de 360° en los modelos de bloques/objetos personalizados.",
"puzzle.option.bigger_custom_models":"Modelos Personalizados más Grandes",
"puzzle.option.bigger_custom_models.tooltip":"Aumenta el límite de tamaños\nde los modelos de bloques/objetos personalizados\nde 3x3x3 a 5x5x5.",
"puzzle.midnightconfig.title":"Acceder a las Opciones adicionales de Puzzle para Expertos",
"puzzle.midnightconfig.category.gui":"Interfaz",
"puzzle.midnightconfig.category.features":"Características",
"puzzle.midnightconfig.category.debug":"Depuración",
"puzzle.midnightconfig.tooltip":"Ajustes para usuarios experimentados.",
"cullleaves.puzzle.option.enabled": "Reducir Cantidad de Hojas",
"cullleaves.puzzle.option.enabled.tooltip": "Permitir reducir la cantidad de hojas para mejorar el rendimiento.",
"iris.puzzle.option.enableShaders": "Activar Sombreadores",
"iris.puzzle.option.enableShaders.tooltip": "Activar o no los paquetes de sombreadores.",
"iris.puzzle.option.open": "ABRIR",
"options.iris.shaderPackSelection.tooltip": "Abre la pantalla de selección\nde los paquetes de sombreadores.",
"lambdabettergrass.option.mode.tooltip": "Hace que los lados de los bloques de\ncésped se conecten con los bloques de\ncésped adyacentes.",
"lambdabettergrass.option.better_snow.tooltip": "Añade una capa de nieve/musgo puramente\nvisual a los bloques no llenos que están rodeados\nde nieve/musgo.",
"config.dynamicfps.reduce_when_unfocused.tooltip": "Reduce los FPS de Minecraft cuando el\njuego se encuentra en segundo plano (es decir,\ncuando otra ventana está en primer plano o el juego\nestá oculto) para ahorrar energía y recursos\ndel sistema.",
"config.dynamicfps.unfocused_fps.tooltip": "La cantidad de fotogramas por segundo que\nMinecraft puede renderizar mientras se\nencuentra en segundo plano.",
"config.dynamicfps.restore_when_hovered.tooltip": "Detener o no la limitación de FPS mientras\ndurante la previsualización de Minecraft\n(por ejemplo cuando se señala en la barra de\ntareas o en el área de notificación).",
"config.dynamicfps.run_gc_on_unfocus.tooltip": "Ejecutar un recolector de basura mientras\nMinecraft se encuentra en segundo plano\npara liberar algo de RAM.",
"config.dynamicfps.unfocused_volume.tooltip": "El volumen del sonido del juego cuando permanece\nen segundo plano (es decir, cuando hay otra\nventana seleccionada).",
"config.dynamicfps.hidden_volume.tooltip": "El volumen del juego cuando no es visible (es decir, minimizado, cubierto por otras ventanas o en otro escritorio virtual).",
"entity_texture_features.puzzle.emissive_type.brighter": "§eResplandeciente",
"entity_texture_features.puzzle.emissive_type.default": "§6Predeterminado"
}

View File

@@ -1,10 +1,10 @@
{
"puzzle.text.update_available":"Uuendus on saadaval!",
"puzzle.screen.title":"Puzzle sätted",
"puzzle.page.graphics":"Graafikasätted",
"puzzle.page.resources":"Ressursisätted",
"puzzle.page.performance":"Jõudlussätted",
"puzzle.page.misc":"Muud sätted",
"puzzle.page.graphics":"Graafika",
"puzzle.page.resources":"Ressursi",
"puzzle.page.performance":"Jõudlus",
"puzzle.page.misc":"Muud",
"puzzle.option.check_for_updates":"Uuenduste kontroll",
"puzzle.option.show_version_info":"Kuva Puzzle versiooniteavet",
"puzzle.option.resourcepack_splash_screen":"Kasuta ressursipaki laadimiskuva",

View File

@@ -0,0 +1,17 @@
{
"puzzle.text.update_available":"업데이트가 가능합니다!",
"puzzle.screen.title":"Puzzle 설정",
"puzzle.page.graphics":"그래픽",
"puzzle.page.resources":"리소스",
"puzzle.page.performance":"성능",
"puzzle.page.misc":"기타",
"puzzle.option.check_for_updates":"업데이트 확인",
"puzzle.option.show_version_info":"Puzzle 버전 정보 보기",
"puzzle.option.resourcepack_splash_screen":"스플래시 화면에서 리소스팩 사용",
"puzzle.option.better_splash_screen_blend":"향상된 스플래시 화면 로고 블렌딩",
"puzzle.option.emissive_textures":"방사성 텍스쳐",
"puzzle.option.unlimited_model_rotations":"모델 회전 제한없음",
"puzzle.option.bigger_custom_models":"향상된 커스텀 모델",
"puzzle.option.render_layer_overrides":"렌더링 레이어 재정의",
"puzzle.midnightconfig.title":"Puzzle 고급 환경설정"
}

View File

@@ -1,10 +1,10 @@
{
"puzzle.text.update_available":"Aktualizacja jest dostępna!",
"puzzle.screen.title":"Ustawienia Puzzle",
"puzzle.page.graphics":"Ustawienia grafiki",
"puzzle.page.resources":"Ustawienia zasobów",
"puzzle.page.performance":"Ustawienia wydajności",
"puzzle.page.misc":"Różne ustawienia",
"puzzle.page.graphics":"Grafiki",
"puzzle.page.resources":"Zasobów",
"puzzle.page.performance":"Wydajności",
"puzzle.page.misc":"Ustawienia",
"puzzle.option.check_for_updates":"Sprawdź aktualizacje",
"puzzle.option.show_version_info":"Pokaż informacje o wersji Puzzle",
"puzzle.option.resourcepack_splash_screen":"Użyj ekranu powitalnego paczek zasobów",

View File

@@ -0,0 +1,42 @@
{
"puzzle.text.update_available":"Uma atualização está disponível!",
"puzzle.screen.title":"Configurações do Puzzle",
"puzzle.page.graphics":"Gráficas",
"puzzle.page.resources":"Recursos",
"puzzle.page.performance":"Desempenho",
"puzzle.page.misc":"Diversas",
"puzzle.option.check_for_updates":"Verifique se há atualizações",
"puzzle.option.check_for_updates.tooltip":"Ativa o verificador de atualização integrado do Puzzle",
"puzzle.option.show_version_info":"Mostrar informações da versão do Puzzle",
"puzzle.option.show_version_info.tooltip":"Mostrar informações sobre o atual\nversão do Puzzle e status de atualização em\n Tela de Título e o Menu F3",
"puzzle.option.resourcepack_splash_screen":"Use a tela inicial do pacote de recursos",
"puzzle.option.resourcepack_splash_screen.tooltip":"Permite que os pacotes de recursos mudem a aparência\ndo carregamento do Minecraft/splash\ntela usando o formato OptiFine",
"puzzle.option.better_splash_screen_blend":"Melhor combinação do logotipo da tela inicial",
"puzzle.option.better_splash_screen_blend.tooltip":"Muda o tipo de mistura usado\npelo logotipo na tela inicial\npara trabalhar melhor com logotipos coloridos personalizados",
"puzzle.option.unlimited_model_rotations":"Rotações de Modelo Ilimitadas",
"puzzle.option.unlimited_model_rotations.tooltip":"Desbloqueia rotação total de 360° em modelos de itens/blocos personalizados",
"puzzle.option.bigger_custom_models":"Modelos Personalizados Maiores",
"puzzle.option.bigger_custom_models.tooltip":"Aumenta o limite de\ntamanhos de modelo de bloco/item personalizados\nde 3x3x3 a 5x5x5",
"puzzle.midnightconfig.title":"Configuração Avançada do Puzzle",
"puzzle.midnightconfig.category.gui":"GUI",
"puzzle.midnightconfig.category.features":"Recursos",
"puzzle.midnightconfig.category.internal":"Interno",
"puzzle.midnightconfig.tooltip":"Opções apenas para usuários avançados",
"cullleaves.puzzle.option.enabled": "Abate de Folhas",
"cullleaves.puzzle.option.enabled.tooltip": "Ative o abate de folhas para melhorar o desempenho",
"iris.puzzle.option.enableShaders": "Ativar sombreadores",
"iris.puzzle.option.enableShaders.tooltip": "Habilitar ou não shaderpacks",
"iris.puzzle.option.open": "ABRIR",
"options.iris.shaderPackSelection.tooltip": "Abra uma tela para selecionar\nshaderpacks e configurá-los",
"lambdabettergrass.option.mode.tooltip": "Faz os lados de\nblocos de grama se conectam a\nblocos de grama adjacentes",
"lambdabettergrass.option.better_snow.tooltip": "Adiciona uma neve puramente visual/camada de musgo\na blocos não completos que\nestão rodeados de neve/musgo",
"config.dynamicfps.reduce_when_unfocused.tooltip": "Reduz o FPS do Minecraft quando desfocado\n(ou seja, outra janela está focada ou o jogo está oculto)\npara economizar energia e recursos do sistema",
"config.dynamicfps.unfocused_fps.tooltip": "A quantidade de quadros por segundo\nMinecraft é permitido\nrenderizar enquanto estiver fora de foco",
"config.dynamicfps.restore_when_hovered.tooltip": "Interromper ou não o\nLimitação de FPS enquanto o Minecraft é visualizado\n(ou seja, pairou na barra de tarefas ou dock)",
"config.dynamicfps.run_gc_on_unfocus.tooltip": "Execute um coletor de lixo enquanto\nMinecraft não está focado em\nliberar um pouco de RAM",
"config.dynamicfps.unfocused_volume.tooltip": "O volume que o jogo deve reproduzir\nsom enquanto desfocado\n(ou seja, outra janela é selecionada)",
"config.dynamicfps.hidden_volume.tooltip": "O volume que o jogo deve reproduzir\nsom em enquanto não visível\n(ou seja, minimizado, coberto por outras janelas\nem em outra área de trabalho virtual)",
"entity_texture_features.puzzle.emissive_type.brighter": "§eMais Brilhante",
"entity_texture_features.puzzle.emissive_type.default": "§6Padrão"
}

View File

@@ -0,0 +1,48 @@
{
"puzzle.text.update_available":"Доступно обновление!",
"puzzle.screen.title":"Настройки Puzzle",
"puzzle.page.graphics":"Графика",
"puzzle.page.resources":"Ресурсы",
"puzzle.page.performance":"Оптимизация",
"puzzle.page.misc":"Прочие",
"puzzle.option.check_for_updates":"Проверять обновления",
"puzzle.option.check_for_updates.tooltip":"Включить встроенную в Puzzle проверку обновлений",
"puzzle.option.show_version_info":"Показывать информацию о версии",
"puzzle.option.show_version_info.tooltip":"Отображать информацию о текущей версии\nPuzzle и наличии обновлений\nна главном экране и экране отладки",
"puzzle.option.resourcepack_splash_screen":"Пользовательский экран загрузки",
"puzzle.option.resourcepack_splash_screen.tooltip":"Разрешить наборам ресурсов изменять\nвнешний вид экрана загрузки Minecraft,\nиспользуя формат OptiFine",
"puzzle.option.better_splash_screen_blend":"Улучшенное смешивание логотипа",
"puzzle.option.better_splash_screen_blend.tooltip":"Изменить метод смешивания, используемый\nдля логотипа на экране загрузки,\nчтобы улучшить вид с изменёнными цветами",
"puzzle.option.unlimited_model_rotations":"Неограниченные повороты моделей",
"puzzle.option.unlimited_model_rotations.tooltip":"Разрешить поворот частей\nпользовательских моделей\nблоков/предметов на 360°",
"puzzle.option.bigger_custom_models":"Увеличенный размер моделей",
"puzzle.option.bigger_custom_models.tooltip":"Увеличить предельный размер\nпользовательских моделей блоков\nи предметов с 3×3×3 до 5×5×5",
"puzzle.midnightconfig.title":"Расширенные настройки Puzzle",
"puzzle.midnightconfig.category.gui":"Интерфейс",
"puzzle.midnightconfig.category.features":"Функционал",
"puzzle.midnightconfig.category.debug":"Отладка",
"puzzle.midnightconfig.tooltip":"Только для продвинутых пользователей!",
"cullleaves.puzzle.option.enabled": "Отбраковка листьев",
"cullleaves.puzzle.option.enabled.tooltip": "Включить отбраковку блоков листьев\nдля улучшения производительности",
"iris.puzzle.option.enableShaders": "Шейдеры",
"iris.puzzle.option.enableShaders.tooltip": "Включить выбранный набор шейдеров",
"iris.puzzle.option.open": "Выбрать ",
"options.iris.shaderPackSelection.tooltip": "Открыть экран переключения\nи настройки наборов шейдеров",
"lambdabettergrass.option.mode.tooltip": "Включить соединение текстуры\nтравы у соседних блоков дёрна",
"lambdabettergrass.option.better_snow.tooltip": "Добавить имитацию наличия слоя снега\nили мха для неполных блоков, имеющих\nсоответствующее окружение",
"config.dynamicfps.reduce_when_unfocused.tooltip": "Уменьшать FPS в Minecraft при переходе в фон\nдля экономии энергии и системных ресурсов\n(когда игра свёрнута или активно другое окно)",
"config.dynamicfps.unfocused_fps.tooltip": "Фактическое количество\nкадров в секунду, которое\nMinecraft сможет выводить\nв фоновом режиме",
"config.dynamicfps.restore_when_hovered.tooltip": "Отключать ограничение FPS,\nкогда на окно с Minecraft\nнаведён курсор мыши",
"config.dynamicfps.run_gc_on_unfocus.tooltip": "Запускать сборщик мусора при\nпереходе игры в фон, чтобы\nосвободить пространство в ОЗУ\n(уменьшает число просадок FPS)",
"config.dynamicfps.unfocused_volume.tooltip": "Громкость звука игры в состоянии фона\n(когда активно другое окно)",
"config.dynamicfps.hidden_volume.tooltip": "Громкость звука игры в скрытом состоянии\n(когда окно свёрнуто, закрыто другим окном\nили находится на другом рабочем столе)",
"entity_texture_features.puzzle.emissive_type.brighter": "§eЯркие",
"entity_texture_features.puzzle.emissive_type.default": "§6Обычные",
"modmenu.descriptionTranslation.puzzle": "Функции улучшения внешнего вида и производительности.",
"modmenu.descriptionTranslation.puzzle-base": "Общий код всех модулей Puzzle.",
"modmenu.descriptionTranslation.puzzle-gui": "Альтернативы Optifine, объединённые в едином меню.",
"modmenu.descriptionTranslation.puzzle-models": "Больше свободы моделям блоков и предметов!",
"modmenu.descriptionTranslation.puzzle-splashscreen": "Свой экран загрузки при помощи наборов ресурсов."
}

View File

@@ -0,0 +1,42 @@
{
"puzzle.text.update_available":"Đã có bản cập nhật!",
"puzzle.screen.title":"Cài đặt Puzzle",
"puzzle.page.graphics":"Đồ họa",
"puzzle.page.resources":"Tài nguyên",
"puzzle.page.performance":"Hiệu năng",
"puzzle.page.misc":"Khác",
"puzzle.option.check_for_updates":"Kiểm tra cập nhật",
"puzzle.option.check_for_updates.tooltip":"Bật trình kiểm tra cập nhật tích hợp của Puzzle",
"puzzle.option.show_version_info":"Hiển thị thông tin phiên bản Puzzle",
"puzzle.option.show_version_info.tooltip":"Hiển thị thông tin về phiên bản \nPuzzle hiện tại và trạng thái cập nhật trên\nMàn hình Tiêu đề và Menu F3",
"puzzle.option.resourcepack_splash_screen":"Sử dụng màn hình đốm gói tài nguyên",
"puzzle.option.resourcepack_splash_screen.tooltip":"Cho phép gói tài nguyên thay đổi giao diện\nmàn hình tải/đốm\ncủa Minecraft bằng định dạng OptiFine",
"puzzle.option.better_splash_screen_blend":"Logo màn hình đốm tốt hơn",
"puzzle.option.better_splash_screen_blend.tooltip":"Thay đổi kiểu hòa trộn được sử dụng\nbởi biểu trưng trên màn hình đốm\nđể hoạt động tốt hơn với các biểu trưng có màu tùy chỉnh",
"puzzle.option.unlimited_model_rotations":"Xoay mô hình không giới hạn",
"puzzle.option.unlimited_model_rotations.tooltip":"Mở khóa xoay 360° đầy đủ trên các mô hình khối/vật phẩm tùy chỉnh",
"puzzle.option.bigger_custom_models":"Mô hình tùy chỉnh lớn hơn",
"puzzle.option.bigger_custom_models.tooltip":"Tăng giới hạn của\nkích thước mô hình khối/vật phẩm tùy chỉnh\ntừ 3x3x3 lên 5x5x5",
"puzzle.midnightconfig.title":"Cấu hình Puzzle nâng cao",
"puzzle.midnightconfig.category.gui":"GUI",
"puzzle.midnightconfig.category.features":"Tính năng",
"puzzle.midnightconfig.category.debug":"Gỡ lỗi",
"puzzle.midnightconfig.tooltip":"Tùy chọn chỉ dành cho người dùng nâng cao",
"cullleaves.puzzle.option.enabled": "Loại bỏ Lá",
"cullleaves.puzzle.option.enabled.tooltip": "Bật tính năng loại bỏ lá để nâng cao hiệu suất",
"iris.puzzle.option.enableShaders": "Bật Shader",
"iris.puzzle.option.enableShaders.tooltip": "Bật shaderpack",
"iris.puzzle.option.open": "MỞ",
"options.iris.shaderPackSelection.tooltip": "Mở một màn hình để chọn\nshaderpack và định cấu hình chúng",
"lambdabettergrass.option.mode.tooltip": "Làm cho các cạnh của\nkhối cỏ kết nối với\nkhối cỏ liền kề",
"lambdabettergrass.option.better_snow.tooltip": "Thêm một lớp tuyết/rêu hoàn toàn trực quan\nvào các khối không đầy đủ\nđược bao quanh bởi tuyết/rêu",
"config.dynamicfps.reduce_when_unfocused.tooltip": "Giảm FPS của Minecraft khi không tập trung\n(tức là một cửa sổ khác được tập trung hoặc trò chơi bị ẩn)\nđể tiết kiệm năng lượng và tài nguyên hệ thống",
"config.dynamicfps.unfocused_fps.tooltip": "Lượng khung hình mỗi giây\nMinecraft được phép\nkết xuất khi không tập trung",
"config.dynamicfps.restore_when_hovered.tooltip": "Dừng giới hạn\nFPS trong khi Minecraft được xem trước\n(tức là được di chuột trên thanh tác vụ hoặc thanh công cụ)",
"config.dynamicfps.run_gc_on_unfocus.tooltip": "Chạy trình thu gom rác trong khi\nMinecraft không tập trung vào\ngiải phóng một số RAM",
"config.dynamicfps.unfocused_volume.tooltip": "Âm lượng mà trò chơi sẽ phát\nâm thanh khi không tập trung\n(tức là một cửa sổ khác được chọn)",
"config.dynamicfps.hidden_volume.tooltip": "Âm lượng mà trò chơi sẽ phát\nâm thanh trong khi không hiển thị\n(tức là được thu nhỏ, bị che bởi các cửa sổ khác\ncũng như trên màn hình ảo khác)",
"entity_texture_features.puzzle.emissive_type.brighter": "§eSáng hơn",
"entity_texture_features.puzzle.emissive_type.default": "§6Mặc định"
}

View File

@@ -0,0 +1,42 @@
{
"puzzle.text.update_available":"有新的更新可用!",
"puzzle.screen.title":"Puzzle 設定",
"puzzle.page.graphics":"圖形",
"puzzle.page.resources":"資源",
"puzzle.page.performance":"效能",
"puzzle.page.misc":"其他",
"puzzle.option.check_for_updates":"檢查更新",
"puzzle.option.check_for_updates.tooltip":"啟用 Puzzle 內建的更新檢查器",
"puzzle.option.show_version_info":"顯示 Puzzle 版本資訊",
"puzzle.option.show_version_info.tooltip":"在標題畫面和 F3 選單上顯示\n目前 Puzzle 版本和更新狀態的資訊",
"puzzle.option.resourcepack_splash_screen":"使用資源包的啟動畫面",
"puzzle.option.resourcepack_splash_screen.tooltip":"允許資源包使用 OptiFine 格式變更\nMinecraft 的載入/啟動畫面",
"puzzle.option.better_splash_screen_blend":"更好的啟動畫面標誌混合",
"puzzle.option.better_splash_screen_blend.tooltip":"變更啟動畫面標誌使用的混合類型,\n使其更好地與自訂顏色的標誌配合使用",
"puzzle.option.unlimited_model_rotations":"無限模型旋轉",
"puzzle.option.unlimited_model_rotations.tooltip":"解鎖自訂方塊/物品模型的完整 360° 旋轉",
"puzzle.option.bigger_custom_models":"更大的自訂模型",
"puzzle.option.bigger_custom_models.tooltip":"將自訂方塊/物品模型的大小限制\n從 3×3×3 增加到 5×5×5",
"puzzle.midnightconfig.title":"Puzzle 進階設定",
"puzzle.midnightconfig.category.gui":"介面",
"puzzle.midnightconfig.category.features":"功能",
"puzzle.midnightconfig.category.internal":"內部",
"puzzle.midnightconfig.tooltip":"僅供進階使用者使用的選項",
"cullleaves.puzzle.option.enabled": "剔除樹葉",
"cullleaves.puzzle.option.enabled.tooltip": "啟用樹葉剔除以提升效能",
"iris.puzzle.option.enableShaders": "啟用光影",
"iris.puzzle.option.enableShaders.tooltip": "是否啟用光影包",
"iris.puzzle.option.open": "開啟",
"options.iris.shaderPackSelection.tooltip": "開啟一個畫面以選擇\n並設定光影包",
"lambdabettergrass.option.mode.tooltip": "使草地的側面與\n相鄰的草地連接",
"lambdabettergrass.option.better_snow.tooltip": "為被雪/苔蘚包圍的非完整方塊\n加入純粹視覺上的雪/苔蘚層",
"config.dynamicfps.reduce_when_unfocused.tooltip": "在未聚焦時降低 Minecraft 的 FPS\n例如另一個視窗被聚焦或遊戲被隱藏\n以節省電力和系統資源",
"config.dynamicfps.unfocused_fps.tooltip": "Minecraft 在未聚焦時\n允許繪製的 FPS",
"config.dynamicfps.restore_when_hovered.tooltip": "當預覽 Minecraft 時是否停止\nFPS 限制(例如,將滑鼠懸停在工作列或 Dock 上)",
"config.dynamicfps.run_gc_on_unfocus.tooltip": "在 Minecraft 未聚焦時執行垃圾回收器\n以釋放一些記憶體",
"config.dynamicfps.unfocused_volume.tooltip": "遊戲在未聚焦時播放聲音的音量\n例如選取了另一個視窗",
"config.dynamicfps.hidden_volume.tooltip": "遊戲在不可見時播放聲音的音量\n例如最小化、被其他視窗覆蓋\n或在另一個虛擬桌面上",
"entity_texture_features.puzzle.emissive_type.brighter": "§e更亮",
"entity_texture_features.puzzle.emissive_type.default": "§6預設"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

View File

@@ -3,8 +3,7 @@
"package": "net.puzzlemc.gui.mixin",
"compatibilityLevel": "JAVA_17",
"client": [
"MixinOptionsScreen",
"CemConfigAccessor"
"MixinOptionsScreen"
],
"injectors": {
"defaultRequire": 1

View File

@@ -0,0 +1,7 @@
accessWidener v1 named
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
accessible method net/minecraft/client/render/RenderLayer$MultiPhaseParameters$Builder texture (Lnet/minecraft/client/render/RenderPhase$TextureBase;)Lnet/minecraft/client/render/RenderLayer$MultiPhaseParameters$Builder;
accessible method net/minecraft/client/render/RenderLayer$MultiPhaseParameters$Builder build (Z)Lnet/minecraft/client/render/RenderLayer$MultiPhaseParameters;

View 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"
]
}

View File

@@ -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
}
}

View File

@@ -3,7 +3,8 @@
"package": "net.puzzlemc.splashscreen.mixin",
"compatibilityLevel": "JAVA_17",
"client": [
"MixinSplashScreen"
"MixinSplashScreen",
"RenderPipelinesAccessor"
],
"injectors": {
"defaultRequire": 1

109
fabric/build.gradle Normal file
View 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
}
}
}
}

View File

@@ -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);
}
}
}

View 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);
}
});
}
}

View File

@@ -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;
}
}

View File

@@ -1,9 +1,9 @@
{
"schemaVersion": 1,
"id": "puzzle-gui",
"id": "puzzle",
"version": "${version}",
"name": "Puzzle GUI",
"name": "Puzzle",
"description": "Unites optifine replacement mods in a clean & vanilla-style gui",
"authors": [
"PuzzleMC",
@@ -19,30 +19,26 @@
"icon": "assets/puzzle/icon.png",
"environment": "client",
"entrypoints": {
"client": [
"net.puzzlemc.gui.PuzzleClient"
"net.puzzlemc.fabric.PuzzleFabric"
],
"modmenu": [
"net.puzzlemc.gui.config.ModMenuIntegration"
"net.puzzlemc.fabric.modmenu.ModMenuIntegration"
]
},
"custom": {
"modmenu": {
"parent": "puzzle"
}
},
"mixins": [
"puzzle-gui.mixins.json"
"puzzle-gui.mixins.json",
"puzzle-models.mixins.json",
"puzzle-splashscreen.mixins.json",
"puzzle-predicates.mixins.json",
"puzzle-predicates_compat.mixins.json"
],
"depends": {
"fabric": "*",
"midnightlib": "*"
},
"breaks": {
"citresewn": "<=1.0.0+1.18.2",
"entity_texture_features": "<3.0.0"
"minecraft": ">=1.21"
}
}

View File

@@ -1,31 +1,47 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
org.gradle.jvmargs=-Xmx2G
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.19
yarn_mappings=1.19+build.1
loader_version=0.14.6
minecraft_version=1.21.5
supported_versions=
yarn_mappings=1.21.5+build.1
enabled_platforms=fabric,neoforge
# Mod Properties
mod_version = 1.3.3
maven_group = net.puzzlemc
archives_base_name = puzzle
mod_version = 2.1.0
maven_group = net.puzzlemc
archives_base_name = puzzle
release_type=release
curseforge_id=563977
modrinth_id=3IuO68q1
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.55.1+1.19
mod_menu_version = 2.0.13
cull_leaves_version = 2.3.3
ldl_version = 2.1.0+1.17
lbg_version = 1.2.3+1.18
iris_version = 1.18.x-v1.2.4
continuity_version = 1.0.3+1.18
animatica_version = 0.2+1.18
cit_resewn_version = 1.0.1+1.18.2
cem_version = 0.7.1
complete_config_version = 1.0.0
spruceui_version=3.3.3+1.18
midnightlib_version=0.5.2
entitytexturefeatures_version=3.0.0
# Modloaders
fabric_loader_version=0.16.10
fabric_api_version=0.119.5+1.21.5
neoforge_version=21.5.3-beta
yarn_mappings_patch_neoforge_version = 1.21+build.4
# Libraries
midnightlib_version = 1.7.0+1.21.4
modmenu_version = 13.0.0-beta.1
# 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

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.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
View 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
}
}
}
}

View File

@@ -0,0 +1 @@
loom.platform=neoforge

View File

@@ -0,0 +1,31 @@
package net.puzzlemc.neoforge;
import net.minecraft.util.Identifier;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.client.event.AddClientReloadListenersEvent;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
import net.puzzlemc.core.PuzzleCore;
import net.puzzlemc.gui.screen.PuzzleOptionsScreen;
import net.puzzlemc.splashscreen.PuzzleSplashScreen;
import static net.puzzlemc.core.PuzzleCore.MOD_ID;
@Mod(value = MOD_ID, dist = Dist.CLIENT)
public class PuzzleNeoForge {
public PuzzleNeoForge() {
PuzzleCore.initModules();
ModList.get().getModContainerById(MOD_ID).orElseThrow().registerExtensionPoint(IConfigScreenFactory.class, (client, parent) -> new PuzzleOptionsScreen(parent));
}
@EventBusSubscriber(modid = MOD_ID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public static class MidnightLibBusEvents {
@SubscribeEvent
public static void onResourceReload(AddClientReloadListenersEvent event) {
event.addListener(Identifier.of(MOD_ID, "splash_screen"), PuzzleSplashScreen.ReloadListener.INSTANCE);
}
}
}

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