使用塔吊API 将该项目 跨模组加载器化

This commit is contained in:
叁玖领域 2025-05-24 23:39:49 +08:00
parent a0d9841112
commit 600d628dec
33 changed files with 636 additions and 53 deletions

View File

@ -1,8 +1,11 @@
package com.leisuretimedock.jsonem;
public final class Jsonem {
public static final String MOD_ID = "jsonem";
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class JsonEm {
public static final String MOD_ID = "jsonem";
public static final Logger LOG = LoggerFactory.getLogger(JsonEm.class);
public static void init() {
// Write common init code here.
}

View File

@ -0,0 +1,17 @@
package com.leisuretimedock.jsonem.mixin;
import net.minecraft.client.model.geom.builders.CubeDeformation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(CubeDeformation.class)
public interface DilationAccess {
@Accessor("growX")
float jsonem$growX();
@Accessor("growY")
float jsonem$growY();
@Accessor("growZ")
float jsonem$growZ();
}

View File

@ -0,0 +1,26 @@
package com.leisuretimedock.jsonem.mixin;
import com.leisuretimedock.jsonem.util.JsonEntityModelUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.client.model.geom.EntityModelSet;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.server.packs.resources.ResourceManager;
@Mixin(EntityModelSet.class)
public class EntityModelLoaderMixin {
@Shadow private Map<ModelLayerLocation, LayerDefinition> roots;
@Inject(method = "onResourceManagerReload", at = @At("TAIL"))
private void jsonem$loadJsonEntityModels(ResourceManager manager, CallbackInfo ci) {
this.roots = new HashMap<>(this.roots);
JsonEntityModelUtil.loadModels(manager, this.roots);
}
}

View File

@ -0,0 +1,33 @@
package com.leisuretimedock.jsonem.mixin;
import com.google.common.collect.ImmutableMap;
import com.leisuretimedock.jsonem.JsonEm;
import com.leisuretimedock.jsonem.platform.Services;
import com.leisuretimedock.jsonem.util.JsonEntityModelUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.io.IOException;
import java.util.Map;
import net.minecraft.client.model.geom.LayerDefinitions;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.builders.LayerDefinition;
@Mixin(LayerDefinitions.class)
public class EntityModelsMixin {
@Inject(method = "createRoots", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;"), locals = LocalCapture.CAPTURE_FAILSOFT)
private static void jsonem$dumpModels(CallbackInfoReturnable<Map<ModelLayerLocation, LayerDefinition>> cir, ImmutableMap.Builder<ModelLayerLocation, LayerDefinition> layers) {
if (Services.PLATFORM.shouldDumpModels()) {
layers.build().forEach((layer, data) -> {
try {
JsonEntityModelUtil.dump(layer, data);
} catch (IOException e) {
JsonEm.LOG.error("Error",e);
}
});
}
}
}

View File

@ -0,0 +1,45 @@
package com.leisuretimedock.jsonem.mixin;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.Set;
import net.minecraft.client.model.geom.builders.CubeDefinition;
import net.minecraft.client.model.geom.builders.CubeDeformation;
import net.minecraft.client.model.geom.builders.UVPair;
import net.minecraft.core.Direction;
@Mixin(CubeDefinition.class)
public interface ModelCuboidDataAccess {
@Accessor("comment")
String jsonem$comment();
@Accessor("origin")
Vector3f jsonem$origin();
@Accessor("dimensions")
Vector3f jsonem$dimensions();
@Accessor("grow")
CubeDeformation jsonem$grow();
@Accessor("mirror")
boolean jsonem$mirror();
@Accessor("texCoord")
UVPair jsonem$uv();
@Accessor("texScale")
UVPair jsonem$uvScale();
@Accessor("visibleFaces")
Set<Direction> jsonem$faces();
@Invoker("<init>")
static CubeDefinition jsonem$create(@Nullable String name, float textureX, float textureY, float offsetX, float offsetY, float offsetZ, float sizeX, float sizeY, float sizeZ, CubeDeformation extra, boolean mirror, float textureScaleX, float textureScaleY, Set<Direction> directions) {
throw new AssertionError("mixin broke");
}
}

View File

@ -0,0 +1,28 @@
package com.leisuretimedock.jsonem.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.List;
import java.util.Map;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.CubeDefinition;
import net.minecraft.client.model.geom.builders.PartDefinition;
@Mixin(PartDefinition.class)
public interface ModelPartDataAccess {
@Accessor("cubes")
List<CubeDefinition> jsonem$cubes();
@Accessor("partPose")
PartPose jsonem$transform();
@Accessor("children")
Map<String, PartDefinition> jsonem$children();
@Invoker("<init>")
static PartDefinition create(List<CubeDefinition> cuboids, PartPose rotation) {
throw new AssertionError("mixin broke");
}
}

View File

@ -0,0 +1,14 @@
package com.leisuretimedock.jsonem.mixin;
import net.minecraft.client.model.geom.builders.MaterialDefinition;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(MaterialDefinition.class)
public interface TextureDimensionsAccess {
@Accessor("xTexSize")
int jsonem$width();
@Accessor("yTexSize")
int jsonem$height();
}

View File

@ -0,0 +1,22 @@
package com.leisuretimedock.jsonem.mixin;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.model.geom.builders.MaterialDefinition;
import net.minecraft.client.model.geom.builders.MeshDefinition;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(LayerDefinition.class)
public interface TexturedModelDataAccess {
@Accessor("mesh")
MeshDefinition jsonem$root();
@Accessor("material")
MaterialDefinition jsonem$texture();
@Invoker("<init>")
static LayerDefinition create(MeshDefinition data, MaterialDefinition dimensions) {
throw new AssertionError("mixin broke");
}
}

View File

@ -0,0 +1,5 @@
package com.leisuretimedock.jsonem.platform;
public interface IPlatFormHelper {
boolean shouldDumpModels();
}

View File

@ -0,0 +1,16 @@
package com.leisuretimedock.jsonem.platform;
import com.leisuretimedock.jsonem.JsonEm;
import java.util.ServiceLoader;
public class Services {
public static final IPlatFormHelper PLATFORM = load(IPlatFormHelper.class);
public static <T> T load(Class<T> clazz) {
final T loadedService = ServiceLoader.load(clazz)
.findFirst()
.orElseThrow(() -> new RuntimeException("Could not find service for " + clazz.getSimpleName()));
JsonEm.LOG.debug("Loaded {} service for {}", loadedService, clazz);
return loadedService;
}
}

View File

@ -0,0 +1,123 @@
package com.leisuretimedock.jsonem.serialization;
import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.leisuretimedock.jsonem.mixin.DilationAccess;
import com.leisuretimedock.jsonem.mixin.ModelCuboidDataAccess;
import com.leisuretimedock.jsonem.mixin.ModelPartDataAccess;
import com.leisuretimedock.jsonem.mixin.TextureDimensionsAccess;
import com.leisuretimedock.jsonem.mixin.TexturedModelDataAccess;
import com.leisuretimedock.jsonem.util.Vector2fComparable;
import org.joml.Vector3f;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import net.minecraft.Util;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.CubeDefinition;
import net.minecraft.client.model.geom.builders.CubeDeformation;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.model.geom.builders.MaterialDefinition;
import net.minecraft.client.model.geom.builders.MeshDefinition;
import net.minecraft.client.model.geom.builders.PartDefinition;
import net.minecraft.client.model.geom.builders.UVPair;
import net.minecraft.core.Direction;
import net.minecraft.util.ExtraCodecs;
public class JsonEMCodecs {
private static final Set<Direction> ALL_DIRECTIONS = EnumSet.allOf(Direction.class);
public static final Codec<UVPair> VECTOR2F = Codec.FLOAT.listOf().comapFlatMap((vec) ->
Util.fixedSize(vec, 2).map((arr) -> new Vector2fComparable(arr.get(0), arr.get(1))),
(vec) -> ImmutableList.of(vec.u(), vec.v())
);
public static final Codec<MaterialDefinition> TEXTURE_DIMENSIONS = RecordCodecBuilder.create((instance) ->
instance.group(
Codec.INT.fieldOf("width").forGetter(obj -> ((TextureDimensionsAccess) obj).jsonem$width()),
Codec.INT.fieldOf("height").forGetter(obj -> ((TextureDimensionsAccess) obj).jsonem$height())
).apply(instance, MaterialDefinition::new)
);
public static final Codec<PartPose> MODEL_TRANSFORM = RecordCodecBuilder.create((instance) ->
instance.group(
ExtraCodecs.VECTOR3F.optionalFieldOf("origin", new Vector3f(0)).forGetter(obj -> new Vector3f(obj.x, obj.y, obj.z)),
ExtraCodecs.VECTOR3F.optionalFieldOf("rotation", new Vector3f(0)).forGetter(obj -> new Vector3f(obj.xRot, obj.yRot, obj.zRot))
).apply(instance, (origin, rot) -> PartPose.offsetAndRotation(origin.x(), origin.y(), origin.z(), rot.x(), rot.y(), rot.z()))
);
public static final Codec<CubeDeformation> DILATION = ExtraCodecs.VECTOR3F.xmap(
vec -> new CubeDeformation(vec.x(), vec.y(), vec.z()),
dil -> new Vector3f(
((DilationAccess) dil).jsonem$growX(),
((DilationAccess) dil).jsonem$growY(),
((DilationAccess) dil).jsonem$growZ())
);
private static CubeDefinition createCuboidData(Optional<String> name, Vector3f offset, Vector3f dimensions, CubeDeformation dilation, boolean mirror, UVPair uv, UVPair uvSize, Optional<List<Direction>> faces) {
return ModelCuboidDataAccess.jsonem$create(name.orElse(null),
uv.u(), uv.v(),
offset.x(), offset.y(), offset.z(),
dimensions.x(), dimensions.y(), dimensions.z(),
dilation, mirror,
uvSize.u(), uvSize.v(),
faces.map(Set::copyOf).orElse(ALL_DIRECTIONS));
}
// If the set has all faces, return empty
private static Optional<List<Direction>> optionalFaceList(Set<Direction> faces) {
for (Direction direction : Direction.values()) {
if (!faces.contains(direction)) {
return Optional.of(List.copyOf(faces));
}
}
return Optional.empty();
}
private static final UVPair DEFAULT_UV_SCALE = new Vector2fComparable(1.0f, 1.0f);
public static final Codec<CubeDefinition> MODEL_CUBOID_DATA = RecordCodecBuilder.create((instance) ->
instance.group(
Codec.STRING.optionalFieldOf("name").forGetter(obj -> Optional.ofNullable(((ModelCuboidDataAccess) (Object) obj).jsonem$comment())),
ExtraCodecs.VECTOR3F.fieldOf("offset").forGetter(obj -> ((ModelCuboidDataAccess)(Object)obj).jsonem$origin()),
ExtraCodecs.VECTOR3F.fieldOf("dimensions").forGetter(obj -> ((ModelCuboidDataAccess)(Object)obj).jsonem$dimensions()),
DILATION.optionalFieldOf("dilation", CubeDeformation.NONE).forGetter(obj -> ((ModelCuboidDataAccess)(Object)obj).jsonem$grow()),
Codec.BOOL.optionalFieldOf("mirror", false).forGetter(obj -> ((ModelCuboidDataAccess)(Object)obj).jsonem$mirror()),
VECTOR2F.fieldOf("uv").forGetter(obj -> ((ModelCuboidDataAccess)(Object)obj).jsonem$uv()),
VECTOR2F.optionalFieldOf("uv_scale", DEFAULT_UV_SCALE).forGetter(obj -> Vector2fComparable.of(((ModelCuboidDataAccess)(Object)obj).jsonem$uvScale())),
Codec.list(Direction.CODEC).optionalFieldOf("faces").forGetter(obj -> optionalFaceList(((ModelCuboidDataAccess)(Object)obj).jsonem$faces()))
).apply(instance, JsonEMCodecs::createCuboidData)
);
private static Codec<PartDefinition> createPartDataCodec() {
return RecordCodecBuilder.create((instance) ->
instance.group(
MODEL_TRANSFORM.optionalFieldOf("transform", PartPose.ZERO).forGetter(obj -> ((ModelPartDataAccess) obj).jsonem$transform()),
Codec.list(MODEL_CUBOID_DATA).fieldOf("cuboids").forGetter(obj -> ((ModelPartDataAccess) obj).jsonem$cubes()),
LazyTypeUnboundedMapCodec.of(Codec.STRING, JsonEMCodecs::createPartDataCodec).optionalFieldOf("children", new HashMap<>()).forGetter(obj -> ((ModelPartDataAccess) obj).jsonem$children())
).apply(instance, (transform, cuboids, children) -> {
var data = ModelPartDataAccess.create(cuboids, transform);
((ModelPartDataAccess) data).jsonem$children().putAll(children);
return data;
})
);
}
public static final Codec<PartDefinition> MODEL_PART_DATA = createPartDataCodec();
public static final Codec<LayerDefinition> TEXTURED_MODEL_DATA = RecordCodecBuilder.create((instance) ->
instance.group(
TEXTURE_DIMENSIONS.fieldOf("texture").forGetter(obj -> ((TexturedModelDataAccess) obj).jsonem$texture()),
Codec.unboundedMap(Codec.STRING, MODEL_PART_DATA).fieldOf("bones").forGetter(obj -> ((ModelPartDataAccess) ((TexturedModelDataAccess) obj).jsonem$root().getRoot()).jsonem$children())
).apply(instance, (texture, bones) -> {
var data = new MeshDefinition();
((ModelPartDataAccess) data.getRoot()).jsonem$children().putAll(bones);
return TexturedModelDataAccess.create(data, texture);
})
);
}

View File

@ -0,0 +1,51 @@
package com.leisuretimedock.jsonem.serialization;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Lifecycle;
import com.mojang.serialization.codecs.BaseMapCodec;
import java.util.Map;
import java.util.function.Supplier;
public class LazyTypeUnboundedMapCodec<K, V> implements BaseMapCodec<K, V>, Codec<Map<K, V>> {
private final Codec<K> keyCodec;
private final Supplier<Codec<V>> elementCodecProvider;
private Codec<V> elementCodec;
public LazyTypeUnboundedMapCodec(Codec<K> keyCodec, Supplier<Codec<V>> elementCodecProvider) {
this.keyCodec = keyCodec;
this.elementCodecProvider = elementCodecProvider;
}
public static <K, V> LazyTypeUnboundedMapCodec<K, V> of(Codec<K> keyCodec, Supplier<Codec<V>> elementCodecProvider) {
return new LazyTypeUnboundedMapCodec<>(keyCodec, elementCodecProvider);
}
@Override
public <T> DataResult<Pair<Map<K, V>, T>> decode(DynamicOps<T> ops, T input) {
return ops.getMap(input).setLifecycle(Lifecycle.stable()).flatMap(map -> decode(ops, map)).map(r -> Pair.of(r, input));
}
@Override
public <T> DataResult<T> encode(Map<K, V> input, DynamicOps<T> ops, T prefix) {
return encode(input, ops, ops.mapBuilder()).build(prefix);
}
@Override
public Codec<K> keyCodec() {
return keyCodec;
}
@Override
public Codec<V> elementCodec() {
if (elementCodec == null) {
elementCodec = elementCodecProvider.get();
}
return elementCodec;
}
}

View File

@ -0,0 +1,76 @@
package com.leisuretimedock.jsonem.util;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.leisuretimedock.jsonem.JsonEm;
import com.leisuretimedock.jsonem.serialization.JsonEMCodecs;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.JsonOps;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import org.jetbrains.annotations.ApiStatus;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
public class JsonEntityModelUtil {
public static Path DUMP_DIR;
public static final Gson GSON = new Gson();
public static Optional<LayerDefinition> readJson(InputStream data) {
JsonElement json = GSON.fromJson(GSON.newJsonReader(new InputStreamReader(data)), JsonObject.class);
return JsonEMCodecs.TEXTURED_MODEL_DATA.decode(JsonOps.INSTANCE, json).result().map(Pair::getFirst);
}
public static void loadModels(ResourceManager manager, Map<ModelLayerLocation, LayerDefinition> models) {
ModelLayers.getKnownLocations().forEach(layer -> {
var modelLoc = new ResourceLocation(layer.getModel().getNamespace(), "models/entity/"+layer.getModel().getPath()+"/"+layer.getLayer()+".json");
var res = manager.getResource(modelLoc);
if (res.isPresent()) {
try {
try (var in = res.get().open()) {
var data = JsonEntityModelUtil.readJson(in);
data.ifPresent(model -> models.put(layer, model));
}
} catch (IOException e) {
JsonEm.LOG.error("Error: {}",e.getMessage());
}
}
});
}
public static void dump(ModelLayerLocation layer, LayerDefinition data) throws IOException {
if (!Files.exists(DUMP_DIR)) {
Files.createDirectories(DUMP_DIR);
}
var modelResult = JsonEMCodecs.TEXTURED_MODEL_DATA.encode(data, JsonOps.INSTANCE, new JsonObject());
var modelFolder = DUMP_DIR.resolve("assets").resolve(layer.getModel().getNamespace()).resolve("models").resolve("entity").resolve(layer.getModel().getPath());
var modelFile = modelFolder.resolve(layer.getLayer()+".json");
if (!Files.exists(modelFolder)) {
Files.createDirectories(modelFolder);
}
var element = modelResult.get().left();
if (element.isPresent()) {
var writer = GSON.newJsonWriter(Files.newBufferedWriter(modelFile));
writer.setIndent(" ");
GSON.toJson(element.get(), writer);
writer.close();
}
}
}

View File

@ -0,0 +1,24 @@
package com.leisuretimedock.jsonem.util;
import net.minecraft.client.model.geom.builders.UVPair;
/**
* Implementation of {@code equals()} on {@link UVPair}
*/
public class Vector2fComparable extends UVPair {
public Vector2fComparable(float x, float y) {
super(x, y);
}
public static Vector2fComparable of(UVPair vec) {
return new Vector2fComparable(vec.u(), vec.v());
}
@Override
public boolean equals(Object obj) {
if (obj instanceof UVPair vec) {
return this.u() == vec.u() && this.v() == vec.v();
}
return super.equals(obj);
}
}

View File

@ -4,6 +4,12 @@
"compatibilityLevel": "JAVA_17",
"minVersion": "0.8",
"client": [
"DilationAccess",
"EntityModelLoaderMixin",
"EntityModelsMixin",
"ModelPartDataAccess",
"TextureDimensionsAccess",
"TexturedModelDataAccess"
],
"mixins": [
],

View File

@ -0,0 +1,23 @@
package com.leisuretimedock.jsonem.fabric;
import com.leisuretimedock.jsonem.fabric.config.JsonEmConfig;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.model.geom.builders.MeshDefinition;
public class JsonEmFabric implements ClientModInitializer {
public static final JsonEmConfig CONFIG = new JsonEmConfig();
@Override
public void onInitializeClient() {
CONFIG.load();
}
public static void registerModelLayer(ModelLayerLocation layer) {
EntityModelLayerRegistry.registerModelLayer(layer, () -> LayerDefinition.create(new MeshDefinition(), 32, 32));
}
}

View File

@ -1,16 +0,0 @@
package com.leisuretimedock.jsonem.fabric;
import com.leisuretimedock.jsonem.Jsonem;
import net.fabricmc.api.ModInitializer;
public final class JsonemFabric implements ModInitializer {
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
// Run our common setup.
Jsonem.init();
}
}

View File

@ -1,10 +0,0 @@
package com.leisuretimedock.jsonem.fabric.client;
import net.fabricmc.api.ClientModInitializer;
public final class JsonemFabricClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
}
}

View File

@ -0,0 +1,49 @@
package com.leisuretimedock.jsonem.fabric.config;
import com.leisuretimedock.jsonem.JsonEm;
import net.fabricmc.loader.api.FabricLoader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Properties;
public final class JsonEmConfig {
public static final Path FILE = FabricLoader.getInstance().getConfigDir().resolve("jsonem.properties");
public final Properties values = new Properties();
private static void defaultValues(Properties values) {
values.setProperty("dump_models", "false");
}
public void load() {
try {
if (!Files.exists(FILE)) {
save();
}
this.values.clear();
try (var in = Files.newInputStream(FILE)) {
this.values.load(in);
}
} catch (IOException ex) {
JsonEm.LOG.error("Error loading config file for Json Entity Models", ex);
}
}
public void save() {
try {
if (!Files.exists(FILE)) {
Files.createFile(FILE);
}
defaultValues(this.values);
try (var out = Files.newOutputStream(FILE)) {
this.values.store(out, null);
}
} catch (IOException ex) {
JsonEm.LOG.error("Error saving config file for Json Entity Models", ex);
}
}
}

View File

@ -0,0 +1,11 @@
package com.leisuretimedock.jsonem.fabric.platform;
import com.leisuretimedock.jsonem.fabric.JsonEmFabric;
import com.leisuretimedock.jsonem.platform.IPlatFormHelper;
public class FabricPlatformHelper implements IPlatFormHelper {
@Override
public boolean shouldDumpModels() {
return "true".equals(JsonEmFabric.CONFIG.values.getProperty("dump_models"));
}
}

View File

@ -0,0 +1 @@
com.leisuretimedock.jsonem.fabric.platform.FabricPlatformHelper

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -15,11 +15,8 @@
"icon": "assets/jsonem/icon.png",
"environment": "*",
"entrypoints": {
"main": [
"com.leisuretimedock.jsonem.fabric.JsonemFabric"
],
"client": [
"com.leisuretimedock.jsonem.fabric.client.JsonemFabricClient"
"com.leisuretimedock.jsonem.fabric.JsonEmFabric"
]
},
"mixins": [

View File

@ -18,6 +18,7 @@ configurations {
canBeResolved = true
canBeConsumed = false
}
shadowCommon
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
developmentForge.extendsFrom common
@ -31,12 +32,11 @@ configurations {
}
dependencies {
compileOnly project(":common")
forge "net.minecraftforge:forge:$rootProject.forge_version"
modImplementation "dev.architectury:architectury-forge:$rootProject.architectury_api_version"
common(project(path: ':common', configuration: 'namedElements')) { transitive false }
shadowBundle project(path: ':common', configuration: 'transformProductionForge')
}
processResources {

View File

@ -0,0 +1,21 @@
package com.leisuretimedock.jsonem.forge;
import com.leisuretimedock.jsonem.JsonEm;
import com.leisuretimedock.jsonem.forge.config.JsonEmConfig;
import dev.architectury.platform.forge.EventBuses;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
@Mod(JsonEm.MOD_ID)
public final class JsonEmForge {
public JsonEmForge(IEventBus eventBus) {
// Submit our event bus to let Architectury API register our content on the right time.
EventBuses.registerModEventBus(JsonEm.MOD_ID, eventBus);
//noinspection removal
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, JsonEmConfig.spec, "jsonem.toml");
// Run our common setup.
JsonEm.init();
}
}

View File

@ -1,18 +0,0 @@
package com.leisuretimedock.jsonem.forge;
import com.leisuretimedock.jsonem.Jsonem;
import dev.architectury.platform.forge.EventBuses;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@Mod(Jsonem.MOD_ID)
public final class JsonemForge {
@SuppressWarnings("removal")
public JsonemForge() {
// Submit our event bus to let Architectury API register our content on the right time.
EventBuses.registerModEventBus(Jsonem.MOD_ID, FMLJavaModLoadingContext.get().getModEventBus());
// Run our common setup.
Jsonem.init();
}
}

View File

@ -0,0 +1,20 @@
package com.leisuretimedock.jsonem.forge.config;
import net.minecraftforge.common.ForgeConfigSpec;
import org.apache.commons.lang3.tuple.Pair;
public class JsonEmConfig {
public static final ForgeConfigSpec spec;
public static final JsonEmConfig INSTANCE;
public final ForgeConfigSpec.BooleanValue DUMP_MODELS;
public JsonEmConfig(ForgeConfigSpec.Builder builder) {
builder.push("jsonem");
DUMP_MODELS = builder.comment("Whether to dump models").define("dump_models", false);
builder.pop();
}
static {
Pair<JsonEmConfig, ForgeConfigSpec> config = new ForgeConfigSpec.Builder().configure(JsonEmConfig::new);
spec = config.getRight();
INSTANCE = config.getLeft();
}
}

View File

@ -0,0 +1,11 @@
package com.leisuretimedock.jsonem.forge.platform;
import com.leisuretimedock.jsonem.forge.config.JsonEmConfig;
import com.leisuretimedock.jsonem.platform.IPlatFormHelper;
public class ForgePlatformHelper implements IPlatFormHelper {
@Override
public boolean shouldDumpModels() {
return JsonEmConfig.INSTANCE.DUMP_MODELS.get();
}
}

View File

@ -11,7 +11,7 @@ authors = "FoundationGames, R3944Realms"
description = '''
Migrate from Fabric 1.20.1
'''
#logoFile = ""
logoFile = "assets/jsonem/icon.png"
[[dependencies.jsonem]]
modId = "forge"

View File

@ -0,0 +1 @@
com.leisuretimedock.jsonem.forge.platform.ForgePlatformHelper

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -12,3 +12,7 @@ rootProject.name = 'jsonem'
include 'common'
include 'fabric'
include 'forge'
project(':common').projectDir = file('common')
project(':forge').projectDir = file('forge')
project(':fabric').projectDir = file('fabric')