Add tint override to texture packs

This commit is contained in:
Linnea Gräf
2024-11-01 23:00:53 +01:00
parent 653454e290
commit 8b410fbdf2
29 changed files with 466 additions and 156 deletions

View File

@@ -7,5 +7,6 @@ public class EarlyRiser implements Runnable {
new ClientPlayerRiser().addTinkerers();
new HandledScreenRiser().addTinkerers();
new SectionBuilderRiser().addTinkerers();
new ItemColorsSodiumRiser().addTinkerers();
}
}

View File

@@ -0,0 +1,64 @@
package moe.nea.firmament.init;
import me.shedaniel.mm.api.ClassTinkerers;
import moe.nea.firmament.util.ErrorUtil;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.color.item.ItemColorProvider;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.item.ItemStack;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
public class ItemColorsSodiumRiser extends RiserUtils {
@IntermediaryName(ItemColors.class)
String ItemColors;
@IntermediaryName(ItemColorProvider.class)
String ItemColorProvider;
@IntermediaryName(ItemStack.class)
String ItemStack;
String getColorProvider = "sodium$getColorProvider";
Type getColorProviderDesc = Type.getMethodType(getTypeForClassName(ItemColorProvider),
getTypeForClassName(ItemStack));
@Override
public void addTinkerers() {
ClassTinkerers.addTransformation(ItemColors, this::addSodiumOverride, true);
}
private void addSodiumOverride(ClassNode classNode) {
var node = findMethod(classNode, getColorProvider, getColorProviderDesc);
if (node == null) {
if (!FabricLoader.getInstance().isModLoaded("sodium"))
ErrorUtil.INSTANCE.softError("Sodium is present, but sodium color override could not be injected.");
return;
}
var p = node.instructions.getFirst();
while (p != null) {
if (p.getOpcode() == Opcodes.ARETURN) {
node.instructions.insertBefore(
p,
mkOverrideSodiumCall()
);
}
p = p.getNext();
}
}
private InsnList mkOverrideSodiumCall() {
var insnList = new InsnList();
insnList.add(new VarInsnNode(Opcodes.ALOAD, 0));
insnList.add(new InsnNode(Opcodes.SWAP));
insnList.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
getTypeForClassName(ItemColors).getInternalName(),
"overrideSodium_firmament",
Type.getMethodType(getTypeForClassName(ItemColorProvider),
getTypeForClassName(ItemColorProvider)).getDescriptor(),
false));
return insnList;
}
}

View File

@@ -2,6 +2,7 @@
package moe.nea.firmament.mixins.custommodels;
import moe.nea.firmament.features.texturepack.BakedModelExtra;
import moe.nea.firmament.features.texturepack.TintOverrides;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BasicBakedModel;
import org.jetbrains.annotations.Nullable;
@@ -11,18 +12,31 @@ import org.spongepowered.asm.mixin.Unique;
@Mixin(BasicBakedModel.class)
public class BakedModelDataHolderBasic implements BakedModelExtra {
@Unique
private BakedModel headModel;
@Unique
private BakedModel headModel;
@Unique
@Nullable
private TintOverrides tintOverrides;
@Nullable
@Override
public BakedModel getHeadModel_firmament() {
return headModel;
}
@Nullable
@Override
public BakedModel getHeadModel_firmament() {
return headModel;
}
@Override
public void setHeadModel_firmament(@Nullable BakedModel headModel) {
this.headModel = headModel;
}
@Override
public void setHeadModel_firmament(@Nullable BakedModel headModel) {
this.headModel = headModel;
}
@Override
public @Nullable TintOverrides getTintOverrides_firmament() {
return tintOverrides;
}
@Override
public void setTintOverrides_firmament(@Nullable TintOverrides tintOverrides) {
this.tintOverrides = tintOverrides;
}
}

View File

@@ -2,6 +2,7 @@
package moe.nea.firmament.mixins.custommodels;
import moe.nea.firmament.features.texturepack.BakedModelExtra;
import moe.nea.firmament.features.texturepack.TintOverrides;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BuiltinBakedModel;
import org.jetbrains.annotations.Nullable;
@@ -11,18 +12,32 @@ import org.spongepowered.asm.mixin.Unique;
@Mixin(BuiltinBakedModel.class)
public class BakedModelDataHolderBuiltin implements BakedModelExtra {
@Unique
private BakedModel headModel;
@Unique
@Nullable
private BakedModel headModel;
@Unique
@Nullable
private TintOverrides tintOverrides;
@Nullable
@Override
public BakedModel getHeadModel_firmament() {
return headModel;
}
@Override
public @Nullable TintOverrides getTintOverrides_firmament() {
return tintOverrides;
}
@Override
public void setHeadModel_firmament(@Nullable BakedModel headModel) {
this.headModel = headModel;
}
@Override
public void setTintOverrides_firmament(@Nullable TintOverrides tintOverrides) {
this.tintOverrides = tintOverrides;
}
@Nullable
@Override
public BakedModel getHeadModel_firmament() {
return headModel;
}
@Override
public void setHeadModel_firmament(@Nullable BakedModel headModel) {
this.headModel = headModel;
}
}

View File

@@ -0,0 +1,39 @@
package moe.nea.firmament.mixins.custommodels;
import moe.nea.firmament.features.texturepack.TintOverrides;
import moe.nea.firmament.init.ItemColorsSodiumRiser;
import net.minecraft.client.color.item.ItemColorProvider;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.item.ItemStack;
import org.jetbrains.annotations.Nullable;
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;
@Mixin(ItemColors.class)
public class ItemColorRemovalPatch {
/**
* @see ItemColorsSodiumRiser
*/
private @Nullable ItemColorProvider overrideSodium_firmament(@Nullable ItemColorProvider original) {
var tintOverrides = TintOverrides.Companion.getCurrentOverrides();
if (!tintOverrides.hasOverrides()) return original;
return (stack, tintIndex) -> {
var override = tintOverrides.getOverride(tintIndex);
if (override != null) return override;
if (original != null) return original.getColor(stack, tintIndex);
return -1;
};
}
@Inject(method = "getColor", at = @At("HEAD"), cancellable = true)
private void overrideGetColorCall(ItemStack item, int tintIndex, CallbackInfoReturnable<Integer> cir) {
var tintOverrides = TintOverrides.Companion.getCurrentOverrides();
var override = tintOverrides.getOverride(tintIndex);
if (override != null)
cir.setReturnValue(override);
}
}

View File

@@ -12,8 +12,11 @@ import org.spongepowered.asm.mixin.injection.At;
@Mixin(ItemModelGenerator.class)
public class ItemModelGeneratorJsonUnbakedModelCopy {
@ModifyReturnValue(method = "create", at = @At("RETURN"))
private JsonUnbakedModel copyHeadModel(JsonUnbakedModel original, @Local(argsOnly = true) JsonUnbakedModel oldModel) {
((JsonUnbakedModelFirmExtra) original).setHeadModel_firmament(((JsonUnbakedModelFirmExtra) oldModel).getHeadModel_firmament());
private JsonUnbakedModel copyExtraModelData(JsonUnbakedModel original, @Local(argsOnly = true) JsonUnbakedModel oldModel) {
var extra = ((JsonUnbakedModelFirmExtra) original);
var oldExtra = ((JsonUnbakedModelFirmExtra) oldModel);
extra.setHeadModel_firmament(oldExtra.getHeadModel_firmament());
extra.setTintOverrides_firmament(oldExtra.getTintOverrides_firmament());
return original;
}
}

View File

@@ -0,0 +1,33 @@
package moe.nea.firmament.mixins.custommodels;
import moe.nea.firmament.features.texturepack.BakedModelExtra;
import moe.nea.firmament.features.texturepack.TintOverrides;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ItemRenderer.class)
public class ItemRendererTintContextPatch {
@Inject(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/BakedModel;getTransformation()Lnet/minecraft/client/render/model/json/ModelTransformation;"), allow = 1)
private void onStartRendering(ItemStack stack, ModelTransformationMode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model, CallbackInfo ci) {
if (model instanceof BakedModelExtra extra) {
TintOverrides.Companion.enter(extra.getTintOverrides_firmament());
}
}
@Inject(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;pop()V"), allow = 1)
private void onEndRendering(ItemStack stack, ModelTransformationMode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model, CallbackInfo ci) {
if (model instanceof BakedModelExtra extra) {
TintOverrides.Companion.exit(extra.getTintOverrides_firmament());
}
}
}

View File

@@ -1,4 +1,3 @@
package moe.nea.firmament.mixins.custommodels;
import com.google.gson.annotations.SerializedName;
@@ -6,12 +5,14 @@ import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.features.texturepack.BakedModelExtra;
import moe.nea.firmament.features.texturepack.JsonUnbakedModelFirmExtra;
import moe.nea.firmament.features.texturepack.TintOverrides;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.Baker;
import net.minecraft.client.render.model.ModelRotation;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.render.model.json.JsonUnbakedModel;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -23,46 +24,74 @@ import java.util.Objects;
@Mixin(JsonUnbakedModel.class)
public class JsonUnbakedModelDataHolder implements JsonUnbakedModelFirmExtra {
@Shadow
@Nullable
protected JsonUnbakedModel parent;
@Unique
@Nullable
public Identifier headModel;
@Shadow
@Nullable
protected JsonUnbakedModel parent;
@Unique
@Nullable
public Identifier headModel;
@Unique
@Nullable
public TintOverrides tintOverrides;
@Unique
@Nullable
public TintOverrides mergedTintOverrides;
@Override
public void setHeadModel_firmament(@Nullable Identifier identifier) {
this.headModel = identifier;
}
@Override
public void setTintOverrides_firmament(@Nullable TintOverrides tintOverrides) {
this.tintOverrides = tintOverrides;
this.mergedTintOverrides = null;
}
@Override
public @Nullable Identifier getHeadModel_firmament() {
if (this.headModel != null) return this.headModel;
if (this.parent == null) return null;
return ((JsonUnbakedModelFirmExtra) this.parent).getHeadModel_firmament();
}
@Override
public @NotNull TintOverrides getTintOverrides_firmament() {
if (mergedTintOverrides != null)
return mergedTintOverrides;
var mergedTintOverrides = parent == null ? new TintOverrides()
: ((JsonUnbakedModelFirmExtra) parent).getTintOverrides_firmament();
if (tintOverrides != null)
mergedTintOverrides = tintOverrides.mergeWithParent(mergedTintOverrides);
this.mergedTintOverrides = mergedTintOverrides;
return mergedTintOverrides;
}
@ModifyReturnValue(method = "getModelDependencies", at = @At("RETURN"))
private Collection<Identifier> addDependencies(Collection<Identifier> original) {
var headModel = getHeadModel_firmament();
if (headModel != null) {
original.add(headModel);
}
return original;
}
@Override
public void setHeadModel_firmament(@Nullable Identifier identifier) {
this.headModel = identifier;
}
@ModifyReturnValue(
method = "bake(Lnet/minecraft/client/render/model/Baker;Lnet/minecraft/client/render/model/json/JsonUnbakedModel;Ljava/util/function/Function;Lnet/minecraft/client/render/model/ModelBakeSettings;Z)Lnet/minecraft/client/render/model/BakedModel;",
at = @At(value = "RETURN"))
private BakedModel bakeExtraInfo(BakedModel original, @Local(argsOnly = true) Baker baker) {
var headModel = getHeadModel_firmament();
if (headModel != null && original instanceof BakedModelExtra extra) {
UnbakedModel unbakedModel = baker.getOrLoadModel(headModel);
extra.setHeadModel_firmament(
Objects.equals(unbakedModel, parent)
? null
: baker.bake(headModel, ModelRotation.X0_Y0));
}
return original;
}
@Override
public @Nullable Identifier getHeadModel_firmament() {
if (this.headModel != null) return this.headModel;
if (this.parent == null) return null;
return ((JsonUnbakedModelFirmExtra) this.parent).getHeadModel_firmament();
}
@ModifyReturnValue(method = "getModelDependencies", at = @At("RETURN"))
private Collection<Identifier> addDependencies(Collection<Identifier> original) {
var headModel = getHeadModel_firmament();
if (headModel != null) {
original.add(headModel);
}
return original;
}
@ModifyReturnValue(
method = "bake(Lnet/minecraft/client/render/model/Baker;Lnet/minecraft/client/render/model/json/JsonUnbakedModel;Ljava/util/function/Function;Lnet/minecraft/client/render/model/ModelBakeSettings;Z)Lnet/minecraft/client/render/model/BakedModel;",
at = @At(value = "RETURN"))
private BakedModel bakeExtraInfo(BakedModel original, @Local(argsOnly = true) Baker baker) {
if (original instanceof BakedModelExtra extra) {
var headModel = getHeadModel_firmament();
if (headModel != null) {
UnbakedModel unbakedModel = baker.getOrLoadModel(headModel);
extra.setHeadModel_firmament(
Objects.equals(unbakedModel, parent)
? null
: baker.bake(headModel, ModelRotation.X0_Y0));
}
if (getTintOverrides_firmament().hasOverrides())
extra.setTintOverrides_firmament(getTintOverrides_firmament());
}
return original;
}
}

View File

@@ -6,6 +6,7 @@ import com.google.gson.JsonPrimitive;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.features.texturepack.JsonUnbakedModelFirmExtra;
import moe.nea.firmament.features.texturepack.TintOverrides;
import net.minecraft.client.render.model.json.JsonUnbakedModel;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
@@ -13,13 +14,18 @@ import org.spongepowered.asm.mixin.injection.At;
@Mixin(JsonUnbakedModel.Deserializer.class)
public class PatchJsonUnbakedModelDeserializer {
@ModifyReturnValue(method = "deserialize(Lcom/google/gson/JsonElement;Ljava/lang/reflect/Type;Lcom/google/gson/JsonDeserializationContext;)Lnet/minecraft/client/render/model/json/JsonUnbakedModel;",
at = @At("RETURN"))
private JsonUnbakedModel addHeadModel(JsonUnbakedModel original, @Local JsonObject jsonObject) {
var headModel = jsonObject.get("firmament:head_model");
if (headModel instanceof JsonPrimitive prim && prim.isString()) {
((JsonUnbakedModelFirmExtra) original).setHeadModel_firmament(Identifier.of(prim.getAsString()));
}
return original;
}
@ModifyReturnValue(method = "deserialize(Lcom/google/gson/JsonElement;Ljava/lang/reflect/Type;Lcom/google/gson/JsonDeserializationContext;)Lnet/minecraft/client/render/model/json/JsonUnbakedModel;",
at = @At("RETURN"))
private JsonUnbakedModel addHeadModel(JsonUnbakedModel original, @Local JsonObject jsonObject) {
var headModel = jsonObject.get("firmament:head_model");
var extra = ((JsonUnbakedModelFirmExtra) original);
if (headModel instanceof JsonPrimitive prim && prim.isString()) {
extra.setHeadModel_firmament(Identifier.of(prim.getAsString()));
}
var tintOverrides = jsonObject.get("firmament:tint_overrides");
if (tintOverrides instanceof JsonObject object) {
extra.setTintOverrides_firmament(TintOverrides.Companion.parse(object));
}
return original;
}
}

View File

@@ -4,6 +4,8 @@ package moe.nea.firmament.features.texturepack
import net.minecraft.client.render.model.BakedModel
interface BakedModelExtra {
fun getHeadModel_firmament(): BakedModel?
var tintOverrides_firmament: TintOverrides?
fun getHeadModel_firmament(): BakedModel?
fun setHeadModel_firmament(headModel: BakedModel?)
}

View File

@@ -6,6 +6,14 @@ import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import moe.nea.firmament.features.texturepack.predicates.AndPredicate
import moe.nea.firmament.features.texturepack.predicates.DisplayNamePredicate
import moe.nea.firmament.features.texturepack.predicates.ExtraAttributesPredicate
import moe.nea.firmament.features.texturepack.predicates.ItemPredicate
import moe.nea.firmament.features.texturepack.predicates.LorePredicate
import moe.nea.firmament.features.texturepack.predicates.NotPredicate
import moe.nea.firmament.features.texturepack.predicates.OrPredicate
import moe.nea.firmament.features.texturepack.predicates.PetPredicate
import net.minecraft.item.ItemStack
import net.minecraft.util.Identifier

View File

@@ -7,4 +7,8 @@ interface JsonUnbakedModelFirmExtra {
fun setHeadModel_firmament(identifier: Identifier?)
fun getHeadModel_firmament(): Identifier?
fun setTintOverrides_firmament(tintOverrides: TintOverrides?)
fun getTintOverrides_firmament(): TintOverrides
}

View File

@@ -1,19 +0,0 @@
package moe.nea.firmament.features.texturepack
import com.google.gson.JsonElement
import moe.nea.firmament.util.filter.IteratorFilterSet
class ModelOverrideFilterSet(original: java.util.Set<Map.Entry<String, JsonElement>>) :
IteratorFilterSet<Map.Entry<String, JsonElement>>(original) {
companion object {
@JvmStatic
fun createFilterSet(set: java.util.Set<*>): java.util.Set<*> {
return ModelOverrideFilterSet(set as java.util.Set<Map.Entry<String, JsonElement>>) as java.util.Set<*>
}
}
override fun shouldKeepElement(element: Map.Entry<String, JsonElement>): Boolean {
return !element.key.startsWith("firmament:")
}
}

View File

@@ -0,0 +1,75 @@
package moe.nea.firmament.features.texturepack
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import moe.nea.firmament.util.ErrorUtil
import moe.nea.firmament.util.assertNotNullOr
data class TintOverrides(
val layerMap: Map<Int, TintOverride> = mapOf()
) {
val hasOverrides by lazy { layerMap.values.any { it !is Reset } }
companion object {
val EMPTY = TintOverrides()
private val threadLocal = object : ThreadLocal<TintOverrides>() {}
fun enter(overrides: TintOverrides?) {
ErrorUtil.softCheck("Double entered tintOverrides") {
threadLocal.get() == null
}
threadLocal.set(overrides ?: EMPTY)
}
fun exit(overrides: TintOverrides?) {
ErrorUtil.softCheck("Exited with non matching enter tintOverrides") {
threadLocal.get() == (overrides ?: EMPTY)
}
threadLocal.remove()
}
fun getCurrentOverrides() =
assertNotNullOr(threadLocal.get(), "Got current tintOverrides without entering") { EMPTY }
fun parse(jsonObject: JsonObject): TintOverrides {
val map = mutableMapOf<Int, TintOverride>()
for ((key, value) in jsonObject.entrySet()) {
val layerIndex =
ErrorUtil.notNullOr(key.toIntOrNull(),
"Unknown layer index $value. Should be integer") { continue }
if (value.isJsonNull) {
map[layerIndex] = Reset
continue
}
val override = (value as? JsonPrimitive)
?.takeIf(JsonPrimitive::isNumber)
?.asInt
?.let(::Fixed)
if (override == null) {
ErrorUtil.softError("Invalid tint override for a layer: $value")
continue
}
map[layerIndex] = override
}
return TintOverrides(map)
}
}
fun mergeWithParent(parent: TintOverrides): TintOverrides {
val mergedMap = parent.layerMap.toMutableMap()
mergedMap.putAll(this.layerMap)
return TintOverrides(mergedMap)
}
fun hasOverrides(): Boolean = hasOverrides
fun getOverride(tintIndex: Int): Int? {
return when (val tint = layerMap[tintIndex]) {
is Reset -> null
is Fixed -> tint.color
null -> null
}
}
sealed interface TintOverride
data object Reset : TintOverride
data class Fixed(val color: Int) : TintOverride
}

View File

@@ -1,7 +1,9 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import net.minecraft.item.ItemStack
object AlwaysPredicate : FirmamentModelPredicate {

View File

@@ -1,8 +1,11 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import moe.nea.firmament.features.texturepack.CustomModelOverrideParser
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import net.minecraft.item.ItemStack
class AndPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {
@@ -15,7 +18,7 @@ class AndPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentMode
val children =
(jsonElement as JsonArray)
.flatMap {
CustomModelOverrideParser.parsePredicates(it as JsonObject)
CustomModelOverrideParser.parsePredicates(it as JsonObject)
}
.toTypedArray()
return AndPredicate(children)

View File

@@ -1,12 +1,12 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.StringMatcher
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtElement
import net.minecraft.nbt.NbtString
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.loreAccordingToNbt
data class DisplayNamePredicate(val stringMatcher: StringMatcher) : FirmamentModelPredicate {
override fun test(stack: ItemStack): Boolean {

View File

@@ -1,10 +1,13 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.StringMatcher
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtByte
import net.minecraft.nbt.NbtCompound
@@ -210,8 +213,8 @@ fun interface NbtMatcher {
}
data class ExtraAttributesPredicate(
val path: NbtPrism,
val matcher: NbtMatcher,
val path: NbtPrism,
val matcher: NbtMatcher,
) : FirmamentModelPredicate {
object Parser : FirmamentModelPredicateParser {

View File

@@ -1,8 +1,10 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import kotlin.jvm.optionals.getOrNull
import net.minecraft.item.Item
import net.minecraft.item.ItemStack

View File

@@ -1,7 +1,10 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.StringMatcher
import net.minecraft.item.ItemStack
import moe.nea.firmament.util.mc.loreAccordingToNbt

View File

@@ -1,8 +1,11 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import moe.nea.firmament.features.texturepack.CustomModelOverrideParser
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import net.minecraft.item.ItemStack
class NotPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {

View File

@@ -1,4 +1,4 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive

View File

@@ -1,9 +1,12 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import moe.nea.firmament.features.texturepack.CustomModelOverrideParser
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import net.minecraft.item.ItemStack
class OrPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {
@@ -16,7 +19,7 @@ class OrPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModel
val children =
(jsonElement as JsonArray)
.flatMap {
CustomModelOverrideParser.parsePredicates(it as JsonObject)
CustomModelOverrideParser.parsePredicates(it as JsonObject)
}
.toTypedArray()
return OrPredicate(children)

View File

@@ -1,18 +1,22 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.RarityMatcher
import moe.nea.firmament.features.texturepack.StringMatcher
import net.minecraft.item.ItemStack
import moe.nea.firmament.repo.ExpLadders
import moe.nea.firmament.util.petData
class PetPredicate(
val petId: StringMatcher?,
val tier: RarityMatcher?,
val exp: NumberMatcher?,
val candyUsed: NumberMatcher?,
val level: NumberMatcher?,
data class PetPredicate(
val petId: StringMatcher?,
val tier: RarityMatcher?,
val exp: NumberMatcher?,
val candyUsed: NumberMatcher?,
val level: NumberMatcher?,
) : FirmamentModelPredicate {
override fun test(stack: ItemStack): Boolean {
@@ -59,8 +63,4 @@ class PetPredicate(
)
}
}
override fun toString(): String {
return super.toString()
}
}

View File

@@ -9,13 +9,13 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
import kotlinx.coroutines.launch
import net.minecraft.client.MinecraftClient
import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
import net.minecraft.text.Text
import moe.nea.firmament.Firmament
import moe.nea.firmament.Firmament.logger
import moe.nea.firmament.events.ReloadRegistrationEvent
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.MinecraftDispatcher
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.tr
object RepoManager {
object Config : ManagedConfig("repo", Category.META) {
@@ -108,12 +108,13 @@ object RepoManager {
try {
ItemCache.ReloadProgressHud.reportProgress("Reloading from Disk",
0,
-1) // TODO: replace with a proper boundy bar
-1) // TODO: replace with a proper bouncy bar
ItemCache.ReloadProgressHud.isEnabled = true
neuRepo.reload()
} catch (exc: NEURepositoryException) {
MinecraftClient.getInstance().player?.sendMessage(
Text.literal("Failed to reload repository. This will result in some mod features not working.")
tr("firmament.repo.reloadfail",
"Failed to reload repository. This will result in some mod features not working.")
)
ItemCache.ReloadProgressHud.isEnabled = false
exc.printStackTrace()

View File

@@ -7,10 +7,24 @@ object ErrorUtil {
Thread.currentThread().stackTrace.any { it.className.startsWith("org.junit.") } || Firmament.DEBUG
}
inline fun softCheck(message: String, func: () -> Boolean) {
if (!aggressiveErrors) return
if (func()) return
error(message)
}
@Suppress("NOTHING_TO_INLINE") // Suppressed since i want the logger to not pick up the ErrorUtil stack-frame
inline fun softError(message: String) {
if (aggressiveErrors) error(message)
else Firmament.logger.error(message)
}
inline fun <T : Any> notNullOr(nullable: T?, message: String, orElse: () -> T): T {
if (nullable == null) {
softError(message)
return orElse()
}
return nullable
}
}

View File

@@ -1,33 +0,0 @@
package moe.nea.firmament.util.filter
abstract class IteratorFilterSet<K>(val original: java.util.Set<K>) : java.util.Set<K> by original {
abstract fun shouldKeepElement(element: K): Boolean
override fun iterator(): MutableIterator<K> {
val parentIterator = original.iterator()
return object : MutableIterator<K> {
var lastEntry: K? = null
override fun hasNext(): Boolean {
while (lastEntry == null) {
if (!parentIterator.hasNext())
break
val element = parentIterator.next()
if (!shouldKeepElement(element)) continue
lastEntry = element
}
return lastEntry != null
}
override fun next(): K {
if (!hasNext()) throw NoSuchElementException()
return lastEntry ?: throw NoSuchElementException()
}
override fun remove() {
TODO("Not yet implemented")
}
}
}
}