From ae260556b2a26201cad30ef3a8bab882c9816027 Mon Sep 17 00:00:00 2001 From: Tschipp <11649893+Tschipp@users.noreply.github.com> Date: Sat, 4 Jan 2025 00:32:09 +0100 Subject: [PATCH] Updated to 1.21.4, Added support for Cloth Config --- Common/build.gradle | 2 + .../client/render/CarriedObjectRender.java | 26 +++-- .../client/render/CarryRenderHelper.java | 59 +++++++++- .../carryon/common/carry/PickupHandler.java | 2 +- .../carryon/common/config/CarryConfig.java | 38 +++--- .../scripting/ScriptReloadListener.java | 8 +- .../carryon/compat/ClothConfigCompat.java | 108 ++++++++++++++++++ .../carryon/config/AnnotationData.java | 6 +- .../tschipp/carryon/config/BuiltCategory.java | 5 +- .../tschipp/carryon/config/BuiltConfig.java | 2 +- .../tschipp/carryon/config/ConfigLoader.java | 4 +- .../tschipp/carryon/config/PropertyData.java | 62 +++++++++- .../carryon/config/annotations/Category.java | 1 + .../carryon/config/annotations/Property.java | 3 +- .../tschipp/carryon/mixin/InventoryMixin.java | 2 +- Fabric/build.gradle | 9 +- .../compat/ClothConfigCompatFabric.java | 16 +++ .../tschipp/carryon/compat/ModMenuCompat.java | 17 +++ .../config/fabric/ConfigLoaderImpl.java | 63 +++++++--- Fabric/src/main/resources/fabric.mod.json | 3 + Forge/build.gradle | 2 + .../java/tschipp/carryon/CarryOnForge.java | 2 +- .../compat/ClothConfigCompatForge.java | 17 +++ .../config/forge/ConfigLoaderImpl.java | 42 +++---- .../carryon/events/ModClientEvents.java | 17 +++ .../carryon/mixin/ParticleEngineMixin.java | 7 +- NeoForge/build.gradle | 12 +- .../java/tschipp/carryon/CarryOnNeoForge.java | 1 + .../carryon/CarryOnNeoForgeClient.java | 27 +++++ .../carryon/compat/ClothConfigCompatNeo.java | 26 +++++ .../config/neoforge/ConfigLoaderImpl.java | 38 +++--- build.gradle | 12 ++ gradle.properties | 27 ++--- 33 files changed, 533 insertions(+), 133 deletions(-) create mode 100644 Common/src/main/java/tschipp/carryon/compat/ClothConfigCompat.java create mode 100644 Fabric/src/main/java/tschipp/carryon/compat/ClothConfigCompatFabric.java create mode 100644 Fabric/src/main/java/tschipp/carryon/compat/ModMenuCompat.java create mode 100644 Forge/src/main/java/tschipp/carryon/compat/ClothConfigCompatForge.java create mode 100644 NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForgeClient.java create mode 100644 NeoForge/src/main/java/tschipp/carryon/compat/ClothConfigCompatNeo.java diff --git a/Common/build.gradle b/Common/build.gradle index dcf0558..15d6372 100644 --- a/Common/build.gradle +++ b/Common/build.gradle @@ -26,6 +26,8 @@ dependencies { implementation group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1' implementation("io.github.llamalad7:mixinextras-common:${mixinextras_version}") annotationProcessor("io.github.llamalad7:mixinextras-common:${mixinextras_version}") + + compileOnly("me.shedaniel.cloth:cloth-config-neoforge:${cloth_config_version}") } processResources { diff --git a/Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java b/Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java index 168734c..77e6051 100644 --- a/Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java +++ b/Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java @@ -31,6 +31,8 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource.BufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.world.entity.Entity; @@ -38,6 +40,7 @@ import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; @@ -106,6 +109,7 @@ public class CarriedObjectRender RenderSystem.disableCull(); CarryOnData carry = CarryOnDataManager.getCarryData(player); + ItemStackRenderState renderState = new ItemStackRenderState(); if (Constants.CLIENT_CONFIG.facePlayer != CarryRenderHelper.isChest(state.getBlock())) { matrix.mulPose(Axis.YP.rotationDegrees(180)); @@ -117,11 +121,13 @@ public class CarriedObjectRender if(carry.getActiveScript().isPresent()) CarryRenderHelper.performScriptTransformation(matrix, carry.getActiveScript().get()); - RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); + + ItemStack renderStack = CarryRenderHelper.getRenderItemStack(player); + Minecraft.getInstance().getItemModelResolver().updateForTopItem(renderState, renderStack, ItemDisplayContext.NONE, false, player.level(), null, 0); + renderState.render(matrix, buffer, light, OverlayTexture.NO_OVERLAY); + - ItemStack stack = new ItemStack(state.getBlock().asItem()); - BakedModel model = CarryRenderHelper.getRenderBlock(player); - CarryRenderHelper.renderBakedModel(stack, matrix, buffer, light, model); RenderSystem.enableCull(); RenderSystem.disableBlend(); @@ -196,6 +202,7 @@ public class CarriedObjectRender RenderSystem.disableDepthTest(); BufferSource buffer = MultiBufferSource.immediateWithBuffers(builders, builders.get(RenderType.glint())); + ItemStackRenderState renderState = new ItemStackRenderState(); for (Player player : level.players()) { @@ -213,18 +220,17 @@ public class CarriedObjectRender CarryRenderHelper.applyBlockTransformations(player, partialticks, matrix, state.getBlock()); - ItemStack tileItem = new ItemStack(state.getBlock().asItem()); - BakedModel model = CarryRenderHelper.getRenderBlock(player); + ItemStack renderItemStack = CarryRenderHelper.getRenderItemStack(player); + + mc.getItemModelResolver().updateForTopItem(renderState, renderItemStack, ItemDisplayContext.NONE, false, level, null, 0); - //ModelOverridesHandler.hasCustomOverrideModel(state, tag) ? ModelOverridesHandler.getCustomOverrideModel(state, tag, level, player) : tileItem.isEmpty() ? mc.getBlockRenderer().getBlockModel(state) : mc.getItemRenderer().getModel(tileItem, level, player, 0); -// Optional res = carry.getActiveScript(); if (res.isPresent()) { CarryOnScript script = res.get(); CarryRenderHelper.performScriptTransformation(matrix, script); } - RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); RenderSystem.enableCull(); PoseStack.Pose p = matrix.last(); @@ -234,7 +240,7 @@ public class CarriedObjectRender RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - CarryRenderHelper.renderBakedModel(tileItem, copy, buffer, light, model); + renderState.render(copy, buffer, light, OverlayTexture.NO_OVERLAY); matrix.popPose(); } else if (carry.isCarrying(CarryType.ENTITY)) { diff --git a/Common/src/main/java/tschipp/carryon/client/render/CarryRenderHelper.java b/Common/src/main/java/tschipp/carryon/client/render/CarryRenderHelper.java index 23d1734..8ed979a 100644 --- a/Common/src/main/java/tschipp/carryon/client/render/CarryRenderHelper.java +++ b/Common/src/main/java/tschipp/carryon/client/render/CarryRenderHelper.java @@ -24,7 +24,9 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.item.ItemStackRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.registries.BuiltInRegistries; @@ -249,18 +251,64 @@ public class CarryRenderHelper matrix.scale((float) scale.x, (float) scale.y, (float) scale.z); } - - + /* + @Deprecated public static void renderBakedModel(ItemStack stack, PoseStack matrix, MultiBufferSource buffer, int light, BakedModel model) { + ItemStackRenderState state = new ItemStackRenderState(); + try { + + + ItemStackRenderState.LayerRenderState layer = state.newLayer(); + if(stack.hasFoil()) + layer.setFoilType(ItemStackRenderState.FoilType.STANDARD); + layer.setupBlockModel(model, RenderType.translucent()); + + state.render(matrix, buffer, light, OverlayTexture.NO_OVERLAY); + + ItemRenderer renderer = Minecraft.getInstance().getItemRenderer(); + renderer.renderStatic(stack, ItemDisplayContext.NONE, light, OverlayTexture.NO_OVERLAY, matrix, buffer, null, model, 0); renderer.render(stack, ItemDisplayContext.NONE, false, matrix, buffer, light, OverlayTexture.NO_OVERLAY, model); + } catch (Exception e) { } } + */ + + public static ItemStack getRenderItemStack(Player player) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + BlockState state = carry.getBlock().getBlock().defaultBlockState(); + if(carry.getActiveScript().isPresent()) + { + ScriptRender render = carry.getActiveScript().get().scriptRender(); + if(render.renderNameBlock().isPresent()) + { + state = BuiltInRegistries.BLOCK.get(render.renderNameBlock().get()).get().value().defaultBlockState(); + } + } + + ItemStack renderStack = ItemStack.EMPTY; + + Optional ov = ModelOverrideHandler.getModelOverride(state, carry.getContentNbt()); + if(ov.isPresent()) + { + var renderObj = ov.get().getRenderObject(); + if(renderObj.right().isPresent()) + state = renderObj.right().get(); + else if (renderObj.left().isPresent()) + renderStack = renderObj.left().get(); + } + + if(renderStack.isEmpty()) + renderStack = new ItemStack(state.getBlock()); + + return renderStack; + } public static BlockState getRenderState(Player player) { @@ -286,10 +334,14 @@ public class CarryRenderHelper return state; } + + /* + @Deprecated public static BakedModel getRenderBlock(Player player) { CarryOnData carry = CarryOnDataManager.getCarryData(player); ItemRenderer renderer = Minecraft.getInstance().getItemRenderer(); + Minecraft.getInstance().getModelManager().specialBlockModelRenderer().get(). BlockState state = getRenderState(player); BakedModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(state); @@ -308,6 +360,7 @@ public class CarryRenderHelper return model; } + */ public static Entity getRenderEntity(Player player) { @@ -319,7 +372,7 @@ public class CarryRenderHelper CarryOnScript script = carry.getActiveScript().get(); ScriptRender render = script.scriptRender(); if(render.renderNameEntity().isPresent()) - entity = BuiltInRegistries.ENTITY_TYPE.get(render.renderNameEntity().get()).get().value().create(player.level(), EntitySpawnReason.BUCKET); + entity = BuiltInRegistries.ENTITY_TYPE.get(render.renderNameEntity().get()).get().value().create(player.level(), EntitySpawnReason.EVENT); if(render.renderNBT().isPresent()) entity.load(render.renderNBT().get()); diff --git a/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java b/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java index 1cc78fa..600f3d6 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java @@ -237,7 +237,7 @@ public class PickupHandler { entity.ejectPassengers(); entity.stopRiding(); if (entity instanceof Animal animal) { - animal.dropLeash(true, true); + animal.dropLeash(); } if(result.isPresent()) diff --git a/Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java b/Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java index 59289d5..3da321b 100644 --- a/Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java +++ b/Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java @@ -38,7 +38,7 @@ public class CarryConfig ) public Settings settings = new Settings(); - @Category("settings") + @Category(value="settings", translation = "carryon.category.settings") public static class Settings { @Property( @@ -171,7 +171,8 @@ public class CarryConfig @Property( type = PropertyType.STRING_ARRAY, - description = "Usually all the block state information is retained when placing a block that was picked up. But some information is changed to a modified property, like rotation or orientation. In this list, add additional properties that should NOT be saved and instead be updated when placed. Format: modid:block[propertyname]. Note: You don't need to add an entry for every subtype of a same block. For example, we only add an entry for one type of slab, but the change is applied to all slabs." + description = "Usually all the block state information is retained when placing a block that was picked up. But some information is changed to a modified property, like rotation or orientation. In this list, add additional properties that should NOT be saved and instead be updated when placed. Format: modid:block[propertyname]. Note: You don't need to add an entry for every subtype of a same block. For example, we only add an entry for one type of slab, but the change is applied to all slabs.", + validationRegex = "([a-zA-Z0-9_]+:[a-zA-Z0-9_]+)\\[([a-zA-Z0-9_,]+)\\]" ) public String[] placementStateExceptions = { "minecraft:chest[type]", @@ -204,24 +205,27 @@ public class CarryConfig //Whitelist public Whitelist whitelist = new Whitelist(); - @Category("whitelist") + @Category(value="whitelist", translation = "carryon.category.whitelist") public static class Whitelist { @Property( type = PropertyType.STRING_ARRAY, - description = "Entities that CAN be picked up (useWhitelistEntities must be true)" + description = "Entities that CAN be picked up (useWhitelistEntities must be true)", + validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)" ) public String[] allowedEntities = {}; @Property( type = PropertyType.STRING_ARRAY, - description = "Blocks that CAN be picked up (useWhitelistBlocks must be true)" + description = "Blocks that CAN be picked up (useWhitelistBlocks must be true)", + validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)" ) public String[] allowedBlocks = {}; @Property( type = PropertyType.STRING_ARRAY, - description = "Entities that CAN have other entities stacked on top of them (useWhitelistStacking must be true)" + description = "Entities that CAN have other entities stacked on top of them (useWhitelistStacking must be true)", + validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)" ) public String[] allowedStacking = {}; } @@ -233,12 +237,13 @@ public class CarryConfig ) public Blacklist blacklist = new Blacklist(); - @Category("blacklist") + @Category(value="blacklist", translation = "carryon.category.blacklist") public static class Blacklist { @Property( type = PropertyType.STRING_ARRAY, - description = "Blocks that cannot be picked up" + description = "Blocks that cannot be picked up", + validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)" ) public String[] forbiddenTiles = { "#forge:immovable", "#forge:relocation_not_supported", "#neoforge:immovable", "#neoforge:relocation_not_supported", "minecraft:end_portal", "minecraft:piston_head", @@ -283,7 +288,8 @@ public class CarryConfig @Property( type = PropertyType.STRING_ARRAY, - description = "Entities that cannot be picked up" + description = "Entities that cannot be picked up", + validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)" ) public String[] forbiddenEntities = { "#c:capturing_not_supported", "#c:teleporting_not_supported", @@ -298,7 +304,8 @@ public class CarryConfig @Property( type = PropertyType.STRING_ARRAY, - description = "Entities that cannot have other entities stacked on top of them" + description = "Entities that cannot have other entities stacked on top of them", + validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)" ) public String[] forbiddenStacking = { "minecraft:horse" @@ -312,18 +319,20 @@ public class CarryConfig ) public CustomPickupConditions customPickupConditions = new CustomPickupConditions(); - @Category("customPickupConditions") + @Category(value="customPickupConditions", translation = "carryon.category.custompickupconditions") public static class CustomPickupConditions { @Property( type = PropertyType.STRING_ARRAY, - description = "Custom Pickup Conditions for Blocks" + description = "Custom Pickup Conditions for Blocks", + validationRegex = "([a-zA-Z0-9_*\\-:]+(?:\\[[^\\]]*\\])?)\\(([\\w_]+)\\)" ) public String[] customPickupConditionsBlocks = {}; @Property( type = PropertyType.STRING_ARRAY, - description = "Custom Pickup Conditions for Entities" + description = "Custom Pickup Conditions for Entities", + validationRegex = "([a-zA-Z0-9_*\\-:]+(?:\\[[^\\]]*\\])?)\\(([\\w_]+)\\)" ) public String[] customPickupConditionsEntities = {}; } @@ -347,7 +356,8 @@ public class CarryConfig @Property( type = PropertyType.STRING_ARRAY, - description = "Model Overrides based on NBT or Meta. Advanced users only! Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Model-Override-Config" + description = "Model Overrides based on NBT or Meta. Advanced users only! Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Model-Override-Config", + validationRegex = "([a-zA-Z0-9_]+:[a-zA-Z0-9_]+(?:\\[[^\\]]*\\])?(?:\\{[^}]*\\})?)(?:;(\\d+))?->(?:\\((item|block)\\))?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+(?:\\[[^\\]]*\\])?(?:\\{[^}]*\\})?)(?:;(\\d+))?" ) public String[] modelOverrides = { "minecraft:redstone_wire->(item)minecraft:redstone", diff --git a/Common/src/main/java/tschipp/carryon/common/scripting/ScriptReloadListener.java b/Common/src/main/java/tschipp/carryon/common/scripting/ScriptReloadListener.java index 1424213..0c998ac 100644 --- a/Common/src/main/java/tschipp/carryon/common/scripting/ScriptReloadListener.java +++ b/Common/src/main/java/tschipp/carryon/common/scripting/ScriptReloadListener.java @@ -29,11 +29,13 @@ import com.mojang.serialization.JsonOps; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; +import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; import net.minecraft.util.profiling.ProfilerFiller; +import org.jetbrains.annotations.NotNull; import tschipp.carryon.Constants; import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.networking.clientbound.ClientboundSyncScriptsPacket; @@ -46,11 +48,11 @@ public class ScriptReloadListener extends SimpleJsonResourceReloadListener scripts, ResourceManager resourceManager, ProfilerFiller profilerFiller) + protected void apply(Map scripts, @NotNull ResourceManager resourceManager, @NotNull ProfilerFiller profilerFiller) { ScriptManager.SCRIPTS.clear(); @@ -59,7 +61,7 @@ public class ScriptReloadListener extends SimpleJsonResourceReloadListener Long.compare(s2.priority(), s1.priority())); + ScriptManager.SCRIPTS.sort((s1, s2) -> Long.compare(s2.priority(), s1.priority())); } diff --git a/Common/src/main/java/tschipp/carryon/compat/ClothConfigCompat.java b/Common/src/main/java/tschipp/carryon/compat/ClothConfigCompat.java new file mode 100644 index 0000000..554ef44 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/compat/ClothConfigCompat.java @@ -0,0 +1,108 @@ +package tschipp.carryon.compat; + +import me.shedaniel.clothconfig2.api.ConfigBuilder; +import me.shedaniel.clothconfig2.api.ConfigCategory; +import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; +import me.shedaniel.clothconfig2.impl.builders.SubCategoryBuilder; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import tschipp.carryon.config.AnnotationData; +import tschipp.carryon.config.BuiltCategory; +import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.config.ConfigLoader; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +public record ClothConfigCompat(BuiltConfig client, BuiltConfig common, Runnable onSave) { + + public static Screen getConfigScreen(BuiltConfig client, BuiltConfig common, Screen parentScreen, Runnable onSave) { + ConfigBuilder builder = ConfigBuilder.create() + .setParentScreen(parentScreen) + .setTitle(Component.translatable("key.carry.category")); + + buildConfigType(client, builder, "Client Config"); + buildConfigType(common, builder, "Common Config"); + + builder.setSavingRunnable(onSave); + + return builder.build(); + } + + private static void buildConfigType(BuiltConfig cfg, ConfigBuilder builder, String name) { + ConfigCategory configCategory = builder.getOrCreateCategory(Component.literal(name)); + buildProperties(cfg, configCategory, builder, null); + } + + + private static void buildCategory(BuiltCategory category, ConfigCategory categoryBuilder, ConfigBuilder builder) { + ConfigEntryBuilder entryBuilder = builder.entryBuilder(); + SubCategoryBuilder subBuilder = entryBuilder.startSubCategory(Component.translatable(category.translation)); + + buildProperties(category, categoryBuilder, builder, subBuilder); + } + + private static void buildProperties(BuiltCategory category, ConfigCategory categoryBuilder, ConfigBuilder builder, @Nullable SubCategoryBuilder subBuilder) { + category.categories.forEach(cat -> { + buildCategory(cat, categoryBuilder, builder); + }); + + ConfigEntryBuilder entryBuilder = builder.entryBuilder(); + + category.properties.forEach(propertyData -> { + try { + AnnotationData data = propertyData.getData(); + var entry = + switch (data.type()) { + case BOOLEAN -> + entryBuilder.startBooleanToggle(Component.literal(propertyData.getField().getName()), propertyData.getBoolean()) + .setTooltip(Component.literal(data.description())) + .setDefaultValue(propertyData.getDefaultBoolean()) + .setSaveConsumer((Consumer) propertyData.getSetter()) + .build(); + case INT -> + entryBuilder.startIntField(Component.literal(propertyData.getField().getName()), propertyData.getInt()) + .setTooltip(Component.literal(data.description())) + .setDefaultValue(propertyData.getDefaultInt()) + .setMin(data.min()) + .setMax(data.max()) + .setSaveConsumer((Consumer) propertyData.getSetter()) + .build(); + case DOUBLE -> + entryBuilder.startDoubleField(Component.literal(propertyData.getField().getName()), propertyData.getDouble()) + .setTooltip(Component.literal(data.description())) + .setDefaultValue(propertyData.getDefaultDouble()) + .setMin(data.minD()) + .setMax(data.maxD()) + .setSaveConsumer((Consumer) propertyData.getSetter()) + .build(); + case STRING_ARRAY -> + entryBuilder.startStrList(Component.literal(propertyData.getField().getName()), List.of(propertyData.getDefaultStringArray())) + .setTooltip(Component.literal(data.description())) + .setDefaultValue(List.of(propertyData.getDefaultStringArray())) + .setCellErrorSupplier(str -> str.matches(data.validationRegex()) ? Optional.empty() : Optional.of(Component.literal("Invalid Format"))) + .setSaveConsumer((Consumer>) propertyData.getSetter()) + .build(); + default -> null; + }; + + if(subBuilder == null) + categoryBuilder.addEntry(entry); + else + subBuilder.add(entry); + + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + }); + + if(subBuilder != null) + categoryBuilder.addEntry(subBuilder.build()); + } +} + + + diff --git a/Common/src/main/java/tschipp/carryon/config/AnnotationData.java b/Common/src/main/java/tschipp/carryon/config/AnnotationData.java index f5a92fd..6431076 100644 --- a/Common/src/main/java/tschipp/carryon/config/AnnotationData.java +++ b/Common/src/main/java/tschipp/carryon/config/AnnotationData.java @@ -29,7 +29,8 @@ public record AnnotationData( PropertyType type, String description, int min, int max, - double minD, double maxD + double minD, double maxD, + String validationRegex ) { public static AnnotationData getData(Field field) { @@ -38,7 +39,8 @@ public record AnnotationData( annotation.type(), annotation.description(), annotation.min(), annotation.max(), - annotation.minD(), annotation.maxD() + annotation.minD(), annotation.maxD(), + annotation.validationRegex() ); } } diff --git a/Common/src/main/java/tschipp/carryon/config/BuiltCategory.java b/Common/src/main/java/tschipp/carryon/config/BuiltCategory.java index 96b61ac..6fc4a0e 100644 --- a/Common/src/main/java/tschipp/carryon/config/BuiltCategory.java +++ b/Common/src/main/java/tschipp/carryon/config/BuiltCategory.java @@ -32,9 +32,12 @@ public class BuiltCategory { public final String categoryDesc; public final String category; - public BuiltCategory(String categoryDesc, String category) { + public final String translation; + + public BuiltCategory(String categoryDesc, String category, String translation) { this.categoryDesc = categoryDesc; this.category = category; + this.translation = translation; } public Optional getProperty(String id) { diff --git a/Common/src/main/java/tschipp/carryon/config/BuiltConfig.java b/Common/src/main/java/tschipp/carryon/config/BuiltConfig.java index c2b3d3a..c534a79 100644 --- a/Common/src/main/java/tschipp/carryon/config/BuiltConfig.java +++ b/Common/src/main/java/tschipp/carryon/config/BuiltConfig.java @@ -25,7 +25,7 @@ public class BuiltConfig extends BuiltCategory { public final String fileName; public BuiltConfig(String fileName) { - super(null, fileName); + super(null, fileName, "key.carry.category"); this.fileName = fileName; } } diff --git a/Common/src/main/java/tschipp/carryon/config/ConfigLoader.java b/Common/src/main/java/tschipp/carryon/config/ConfigLoader.java index e5ad313..6931459 100644 --- a/Common/src/main/java/tschipp/carryon/config/ConfigLoader.java +++ b/Common/src/main/java/tschipp/carryon/config/ConfigLoader.java @@ -66,7 +66,7 @@ public class ConfigLoader { if (configClass.isAnnotationPresent(Config.class)) { category = new BuiltConfig(configClass.getAnnotation(Config.class).value()); } else if (configClass.isAnnotationPresent(Category.class)) { - category = new BuiltCategory(categoryDesc, configClass.getAnnotation(Category.class).value()); + category = new BuiltCategory(categoryDesc, configClass.getAnnotation(Category.class).value(), configClass.getAnnotation(Category.class).translation()); } else { throw new IllegalStateException("Config does not contain any @Config annotation or @Category"); } @@ -77,7 +77,7 @@ public class ConfigLoader { if (type.equals(PropertyType.CATEGORY)) { category.categories.add(buildCategory(field.getAnnotation(Property.class).description(), field.get(object))); } else { - category.properties.add(new PropertyData(object, field, AnnotationData.getData(field))); + category.properties.add(new PropertyData(object, field, AnnotationData.getData(field), field.get(object))); } } } diff --git a/Common/src/main/java/tschipp/carryon/config/PropertyData.java b/Common/src/main/java/tschipp/carryon/config/PropertyData.java index 20e01f4..4a8f013 100644 --- a/Common/src/main/java/tschipp/carryon/config/PropertyData.java +++ b/Common/src/main/java/tschipp/carryon/config/PropertyData.java @@ -21,15 +21,49 @@ package tschipp.carryon.config; import java.lang.reflect.Field; +import java.util.function.Consumer; -public record PropertyData(Object fieldClass, Field field, AnnotationData data) { +public class PropertyData { + + Object fieldClass; + Field field; + AnnotationData data; + Object defaultValue; + Consumer setter; + + public PropertyData(Object fieldClass, Field field, AnnotationData data, Object defaultValue) { + this.fieldClass = fieldClass; + this.field = field; + this.data = data; + this.defaultValue = defaultValue; + } + + public Consumer getSetter() { + return setter; + } + + public void setSetter(Consumer setter) { + this.setter = setter; + } + + public AnnotationData getData() { + return data; + } + + public Field getField() { + return field; + } + + public Object getFieldClass() { + return fieldClass; + } public String getId() { - return field().getName(); + return field.getName(); } public boolean getBoolean() throws IllegalAccessException { - return field().getBoolean(fieldClass()); + return field.getBoolean(fieldClass); } public void setBoolean(boolean _boolean) { @@ -40,8 +74,12 @@ public record PropertyData(Object fieldClass, Field field, AnnotationData data) } } + public boolean getDefaultBoolean() { + return (boolean)defaultValue; + } + public int getInt() throws IllegalAccessException { - return field().getInt(fieldClass()); + return field.getInt(fieldClass); } public void setInt(int _int) { @@ -52,8 +90,12 @@ public record PropertyData(Object fieldClass, Field field, AnnotationData data) } } + public int getDefaultInt() { + return (int)defaultValue; + } + public double getDouble() throws IllegalAccessException { - return field().getDouble(fieldClass()); + return field.getDouble(fieldClass); } public void setDouble(double _double) { @@ -64,8 +106,12 @@ public record PropertyData(Object fieldClass, Field field, AnnotationData data) } } + public double getDefaultDouble() { + return (double)defaultValue; + } + public String[] getStringArray() throws IllegalAccessException { - return (String[])field().get(fieldClass()); + return (String[])field.get(fieldClass); } public void setStringArray(String[] arr) @@ -76,4 +122,8 @@ public record PropertyData(Object fieldClass, Field field, AnnotationData data) //Ignore } } + + public String[] getDefaultStringArray() { + return (String[])defaultValue; + } } diff --git a/Common/src/main/java/tschipp/carryon/config/annotations/Category.java b/Common/src/main/java/tschipp/carryon/config/annotations/Category.java index daf06cd..3efd5d0 100644 --- a/Common/src/main/java/tschipp/carryon/config/annotations/Category.java +++ b/Common/src/main/java/tschipp/carryon/config/annotations/Category.java @@ -29,4 +29,5 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) public @interface Category { String value(); + String translation() default ""; } diff --git a/Common/src/main/java/tschipp/carryon/config/annotations/Property.java b/Common/src/main/java/tschipp/carryon/config/annotations/Property.java index 7faa605..46845bf 100644 --- a/Common/src/main/java/tschipp/carryon/config/annotations/Property.java +++ b/Common/src/main/java/tschipp/carryon/config/annotations/Property.java @@ -32,7 +32,6 @@ import java.lang.annotation.Target; public @interface Property { - PropertyType type(); String description(); @@ -41,4 +40,6 @@ public @interface Property { double minD() default Double.MIN_VALUE; double maxD() default Double.MAX_VALUE; + + String validationRegex() default ".*"; } diff --git a/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java b/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java index 6da18ee..0380fc0 100644 --- a/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java +++ b/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java @@ -62,7 +62,7 @@ public class InventoryMixin return original.call(instance, slot); } - @Inject(method = "setPickedItem(Lnet/minecraft/world/item/ItemStack;)V", at = @At("HEAD"), cancellable = true) + @Inject(method = "addAndPickItem(Lnet/minecraft/world/item/ItemStack;)V", at = @At("HEAD"), cancellable = true) private void onPickBlock(CallbackInfo info) { if(CarryOnDataManager.getCarryData(player).isCarrying()) diff --git a/Fabric/build.gradle b/Fabric/build.gradle index b22ea47..6360d91 100644 --- a/Fabric/build.gradle +++ b/Fabric/build.gradle @@ -25,6 +25,8 @@ repositories { url "https://maven.siphalor.de/" name "Siphalor's Maven" } + + maven { url "https://maven.terraformersmc.com/releases/" } } @@ -39,7 +41,12 @@ dependencies { implementation group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1' implementation project(":Common") - modRuntimeOnly "de.siphalor:amecsapi-1.20:1.5.6+mc1.20.2" + //modRuntimeOnly "de.siphalor:amecsapi-1.20:1.5.6+mc1.20.2" + + modApi("me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}") { + exclude(group: "net.fabricmc.fabric-api") + } + modApi "com.terraformersmc:modmenu:13.0.0-beta.1" } loom { diff --git a/Fabric/src/main/java/tschipp/carryon/compat/ClothConfigCompatFabric.java b/Fabric/src/main/java/tschipp/carryon/compat/ClothConfigCompatFabric.java new file mode 100644 index 0000000..250e4ee --- /dev/null +++ b/Fabric/src/main/java/tschipp/carryon/compat/ClothConfigCompatFabric.java @@ -0,0 +1,16 @@ +package tschipp.carryon.compat; + +import net.minecraft.client.gui.screens.Screen; +import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.config.fabric.ConfigLoaderImpl; + +public class ClothConfigCompatFabric { + + public static Screen createScreen(BuiltConfig client, BuiltConfig common, Screen screen) { + + return ClothConfigCompat.getConfigScreen(client, common, screen, ConfigLoaderImpl::saveConfigs); + } +} + + + diff --git a/Fabric/src/main/java/tschipp/carryon/compat/ModMenuCompat.java b/Fabric/src/main/java/tschipp/carryon/compat/ModMenuCompat.java new file mode 100644 index 0000000..19379ac --- /dev/null +++ b/Fabric/src/main/java/tschipp/carryon/compat/ModMenuCompat.java @@ -0,0 +1,17 @@ +package tschipp.carryon.compat; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.config.fabric.ConfigLoaderImpl; + +public class ModMenuCompat implements ModMenuApi { + + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + + BuiltConfig[] configs = ConfigLoaderImpl.CONFIGS.values().toArray(new BuiltConfig[0]); + + return (parent) -> ClothConfigCompatFabric.createScreen(configs[1], configs[0], parent); + } +} diff --git a/Fabric/src/main/java/tschipp/carryon/config/fabric/ConfigLoaderImpl.java b/Fabric/src/main/java/tschipp/carryon/config/fabric/ConfigLoaderImpl.java index 890d671..55f2f23 100644 --- a/Fabric/src/main/java/tschipp/carryon/config/fabric/ConfigLoaderImpl.java +++ b/Fabric/src/main/java/tschipp/carryon/config/fabric/ConfigLoaderImpl.java @@ -29,17 +29,14 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class ConfigLoaderImpl { private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create(); //Default JSON and config data. - public static final Map CONFIGS = new HashMap<>(); + public static final Map CONFIGS = new LinkedHashMap<>(); public static void initialize() throws IOException { Path cfgPath = FabricLoader.getInstance().getConfigDir(); @@ -68,11 +65,11 @@ public class ConfigLoaderImpl { JsonElement value = entry.getValue(); if (value instanceof JsonPrimitive configValue) { category.getProperty(id).ifPresent(data -> { - if (configValue.isBoolean() && data.data().type().equals(PropertyType.BOOLEAN)) + if (configValue.isBoolean() && data.getData().type().equals(PropertyType.BOOLEAN)) data.setBoolean(configValue.getAsBoolean()); - if (configValue.isNumber() && data.data().type().equals(PropertyType.INT)) { + if (configValue.isNumber() && data.getData().type().equals(PropertyType.INT)) { int configInt = configValue.getAsInt(); - if (configInt > data.data().max() || configInt < data.data().min()) { + if (configInt > data.getData().max() || configInt < data.getData().min()) { try { config.addProperty(id, data.getInt()); } catch (IllegalAccessException ignored) { @@ -81,9 +78,9 @@ public class ConfigLoaderImpl { data.setInt(configInt); } } - if (configValue.isNumber() && data.data().type().equals(PropertyType.DOUBLE)) { + if (configValue.isNumber() && data.getData().type().equals(PropertyType.DOUBLE)) { double configDouble = configValue.getAsDouble(); - if (configDouble > data.data().maxD() || configDouble < data.data().minD()) { + if (configDouble > data.getData().maxD() || configDouble < data.getData().minD()) { try { config.addProperty(id, data.getDouble()); } catch (IllegalAccessException ignored) { @@ -97,7 +94,7 @@ public class ConfigLoaderImpl { category.getCategory(id).ifPresent(cat -> loadConfig(cat, subConfig)); } else if (value instanceof JsonArray list) { category.getProperty(id).ifPresent(data -> { - if(data.data().type() == PropertyType.STRING_ARRAY) + if(data.getData().type() == PropertyType.STRING_ARRAY) { List ls = new ArrayList<>(); for(JsonElement arrEle : list) @@ -116,6 +113,19 @@ public class ConfigLoaderImpl { return config; } + public static void saveConfigs() { + try { + Path cfgPath = FabricLoader.getInstance().getConfigDir(); + for (Map.Entry entry : CONFIGS.entrySet()) { + File cfgFile = new File(cfgPath.toFile(), entry.getValue().fileName+".json"); + cfgPath.toFile().mkdirs(); + FileUtils.write(cfgFile, GSON.toJson(entry.getKey()), StandardCharsets.UTF_8); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + public static void registerConfig(BuiltConfig config) { try { JsonObject configJson = new JsonObject(); @@ -136,20 +146,37 @@ public class ConfigLoaderImpl { } private static void buildProperty(JsonObject builder, PropertyData data) throws IllegalAccessException { - AnnotationData annotationData = data.data(); + AnnotationData annotationData = data.getData(); builder.addProperty("//"+data.getId(), annotationData.description()); switch (annotationData.type()) { - case BOOLEAN -> builder.addProperty(data.getId(), data.getBoolean()); - case INT -> builder.addProperty(data.getId(), data.getInt()); - case DOUBLE -> builder.addProperty(data.getId(), data.getDouble()); - case STRING_ARRAY -> { + case BOOLEAN: + builder.addProperty(data.getId(), data.getBoolean()); + data.setSetter((b) -> {builder.addProperty(data.getId(), (boolean)b); data.setBoolean((boolean)b);}); + break; + case INT: + builder.addProperty(data.getId(), data.getInt()); + data.setSetter((b) -> {builder.addProperty(data.getId(), (int)b); data.setInt((int)b);}); + break; + case DOUBLE: + builder.addProperty(data.getId(), data.getDouble()); + data.setSetter((b) -> {builder.addProperty(data.getId(), (double)b); data.setDouble((double)b);}); + break; + case STRING_ARRAY: JsonArray arr = new JsonArray(); for(String s : data.getStringArray()) arr.add(s); builder.add(data.getId(), arr); - } - default -> throw new IllegalAccessException("Unknown property type."); + data.setSetter(list -> { + JsonArray overwrite = new JsonArray(); + for(String s : (List)list) + overwrite.add(s); + builder.add(data.getId(), overwrite); + data.setStringArray(((List) list).toArray(new String[0])); + }); + break; + default: + throw new IllegalAccessException("Unknown property type."); } } } diff --git a/Fabric/src/main/resources/fabric.mod.json b/Fabric/src/main/resources/fabric.mod.json index 3d2cb47..a2ea212 100644 --- a/Fabric/src/main/resources/fabric.mod.json +++ b/Fabric/src/main/resources/fabric.mod.json @@ -23,6 +23,9 @@ ], "client": [ "tschipp.carryon.CarryOnFabricClientMod" + ], + "modmenu" : [ + "tschipp.carryon.compat.ModMenuCompat" ] }, "mixins": [ diff --git a/Forge/build.gradle b/Forge/build.gradle index dd888a3..d1a1aa3 100644 --- a/Forge/build.gradle +++ b/Forge/build.gradle @@ -117,6 +117,8 @@ dependencies { //implementation fg.deobf("net.darkhax.gamestages:GameStages-Forge-1.19.2:11.0.2") + implementation(fg.deobf("me.shedaniel.cloth:cloth-config-forge:${cloth_config_version}")) + fileTree("libs").matching { include "*.jar" }.each { diff --git a/Forge/src/main/java/tschipp/carryon/CarryOnForge.java b/Forge/src/main/java/tschipp/carryon/CarryOnForge.java index 3ef9f85..a80feeb 100644 --- a/Forge/src/main/java/tschipp/carryon/CarryOnForge.java +++ b/Forge/src/main/java/tschipp/carryon/CarryOnForge.java @@ -45,7 +45,7 @@ public class CarryOnForge { context.getModEventBus().addListener(this::setup); - ConfigLoaderImpl.initialize(); + ConfigLoaderImpl.initialize(context); } private void setup(final FMLCommonSetupEvent event) diff --git a/Forge/src/main/java/tschipp/carryon/compat/ClothConfigCompatForge.java b/Forge/src/main/java/tschipp/carryon/compat/ClothConfigCompatForge.java new file mode 100644 index 0000000..5ab8ea3 --- /dev/null +++ b/Forge/src/main/java/tschipp/carryon/compat/ClothConfigCompatForge.java @@ -0,0 +1,17 @@ +package tschipp.carryon.compat; + +import net.minecraft.client.gui.screens.Screen; +import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.config.forge.ConfigLoaderImpl; + +public class ClothConfigCompatForge { + + public static Screen createScreen(BuiltConfig client, BuiltConfig common, Screen screen) { + + return ClothConfigCompat.getConfigScreen(client, common, screen, () -> { + ConfigLoaderImpl.saveConfig(client); ConfigLoaderImpl.saveConfig(common);}); + } +} + + + diff --git a/Forge/src/main/java/tschipp/carryon/config/forge/ConfigLoaderImpl.java b/Forge/src/main/java/tschipp/carryon/config/forge/ConfigLoaderImpl.java index acc76c4..6bdf19c 100644 --- a/Forge/src/main/java/tschipp/carryon/config/forge/ConfigLoaderImpl.java +++ b/Forge/src/main/java/tschipp/carryon/config/forge/ConfigLoaderImpl.java @@ -45,42 +45,25 @@ public class ConfigLoaderImpl { public static final Map CONFIGS = new HashMap<>(); - public static void initialize() { - IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); + public static void initialize(FMLJavaModLoadingContext context) { + IEventBus bus = context.getModEventBus(); bus.addListener(ConfigLoaderImpl::onConfigLoad); bus.addListener(ConfigLoaderImpl::onConfigReload); ConfigLoaderImpl.CONFIGS.forEach((spec, config) -> { if(config.fileName.contains("client")) - ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, spec, config.fileName+".toml"); + context.registerConfig(ModConfig.Type.CLIENT, spec, config.fileName+".toml"); else - ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, spec, config.fileName+".toml"); + context.registerConfig(ModConfig.Type.COMMON, spec, config.fileName+".toml"); }); } public static void onConfigLoad(ModConfigEvent.Loading loading) { loadConfig(loading.getConfig().getSpec()); - -// -// DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> () -> { -// ConfigLoader.onConfigLoaded(Minecraft.getInstance().level.registryAccess()); -// }); -// -// DistExecutor.safeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> { -// ConfigLoader.onConfigLoaded(ServerLifecycleHooks.getCurrentServer().registryAccess()); -// }); } public static void onConfigReload(ModConfigEvent.Reloading loading) { loadConfig(loading.getConfig().getSpec()); -// -// DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> () -> { -// ConfigLoader.onConfigLoaded(Minecraft.getInstance().level.registryAccess()); -// }); -// -// DistExecutor.safeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> { -// ConfigLoader.onConfigLoaded(ServerLifecycleHooks.getCurrentServer().registryAccess()); -// }); } private static void loadConfig(IConfigSpec spec) { @@ -108,6 +91,15 @@ public class ConfigLoaderImpl { }); } + public static void saveConfig(BuiltConfig cfg) { + for (Map.Entry entry : CONFIGS.entrySet()) { + if(entry.getValue() == cfg) { + ForgeConfigSpec spec = entry.getKey(); + spec.save(); + } + } + } + public static void registerConfig(BuiltConfig config) { try { ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); @@ -128,10 +120,10 @@ public class ConfigLoaderImpl { } private static void buildProperty(ForgeConfigSpec.Builder builder, PropertyData data) throws IllegalAccessException { - AnnotationData annotationData = data.data(); + AnnotationData annotationData = data.getData(); builder.comment(annotationData.description()); - switch (annotationData.type()) { + ForgeConfigSpec.ConfigValue val = switch (annotationData.type()) { case BOOLEAN -> builder.define(data.getId(), data.getBoolean()); case INT -> builder.defineInRange(data.getId(), data.getInt(), annotationData.min(), annotationData.max()); case DOUBLE -> builder.defineInRange(data.getId(), data.getDouble(), annotationData.minD(), annotationData.maxD()); @@ -144,6 +136,8 @@ public class ConfigLoaderImpl { return new ArrayList<>(); }, obj -> obj instanceof String); default -> throw new IllegalAccessException("Unknown property type."); - } + }; + + data.setSetter(val::set); } } diff --git a/Forge/src/main/java/tschipp/carryon/events/ModClientEvents.java b/Forge/src/main/java/tschipp/carryon/events/ModClientEvents.java index 4524ddf..3914d57 100644 --- a/Forge/src/main/java/tschipp/carryon/events/ModClientEvents.java +++ b/Forge/src/main/java/tschipp/carryon/events/ModClientEvents.java @@ -22,12 +22,19 @@ package tschipp.carryon.events; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.ConfigScreenHandler; import net.minecraftforge.client.event.RegisterKeyMappingsEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import tschipp.carryon.Constants; import tschipp.carryon.client.keybinds.CarryOnKeybinds; +import tschipp.carryon.compat.ClothConfigCompatForge; +import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.config.forge.ConfigLoaderImpl; +import tschipp.carryon.platform.Services; @Mod.EventBusSubscriber(bus = Bus.MOD, modid = Constants.MOD_ID) public class ModClientEvents @@ -37,4 +44,14 @@ public class ModClientEvents { CarryOnKeybinds.registerKeybinds(event::register); } + + @SubscribeEvent + public static void clientSetup(FMLClientSetupEvent event) + { + if(Services.PLATFORM.isModLoaded("cloth_config")) { + + BuiltConfig[] configs = ConfigLoaderImpl.CONFIGS.values().toArray(new BuiltConfig[0]); + ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory((mc, prevScreen) -> ClothConfigCompatForge.createScreen(configs[1], configs[0], prevScreen))); + } + } } diff --git a/Forge/src/main/java/tschipp/carryon/mixin/ParticleEngineMixin.java b/Forge/src/main/java/tschipp/carryon/mixin/ParticleEngineMixin.java index 720034b..44632dc 100644 --- a/Forge/src/main/java/tschipp/carryon/mixin/ParticleEngineMixin.java +++ b/Forge/src/main/java/tschipp/carryon/mixin/ParticleEngineMixin.java @@ -24,6 +24,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Camera; import net.minecraft.client.particle.ParticleEngine; import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.culling.Frustum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -36,10 +37,10 @@ public class ParticleEngineMixin { //I am injecting into a lambda, lord help me - @Inject(method = "Lnet/minecraft/client/particle/ParticleEngine;render(Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LightTexture;turnOffLightLayer()V", + @Inject(method = "render(Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/culling/Frustum;)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;endBatch()V", shift = At.Shift.AFTER)) - private void onRenderLevel(LightTexture p_107339_, Camera p_107340_, float partialTick, Frustum frustum, CallbackInfo ci) + private void onRenderLevel(Camera p_107340_, float partialTick, MultiBufferSource.BufferSource p_377798_, Frustum frustum, CallbackInfo ci) { CarriedObjectRender.drawThirdPerson(partialTick, new PoseStack().last().pose()); } diff --git a/NeoForge/build.gradle b/NeoForge/build.gradle index 00b986a..311945e 100644 --- a/NeoForge/build.gradle +++ b/NeoForge/build.gradle @@ -56,13 +56,14 @@ runs { systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id } + /* data { // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it // workingDirectory project.file('run-data') // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() - } + }*/ } sourceSets.main.resources { srcDir 'src/generated/resources' } @@ -79,6 +80,8 @@ tasks.named("test").configure { dependencies { implementation "net.neoforged:neoforge:${neoforge_version}" compileOnly project(":Common") + + api "me.shedaniel.cloth:cloth-config-neoforge:${cloth_config_version}" //implementation fg.deobf("net.darkhax.gamestages:GameStages-Forge-1.19.2:11.0.2") //implementation fg.deobf("net.darkhax.bookshelf:Bookshelf-Forge-1.19.3:17.0.2") } @@ -114,11 +117,4 @@ publishing { url "file://" + System.getenv("local_maven") } } -} - -idea { - module { - downloadSources = true - downloadJavadoc = true - } } \ No newline at end of file diff --git a/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForge.java b/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForge.java index f10e1ec..945f10f 100644 --- a/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForge.java +++ b/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForge.java @@ -25,6 +25,7 @@ import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModContainer; import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; +import net.neoforged.neoforge.client.gui.ConfigurationScreen; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; import net.neoforged.neoforge.network.registration.PayloadRegistrar; diff --git a/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForgeClient.java b/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForgeClient.java new file mode 100644 index 0000000..cb6b883 --- /dev/null +++ b/NeoForge/src/main/java/tschipp/carryon/CarryOnNeoForgeClient.java @@ -0,0 +1,27 @@ +package tschipp.carryon; + +import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.client.gui.IConfigScreenFactory; +import tschipp.carryon.compat.ClothConfigCompatNeo; +import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.config.neoforge.ConfigLoaderImpl; +import tschipp.carryon.platform.Services; + +import java.util.function.Supplier; + +@Mod(value = Constants.MOD_ID, dist = Dist.CLIENT) +public class CarryOnNeoForgeClient { + + public CarryOnNeoForgeClient(ModContainer container) { + + if(Services.PLATFORM.isModLoaded("cloth_config")) { + + BuiltConfig[] configs = ConfigLoaderImpl.CONFIGS.values().toArray(new BuiltConfig[0]); + + container.registerExtensionPoint(IConfigScreenFactory.class, (Supplier) () -> new ClothConfigCompatNeo(configs[1], configs[0])); + } + } + +} diff --git a/NeoForge/src/main/java/tschipp/carryon/compat/ClothConfigCompatNeo.java b/NeoForge/src/main/java/tschipp/carryon/compat/ClothConfigCompatNeo.java new file mode 100644 index 0000000..4822691 --- /dev/null +++ b/NeoForge/src/main/java/tschipp/carryon/compat/ClothConfigCompatNeo.java @@ -0,0 +1,26 @@ +package tschipp.carryon.compat; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.neoforged.fml.ModContainer; +import net.neoforged.neoforge.client.gui.IConfigScreenFactory; +import tschipp.carryon.config.AnnotationData; +import tschipp.carryon.config.BuiltCategory; +import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.config.neoforge.ConfigLoaderImpl; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Optional; + +public record ClothConfigCompatNeo(BuiltConfig client, BuiltConfig common) implements IConfigScreenFactory { + + @Override + public Screen createScreen(ModContainer modContainer, Screen screen) { + return ClothConfigCompat.getConfigScreen(client, common, screen, () -> {ConfigLoaderImpl.saveConfig(client); ConfigLoaderImpl.saveConfig(common);}); + } +} + + + diff --git a/NeoForge/src/main/java/tschipp/carryon/config/neoforge/ConfigLoaderImpl.java b/NeoForge/src/main/java/tschipp/carryon/config/neoforge/ConfigLoaderImpl.java index 25b6ccd..e16ea09 100644 --- a/NeoForge/src/main/java/tschipp/carryon/config/neoforge/ConfigLoaderImpl.java +++ b/NeoForge/src/main/java/tschipp/carryon/config/neoforge/ConfigLoaderImpl.java @@ -40,11 +40,12 @@ import tschipp.carryon.Constants; import tschipp.carryon.config.*; import java.util.*; +import java.util.function.Consumer; @EventBusSubscriber(modid = Constants.MOD_ID, bus = EventBusSubscriber.Bus.MOD) public class ConfigLoaderImpl { - public static final Map CONFIGS = new HashMap<>(); + public static final Map CONFIGS = new LinkedHashMap<>(); public static void initialize(ModContainer container) { @@ -60,25 +61,10 @@ public class ConfigLoaderImpl { @SubscribeEvent public static void onConfigLoad(ModConfigEvent.Loading loading) { loadConfig((ModConfigSpec) loading.getConfig().getSpec()); - -// DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> () -> { -// ConfigLoader.onConfigLoaded(Minecraft.getInstance().level.registryAccess()); -// }); -// -// DistExecutor.safeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> { -// ConfigLoader.onConfigLoaded(ServerLifecycleHooks.getCurrentServer().registryAccess()); -// }); } @SubscribeEvent public static void onConfigReload(ModConfigEvent.Reloading loading) { - loadConfig((ModConfigSpec) loading.getConfig().getSpec()); -// DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> () -> { -// ConfigLoader.onConfigLoaded(Minecraft.getInstance().level.registryAccess()); -// }); -// -// DistExecutor.safeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> { -// ConfigLoader.onConfigLoaded(ServerLifecycleHooks.getCurrentServer().registryAccess()); -// }); + loadConfig((ModConfigSpec) loading.getConfig().getSpec()); } private static void loadConfig(ModConfigSpec spec) { @@ -106,6 +92,15 @@ public class ConfigLoaderImpl { }); } + public static void saveConfig(BuiltConfig cfg) { + for (Map.Entry entry : CONFIGS.entrySet()) { + if(entry.getValue() == cfg) { + ModConfigSpec spec = entry.getKey(); + spec.save(); + } + } + } + public static void registerConfig(BuiltConfig config) { try { ModConfigSpec.Builder builder = new ModConfigSpec.Builder(); @@ -126,10 +121,11 @@ public class ConfigLoaderImpl { } private static void buildProperty(ModConfigSpec.Builder builder, PropertyData data) throws IllegalAccessException { - AnnotationData annotationData = data.data(); + AnnotationData annotationData = data.getData(); builder.comment(annotationData.description()); - switch (annotationData.type()) { + + ModConfigSpec.ConfigValue val = switch (annotationData.type()) { case BOOLEAN -> builder.define(data.getId(), data.getBoolean()); case INT -> builder.defineInRange(data.getId(), data.getInt(), annotationData.min(), annotationData.max()); case DOUBLE -> builder.defineInRange(data.getId(), data.getDouble(), annotationData.minD(), annotationData.maxD()); @@ -142,6 +138,8 @@ public class ConfigLoaderImpl { return new ArrayList<>(); }, obj -> obj instanceof String); default -> throw new IllegalAccessException("Unknown property type."); - } + }; + + data.setSetter(val::set); } } diff --git a/build.gradle b/build.gradle index b3b3272..ee4fea8 100644 --- a/build.gradle +++ b/build.gradle @@ -50,6 +50,11 @@ subprojects { name = 'BlameJared Maven (CrT / Bookshelf)' url = 'https://maven.blamejared.com' } + + maven { + name = "Shedaniel" + url "https://maven.shedaniel.me/" + } } tasks.withType(JavaCompile).configureEach { @@ -93,4 +98,11 @@ subprojects { enabled = false } + + idea { + module { + downloadSources = true + downloadJavadoc = true + } + } } diff --git a/gradle.properties b/gradle.properties index ffcd74e..1d3e82a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,37 +1,38 @@ # Project -version=2.2.3 +version=2.3.0 group=tschipp.carryon # Common -minecraft_version=1.21.3 +minecraft_version=1.21.4 mod_name=Carry On mod_author=Tschipp, PurpliciousCow mod_id=carryon license=GNU LGPLv3 credits= description=Carry On is a simple mod that improves game interaction by allowing players to pick up, carry, and place single block Tile Entities using only their empty hands. -minecraft_version_range=[1.21, 1.22) +minecraft_version_range=[1.21.4, 1.22) # Forge -forge_version=53.0.33 -forge_loader_version_range=[53,) -forge_version_range=[53,) -parchment_mappings=2024.12.07-1.21.3 +forge_version=54.0.12 +forge_loader_version_range=[54,) +forge_version_range=[54,) +parchment_mappings=2024.12.29-1.21.4 //forge_ats_enabled=true # Fabric -fabric_version=0.112.1+1.21.3 +fabric_version=0.113.0+1.21.4 fabric_loader_version=0.16.9 -parchment_mappings_fabric=1.21.3:2024.12.07 +parchment_mappings_fabric=1.21.4:2024.12.29 # Neoforge -neoforge_version=21.3.58 +neoforge_version=21.4.47-beta neoforge_loader_version_range=[4,) -neogradle.subsystems.parchment.minecraftVersion=1.21.3 -neogradle.subsystems.parchment.mappingsVersion=2024.12.07 +neogradle.subsystems.parchment.minecraftVersion=1.21.4 +neogradle.subsystems.parchment.mappingsVersion=2024.12.29 # Gradle org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -mixinextras_version=0.3.6 \ No newline at end of file +mixinextras_version=0.3.6 +cloth_config_version=17.0.144 \ No newline at end of file