使用塔吊API 将该项目 跨模组加载器化
This commit is contained in:
parent
a0d9841112
commit
600d628dec
|
|
@ -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.
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.leisuretimedock.jsonem.platform;
|
||||
|
||||
public interface IPlatFormHelper {
|
||||
boolean shouldDumpModels();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,12 @@
|
|||
"compatibilityLevel": "JAVA_17",
|
||||
"minVersion": "0.8",
|
||||
"client": [
|
||||
"DilationAccess",
|
||||
"EntityModelLoaderMixin",
|
||||
"EntityModelsMixin",
|
||||
"ModelPartDataAccess",
|
||||
"TextureDimensionsAccess",
|
||||
"TexturedModelDataAccess"
|
||||
],
|
||||
"mixins": [
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
com.leisuretimedock.jsonem.fabric.platform.FabricPlatformHelper
|
||||
BIN
fabric/src/main/resources/assets/jsonem/icon.png
Normal file
BIN
fabric/src/main/resources/assets/jsonem/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
|
|
@ -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": [
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ authors = "FoundationGames, R3944Realms"
|
|||
description = '''
|
||||
Migrate from Fabric 1.20.1
|
||||
'''
|
||||
#logoFile = ""
|
||||
logoFile = "assets/jsonem/icon.png"
|
||||
|
||||
[[dependencies.jsonem]]
|
||||
modId = "forge"
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
com.leisuretimedock.jsonem.forge.platform.ForgePlatformHelper
|
||||
BIN
forge/src/main/resources/assets/jsonem/icon.png
Normal file
BIN
forge/src/main/resources/assets/jsonem/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
|
|
@ -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')
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user