18 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
71 changed files with 1983 additions and 234 deletions

View File

@@ -3,7 +3,7 @@ import groovy.json.JsonOutput
plugins {
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false
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
}
@@ -70,6 +70,7 @@ subprojects {
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}"
}

View File

@@ -1,18 +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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PuzzleCore {
public final static String MOD_ID = "puzzle";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
private static final List<PuzzleModule> MODULES = new ArrayList<>();
public static void initModules() {
PuzzleConfig.init(MOD_ID, PuzzleConfig.class);
PuzzleGui.init();
PuzzleSplashScreen.init();
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,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

@@ -6,8 +6,6 @@ import net.puzzlemc.gui.screen.widget.PuzzleWidget;
import java.util.ArrayList;
import java.util.List;
import static net.puzzlemc.core.PuzzleCore.LOGGER;
public class PuzzleApi {
public static List<PuzzleWidget> GRAPHICS_OPTIONS = new ArrayList<>();
public static List<PuzzleWidget> MISC_OPTIONS = new ArrayList<>();
@@ -17,21 +15,21 @@ public class PuzzleApi {
public static void addToGraphicsOptions(PuzzleWidget button) {
GRAPHICS_OPTIONS.add(button);
if (PuzzleConfig.debugMessages)
LOGGER.info("{} -> Graphics Options", button.descriptionText.getContent().toString());
PuzzleGui.logger().info("{} -> Graphics Options", button.descriptionText.getContent().toString());
}
public static void addToMiscOptions(PuzzleWidget button) {
MISC_OPTIONS.add(button);
if (PuzzleConfig.debugMessages)
LOGGER.info("{} -> Misc Options", button.descriptionText.getContent().toString());
PuzzleGui.logger().info("{} -> Misc Options", button.descriptionText.getContent().toString());
}
public static void addToPerformanceOptions(PuzzleWidget button) {
PERFORMANCE_OPTIONS.add(button);
if (PuzzleConfig.debugMessages)
LOGGER.info("{}- > Performance Options", button.descriptionText.getContent().toString());
PuzzleGui.logger().info("{}- > Performance Options", button.descriptionText.getContent().toString());
}
public static void addToResourceOptions(PuzzleWidget button) {
RESOURCE_OPTIONS.add(button);
if (PuzzleConfig.debugMessages)
LOGGER.info("{} -> Resource Options", button.descriptionText.getContent().toString());
PuzzleGui.logger().info("{} -> Resource Options", button.descriptionText.getContent().toString());
}
}

View File

@@ -3,6 +3,7 @@ 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;
@@ -10,23 +11,28 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.puzzlemc.splashscreen.PuzzleSplashScreen;
import org.slf4j.Logger;
import static net.puzzlemc.core.PuzzleCore.LOGGER;
public class PuzzleGui {
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");
public static void init() {
@Override
public String getModuleId() {
return "gui";
}
@Override
public void init() {
MidnightLib.hiddenMods.add("puzzle");
MinecraftClient client = MinecraftClient.getInstance();
PuzzleApi.addToMiscOptions(new PuzzleWidget(Text.of("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) -> {
client.setScreen(PuzzleConfig.getScreen(client.currentScreen, "puzzle"));
MinecraftClient.getInstance().setScreen(PuzzleConfig.getScreen(MinecraftClient.getInstance().currentScreen, "puzzle"));
}));
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("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();
@@ -57,7 +63,7 @@ public class PuzzleGui {
if (isActive("entity_texture_features")) ETFCompat.init();
if (isActive("entity_model_features")) EMFCompat.init();
} catch (Exception e) {
LOGGER.error("ETF/EMF config structure changed. Again...", e);
INSTANCE.getLogger().error("ETF/EMF config structure changed. Again...", e);
}
lateInitDone = true;
@@ -65,4 +71,7 @@ public class PuzzleGui {
public static boolean isActive(String modid) {
return PlatformFunctions.isModLoaded(modid) && !PuzzleConfig.disabledIntegrations.contains(modid);
}
public static Logger logger() {
return INSTANCE.getLogger();
}
}

View File

@@ -11,7 +11,7 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
public class BorderlessMiningCompat {
public static void init() {
PuzzleApi.addToMiscOptions(new PuzzleWidget(Text.of("Borderless Mining")));
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());

View File

@@ -13,7 +13,7 @@ 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")));
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;

View File

@@ -12,7 +12,7 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
public class ColormaticCompat {
public static void init() {
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("Colormatic")));
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;

View File

@@ -11,7 +11,7 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
public class ContinuityCompat {
public static void init() {
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("Continuity")));
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.of("Continuity")));
ContinuityConfig contConfig = ContinuityConfig.INSTANCE;
contConfig.getOptionMapView().forEach((s, option) -> {
if (s.equals("use_manual_culling")) return;

View File

@@ -11,7 +11,7 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
public class CullLeavesCompat {
public static void init() {
PuzzleApi.addToPerformanceOptions(new PuzzleWidget(Text.of("CullLeaves")));
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");

View File

@@ -13,17 +13,10 @@ 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 EMFCompat {
public static void init() {
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("entity_model_features.title")));
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.literal("\uD83D\uDC37 ").append(Text.translatable("entity_model_features.title"))));
EMFConfig emfConfig = EMF.config().getConfig();
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("entity_model_features.config.force_models"), (button) -> button.setMessage(emfConfig.attemptRevertingEntityModelsAlteredByAnotherMod ? YES : NO), (button) -> {
emfConfig.attemptRevertingEntityModelsAlteredByAnotherMod = !emfConfig.attemptRevertingEntityModelsAlteredByAnotherMod;
EMF.config().saveToFile();
}));
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) -> {

View File

@@ -16,7 +16,7 @@ import static net.puzzlemc.gui.PuzzleGui.YES;
public class ETFCompat {
public static void init() {
PuzzleApi.addToResourceOptions(new PuzzleWidget(Text.translatable("config.entity_texture_features.title")));
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;

View File

@@ -12,7 +12,7 @@ import net.puzzlemc.gui.screen.widget.PuzzleWidget;
public class IrisCompat {
public static void init() {
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.of("Iris")));
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());

View File

@@ -12,7 +12,7 @@ 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("LambdaBetterGrass")));
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

@@ -13,10 +13,9 @@ public class LDLCompat {
public static void init() {
DynamicLightsConfig ldlConfig = LambDynLights.get().config;
PuzzleApi.addToGraphicsOptions(new PuzzleWidget(Text.of("LambDynamicLights")));
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("lambdynlights.option.light_sources.block_entities")), (button) -> button.setMessage(ldlConfig.getBlockEntitiesLightSource().get() ? YES : NO), (button) -> ldlConfig.getBlockEntitiesLightSource().set(!ldlConfig.getBlockEntitiesLightSource().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

@@ -86,7 +86,7 @@ public class PuzzleOptionsScreen extends Screen {
prevTab = tabManager.getCurrentTab();
this.list.clear();
fillList();
list.setScrollAmount(0);
list.setScrollY(0);
}
}
}

View File

@@ -11,13 +11,13 @@ 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;
import static net.puzzlemc.core.PuzzleCore.LOGGER;
@Environment(EnvType.CLIENT)
public class PuzzleOptionListWidget extends MidnightConfig.MidnightConfigListWidget {
TextRenderer textRenderer;
@@ -31,6 +31,7 @@ public class PuzzleOptionListWidget extends MidnightConfig.MidnightConfigListWid
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)
@@ -40,12 +41,24 @@ public class PuzzleOptionListWidget extends MidnightConfig.MidnightConfigListWid
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
LOGGER.warn("Button {} is missing the buttonType variable. This shouldn't happen!", button);
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) {
var entry = new MidnightConfig.ButtonEntry(buttons, text, new MidnightConfig.EntryInfo());
entry.centered = buttons.isEmpty();
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) {

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

@@ -1,16 +1,28 @@
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;
@@ -23,37 +35,71 @@ import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import static net.puzzlemc.core.PuzzleCore.LOGGER;
import static net.puzzlemc.core.PuzzleCore.MOD_ID;
public class PuzzleSplashScreen {
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 final MinecraftClient client = MinecraftClient.getInstance();
private static MinecraftClient client = MinecraftClient.getInstance();
private static boolean keepBackground = false;
private static RenderLayer CUSTOM_LOGO_LAYER;
public static void init() {
if (!CONFIG_PATH.exists()) { // Run when config directory is nonexistent //
if (CONFIG_PATH.mkdir()) { // Create our custom config directory //
if (Util.getOperatingSystem().equals(Util.OperatingSystem.WINDOWS)) {
@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();
public static class ReloadListener implements SynchronousResourceReloader {
public static final ReloadListener INSTANCE = new ReloadListener();
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));
}
}
private ReloadListener() {}
@Override
public void reload(ResourceManager manager) {
public void reloadResources(ResourceManager manager) {
client = MinecraftClient.getInstance();
if (PuzzleConfig.resourcepackSplashScreen) {
PuzzleSplashScreen.resetColors();
client.getTextureManager().registerTexture(LOGO, new LogoTexture(LOGO));
@@ -88,7 +134,7 @@ public class PuzzleSplashScreen {
}
} catch (Exception e) {
LOGGER.error("Error occurred while loading color.properties {}", id.toString(), e);
getLogger().error("Error occurred while loading color.properties {}", id.toString(), e);
}
});
AtomicInteger logoCount = new AtomicInteger();
@@ -99,28 +145,29 @@ public class PuzzleSplashScreen {
if (logoCount.get() > 0) PuzzleConfig.hasCustomSplashScreen = true;
logoCount.getAndIncrement();
} catch (Exception e) {
LOGGER.error("Error occurred while loading custom minecraft logo {}", id.toString(), 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(NativeImage.read(input)));
client.getTextureManager().registerTexture(BACKGROUND, new NativeImageBackedTexture(() -> "splash_screen_background", NativeImage.read(input)));
keepBackground = true;
PuzzleConfig.hasCustomSplashScreen = true;
} catch (Exception e) {
LOGGER.error("Error occurred while loading custom splash background {}", id.toString(), e);
getLogger().error("Error occurred while loading custom splash background {}", id.toString(), e);
}
});
if (!keepBackground) {
try {
Files.delete(BACKGROUND_TEXTURE);
} catch (Exception ignored) {}
} catch (Exception ignored) {
}
}
keepBackground = false;
PuzzleConfig.write(MOD_ID);
}
buildRenderLayer();
}
}
@@ -137,14 +184,15 @@ public class PuzzleSplashScreen {
public static class LogoTexture extends ResourceTexture {
public LogoTexture(Identifier logo) { super(logo); }
protected TextureData loadTextureData(ResourceManager resourceManager) {
@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();
TextureData var6;
TextureContents var6;
try {
var6 = new TextureData(new TextureResourceMetadata(true, true), NativeImage.read(inputStream));
var6 = new TextureContents(NativeImage.read(inputStream), new TextureResourceMetadata(true, true));
} finally {
if (inputStream != null) {
inputStream.close();
@@ -152,7 +200,7 @@ public class PuzzleSplashScreen {
}
return var6;
} catch (IOException var18) {
return new TextureData(var18);
return TextureContents.createMissing();
}
}
}
@@ -161,13 +209,18 @@ public class PuzzleSplashScreen {
public DynamicLogoTexture() {
super(LOGO);
}
protected TextureData loadTextureData(ResourceManager resourceManager) {
@Override
public TextureContents loadContents(ResourceManager resourceManager) {
try {
InputStream input = new FileInputStream(String.valueOf(PuzzleSplashScreen.LOGO_TEXTURE));
return new TextureData(new TextureResourceMetadata(true, true), NativeImage.read(input));
return new TextureContents(NativeImage.read(input), new TextureResourceMetadata(true, true));
} catch (IOException e) {
LOGGER.error("Encountered an error during logo loading: ", e);
return TextureData.load(resourceManager, LOGO);
INSTANCE.getLogger().error("Encountered an error during logo loading: ", e);
try {
return TextureContents.load(resourceManager, LOGO);
} catch (IOException ex) {
return TextureContents.createMissing();
}
}
}
}

View File

@@ -1,7 +1,7 @@
package net.puzzlemc.splashscreen.mixin;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
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;
@@ -9,6 +9,7 @@ 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;
@@ -25,9 +26,9 @@ 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.core.PuzzleCore.LOGGER;
import static net.puzzlemc.splashscreen.PuzzleSplashScreen.BACKGROUND;
@Mixin(value = SplashOverlay.class, priority = 2000)
@@ -42,16 +43,16 @@ public abstract class MixinSplashScreen extends Overlay {
return 0;
}
@Inject(method = "init(Lnet/minecraft/client/MinecraftClient;)V", at = @At("TAIL"))
private static void puzzle$initSplashscreen(MinecraftClient client, CallbackInfo ci) { // Load our custom textures at game start //
@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()) {
client.getTextureManager().registerTexture(LOGO, new PuzzleSplashScreen.DynamicLogoTexture());
textureManager.registerTexture(LOGO, new PuzzleSplashScreen.DynamicLogoTexture());
}
if (PuzzleSplashScreen.BACKGROUND_TEXTURE.toFile().exists()) {
try {
InputStream input = new FileInputStream(String.valueOf(PuzzleSplashScreen.BACKGROUND_TEXTURE));
client.getTextureManager().registerTexture(BACKGROUND, new NativeImageBackedTexture(NativeImage.read(input)));
textureManager.registerTexture(BACKGROUND, new NativeImageBackedTexture(() -> "splash_screen_background", NativeImage.read(input)));
} catch (IOException ignored) {}
}
}
@@ -61,23 +62,14 @@ public abstract class MixinSplashScreen extends Overlay {
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;
}
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/ColorHelper;getWhite(F)I", shift = At.Shift.AFTER))
private void puzzle$betterBlend(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
if (PuzzleConfig.resourcepackSplashScreen) {
if (PuzzleConfig.disableBlend) RenderSystem.disableBlend();
else if (PuzzleConfig.customBlendFunction.size() == 4) {
try {
RenderSystem.blendFuncSeparate(
GlStateManager.SrcFactor.valueOf(PuzzleConfig.customBlendFunction.get(0)),
GlStateManager.DstFactor.valueOf(PuzzleConfig.customBlendFunction.get(1)),
GlStateManager.SrcFactor.valueOf(PuzzleConfig.customBlendFunction.get(2)),
GlStateManager.DstFactor.valueOf(PuzzleConfig.customBlendFunction.get(3)));
} catch (Exception e) {
LOGGER.error("Incorrect blend function defined in color.properties: {}{}", PuzzleConfig.customBlendFunction, e.getMessage());
}
}
}
@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) {
@@ -90,14 +82,11 @@ public abstract class MixinSplashScreen extends Overlay {
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;
RenderSystem.enableBlend();
RenderSystem.blendEquation(32774);
RenderSystem.defaultBlendFunc();
context.getMatrices().translate(0, 0, 1f);
context.drawTexture(RenderLayer::getGuiTextured, BACKGROUND, 0, 0, 0, 0, width, height, width, height, ColorHelper.getWhite(s));
RenderSystem.defaultBlendFunc();
RenderSystem.disableBlend();
}
}
@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);
@@ -105,7 +94,6 @@ public abstract class MixinSplashScreen extends Overlay {
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);
RenderSystem.disableBlend();
context.fill(minX, minY, maxX, maxY, withAlpha(PuzzleConfig.progressBarBackgroundColor, m));
}

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

@@ -1,6 +1,6 @@
{
"puzzle.text.update_available":"Uma atualização está disponível!",
"puzzle.screen.title":"Puzzle Definições",
"puzzle.screen.title":"Configurações do Puzzle",
"puzzle.page.graphics":"Gráficas",
"puzzle.page.resources":"Recursos",
"puzzle.page.performance":"Desempenho",
@@ -8,16 +8,19 @@
"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\na tela de título e o menu F3",
"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":"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":"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.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",
@@ -34,6 +37,6 @@
"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.brighter": "§eMais Brilhante",
"entity_texture_features.puzzle.emissive_type.default": "§6Padrão"
}

View File

@@ -1,39 +1,42 @@
{
"puzzle.text.update_available": "有新版本可供升級",
"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.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 格式\n更改 Minecraft 的載入畫面",
"puzzle.option.better_splash_screen_blend": "更好的載入畫面圖示混和",
"puzzle.option.better_splash_screen_blend.tooltip": "更改激活畫面標誌的混合方式\n以便更好地與自訂顏色的標誌配合使用",
"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.unlimited_model_rotations.tooltip":"解鎖自訂方塊/物品模型完整 360° 旋轉",
"puzzle.option.bigger_custom_models":"更大的自訂模型",
"puzzle.option.bigger_custom_models.tooltip": "增加將自訂方塊物品模型大小\n從 3x3x3 增加到 5x5x5",
"puzzle.option.bigger_custom_models.tooltip":"將自訂方塊/物品模型大小限制\n從 3×3×3 增加到 5×5×5",
"puzzle.midnightconfig.title":"Puzzle 進階設定",
"puzzle.midnightconfig.tooltip": "給予進階使用者使用的選項",
"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": "開啟選擇畫面光影包和設定",
"lambdabettergrass.option.mode.tooltip": "讓草的側面連接相鄰的草",
"lambdabettergrass.option.better_snow.tooltip": "對雪塊/苔蘚方塊被包圍的完整方塊\n增加視覺效果",
"config.dynamicfps.reduce_when_unfocused.tooltip": " Minecraft 失去焦點時限制 FPS\n如切換到其他視窗或是遊戲被隱藏)\n以節省電和系統資源",
"config.dynamicfps.unfocused_fps.tooltip": "Minecraft 失去焦點時允許的最大 FPS",
"config.dynamicfps.restore_when_hovered.tooltip": "開啟或關閉預覽 Mineceraft 時是否停止 FPS 限制\n如停留在工作列或 Dock",
"config.dynamicfps.run_gc_on_unfocus.tooltip": " Minecraft 失去焦點時執行垃圾清理\n以減少一些記憶體",
"config.dynamicfps.unfocused_volume.tooltip": "當 Minecraft 失去焦點時撥放的音量\n如選擇了另一個視窗)",
"config.dynamicfps.hidden_volume.tooltip": "遊戲在不可見時應該播放的音量\n最小化、被其他視窗覆蓋或在另一個虛擬桌面上)",
"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預設"
}

View File

@@ -1,2 +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

View File

@@ -90,7 +90,8 @@ unifiedPublishing {
curseforge {
token = CURSEFORGE_TOKEN
id = rootProject.curseforge_id
gameVersions.addAll "Java 21", project.minecraft_version, project.supported_versions
gameVersions.addAll "Java 21", project.minecraft_version
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
}
}
@@ -100,7 +101,8 @@ unifiedPublishing {
token = MODRINTH_TOKEN
id = rootProject.modrinth_id
version = "$rootProject.version-$project.name"
gameVersions.addAll project.minecraft_version, project.supported_versions
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

@@ -3,16 +3,17 @@ 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;
import net.puzzlemc.splashscreen.PuzzleSplashScreen;
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
@@ -21,7 +22,7 @@ public class PuzzleFabric implements ClientModInitializer {
}
@Override
public void reload(ResourceManager manager) {
PuzzleSplashScreen.ReloadListener.INSTANCE.reload(manager);
PuzzleCore.PuzzleResourceManager.INSTANCE.reload(manager);
}
});
}

View File

@@ -32,7 +32,9 @@
"mixins": [
"puzzle-gui.mixins.json",
"puzzle-models.mixins.json",
"puzzle-splashscreen.mixins.json"
"puzzle-splashscreen.mixins.json",
"puzzle-predicates.mixins.json",
"puzzle-predicates_compat.mixins.json"
],
"depends": {

View File

@@ -1,13 +1,13 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx2G
minecraft_version=1.21.3
supported_versions=1.21.2
yarn_mappings=1.21.3+build.2
minecraft_version=1.21.5
supported_versions=
yarn_mappings=1.21.5+build.1
enabled_platforms=fabric,neoforge
# Mod Properties
mod_version = 2.0.3
mod_version = 2.1.0
maven_group = net.puzzlemc
archives_base_name = puzzle
release_type=release
@@ -15,19 +15,19 @@ curseforge_id=563977
modrinth_id=3IuO68q1
# Modloaders
fabric_loader_version=0.16.9
fabric_api_version=0.107.0+1.21.3
fabric_loader_version=0.16.10
fabric_api_version=0.119.5+1.21.5
neoforge_version=21.3.11-beta
neoforge_version=21.5.3-beta
yarn_mappings_patch_neoforge_version = 1.21+build.4
# Libraries
midnightlib_version = 1.6.4
modmenu_version = 12.0.0-beta.1
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 = 2.3.2+1.20.1
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
@@ -39,8 +39,8 @@ 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.2.3
etf_version=6.2.2
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

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -96,7 +96,8 @@ unifiedPublishing {
curseforge {
token = CURSEFORGE_TOKEN
id = rootProject.curseforge_id
gameVersions.addAll "Java 21", project.minecraft_version, project.supported_versions
gameVersions.addAll "Java 21", project.minecraft_version
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
}
}
@@ -106,7 +107,8 @@ unifiedPublishing {
token = MODRINTH_TOKEN
id = rootProject.modrinth_id
version = "$rootProject.version-$project.name"
gameVersions.addAll project.minecraft_version, project.supported_versions
gameVersions.addAll project.minecraft_version
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
}
}
}

View File

@@ -1,11 +1,12 @@
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.RegisterClientReloadListenersEvent;
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;
@@ -23,8 +24,8 @@ public class PuzzleNeoForge {
@EventBusSubscriber(modid = MOD_ID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public static class MidnightLibBusEvents {
@SubscribeEvent
public static void onResourceReload(RegisterClientReloadListenersEvent event) {
event.registerReloadListener(PuzzleSplashScreen.ReloadListener.INSTANCE);
public static void onResourceReload(AddClientReloadListenersEvent event) {
event.addListener(Identifier.of(MOD_ID, "splash_screen"), PuzzleSplashScreen.ReloadListener.INSTANCE);
}
}
}