minecraft-src/net/minecraft/util/datafix/fixes/VillagerRebuildLevelAndXpFix.java
2025-07-04 01:41:11 +03:00

76 lines
2.7 KiB
Java

package net.minecraft.util.datafix.fixes;
import com.mojang.datafixers.DSL;
import com.mojang.datafixers.DataFix;
import com.mojang.datafixers.OpticFinder;
import com.mojang.datafixers.TypeRewriteRule;
import com.mojang.datafixers.Typed;
import com.mojang.datafixers.schemas.Schema;
import com.mojang.datafixers.types.Type;
import com.mojang.datafixers.types.templates.List.ListType;
import com.mojang.serialization.Dynamic;
import java.util.Optional;
import net.minecraft.util.Mth;
public class VillagerRebuildLevelAndXpFix extends DataFix {
private static final int TRADES_PER_LEVEL = 2;
private static final int[] LEVEL_XP_THRESHOLDS = new int[]{0, 10, 50, 100, 150};
public static int getMinXpPerLevel(int level) {
return LEVEL_XP_THRESHOLDS[Mth.clamp(level - 1, 0, LEVEL_XP_THRESHOLDS.length - 1)];
}
public VillagerRebuildLevelAndXpFix(Schema outputSchema, boolean changesType) {
super(outputSchema, changesType);
}
@Override
public TypeRewriteRule makeRule() {
Type<?> type = this.getInputSchema().getChoiceType(References.ENTITY, "minecraft:villager");
OpticFinder<?> opticFinder = DSL.namedChoice("minecraft:villager", type);
OpticFinder<?> opticFinder2 = type.findField("Offers");
Type<?> type2 = opticFinder2.type();
OpticFinder<?> opticFinder3 = type2.findField("Recipes");
ListType<?> listType = (ListType<?>)opticFinder3.type();
OpticFinder<?> opticFinder4 = listType.getElement().finder();
return this.fixTypeEverywhereTyped(
"Villager level and xp rebuild",
this.getInputSchema().getType(References.ENTITY),
typed -> typed.updateTyped(
opticFinder,
type,
typedx -> {
Dynamic<?> dynamic = typedx.get(DSL.remainderFinder());
int i = dynamic.get("VillagerData").get("level").asInt(0);
Typed<?> typed2 = typedx;
if (i == 0 || i == 1) {
int j = (Integer)typedx.getOptionalTyped(opticFinder2)
.flatMap(typedxx -> typedxx.getOptionalTyped(opticFinder3))
.map(typedxx -> typedxx.getAllTyped(opticFinder4).size())
.orElse(0);
i = Mth.clamp(j / 2, 1, 5);
if (i > 1) {
typed2 = addLevel(typedx, i);
}
}
Optional<Number> optional = dynamic.get("Xp").asNumber().result();
if (optional.isEmpty()) {
typed2 = addXpFromLevel(typed2, i);
}
return typed2;
}
)
);
}
private static Typed<?> addLevel(Typed<?> typed, int level) {
return typed.update(DSL.remainderFinder(), dynamic -> dynamic.update("VillagerData", dynamicx -> dynamicx.set("level", dynamicx.createInt(level))));
}
private static Typed<?> addXpFromLevel(Typed<?> typed, int xp) {
int i = getMinXpPerLevel(xp);
return typed.update(DSL.remainderFinder(), dynamic -> dynamic.set("Xp", dynamic.createInt(i)));
}
}