Updated to 1.21.4, Added support for Cloth Config

This commit is contained in:
Tschipp 2025-01-04 00:32:09 +01:00
parent 7251cbf03f
commit ae260556b2
33 changed files with 533 additions and 133 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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",

View File

@ -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<Carry
{
public ScriptReloadListener()
{
super(CarryOnScript.CODEC, "carryon/scripts");
super(CarryOnScript.CODEC, FileToIdConverter.json("carryon/scripts"));
}
@Override
protected void apply(Map<ResourceLocation, CarryOnScript> scripts, ResourceManager resourceManager, ProfilerFiller profilerFiller)
protected void apply(Map<ResourceLocation, CarryOnScript> scripts, @NotNull ResourceManager resourceManager, @NotNull ProfilerFiller profilerFiller)
{
ScriptManager.SCRIPTS.clear();
@ -59,7 +61,7 @@ public class ScriptReloadListener extends SimpleJsonResourceReloadListener<Carry
ScriptManager.SCRIPTS.add(script);
});
Collections.sort(ScriptManager.SCRIPTS, (s1, s2) -> Long.compare(s2.priority(), s1.priority()));
ScriptManager.SCRIPTS.sort((s1, s2) -> Long.compare(s2.priority(), s1.priority()));
}

View File

@ -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<Boolean>) 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<Integer>) 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<Double>) 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<List<String>>) 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());
}
}

View File

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

View File

@ -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<PropertyData> getProperty(String id) {

View File

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

View File

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

View File

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

View File

@ -29,4 +29,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface Category {
String value();
String translation() default "";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<JsonObject, BuiltConfig> CONFIGS = new HashMap<>();
public static final Map<JsonObject, BuiltConfig> 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<String> 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<JsonObject, BuiltConfig> 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<String>)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.");
}
}
}

View File

@ -23,6 +23,9 @@
],
"client": [
"tschipp.carryon.CarryOnFabricClientMod"
],
"modmenu" : [
"tschipp.carryon.compat.ModMenuCompat"
]
},
"mixins": [

View File

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

View File

@ -45,7 +45,7 @@ public class CarryOnForge {
context.getModEventBus().addListener(this::setup);
ConfigLoaderImpl.initialize();
ConfigLoaderImpl.initialize(context);
}
private void setup(final FMLCommonSetupEvent event)

View File

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

View File

@ -45,42 +45,25 @@ public class ConfigLoaderImpl {
public static final Map<ForgeConfigSpec, BuiltConfig> 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<ForgeConfigSpec> spec) {
@ -108,6 +91,15 @@ public class ConfigLoaderImpl {
});
}
public static void saveConfig(BuiltConfig cfg) {
for (Map.Entry<ForgeConfigSpec, BuiltConfig> 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);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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<IConfigScreenFactory>) () -> new ClothConfigCompatNeo(configs[1], configs[0]));
}
}
}

View File

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

View File

@ -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<ModConfigSpec, BuiltConfig> CONFIGS = new HashMap<>();
public static final Map<ModConfigSpec, BuiltConfig> 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<ModConfigSpec, BuiltConfig> 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);
}
}

View File

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

View File

@ -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
mixinextras_version=0.3.6
cloth_config_version=17.0.144