198 lines
9.3 KiB
Java
198 lines
9.3 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.DSL.TypeReference;
|
|
import com.mojang.datafixers.schemas.Schema;
|
|
import com.mojang.datafixers.types.Type;
|
|
import com.mojang.datafixers.util.Pair;
|
|
import com.mojang.serialization.Dynamic;
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
import java.util.Optional;
|
|
import java.util.Set;
|
|
import java.util.function.Function;
|
|
import java.util.stream.Stream;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.util.datafix.schemas.NamespacedSchema;
|
|
|
|
public class MobEffectIdFix extends DataFix {
|
|
private static final Int2ObjectMap<String> ID_MAP = Util.make(new Int2ObjectOpenHashMap<>(), int2ObjectOpenHashMap -> {
|
|
int2ObjectOpenHashMap.put(1, "minecraft:speed");
|
|
int2ObjectOpenHashMap.put(2, "minecraft:slowness");
|
|
int2ObjectOpenHashMap.put(3, "minecraft:haste");
|
|
int2ObjectOpenHashMap.put(4, "minecraft:mining_fatigue");
|
|
int2ObjectOpenHashMap.put(5, "minecraft:strength");
|
|
int2ObjectOpenHashMap.put(6, "minecraft:instant_health");
|
|
int2ObjectOpenHashMap.put(7, "minecraft:instant_damage");
|
|
int2ObjectOpenHashMap.put(8, "minecraft:jump_boost");
|
|
int2ObjectOpenHashMap.put(9, "minecraft:nausea");
|
|
int2ObjectOpenHashMap.put(10, "minecraft:regeneration");
|
|
int2ObjectOpenHashMap.put(11, "minecraft:resistance");
|
|
int2ObjectOpenHashMap.put(12, "minecraft:fire_resistance");
|
|
int2ObjectOpenHashMap.put(13, "minecraft:water_breathing");
|
|
int2ObjectOpenHashMap.put(14, "minecraft:invisibility");
|
|
int2ObjectOpenHashMap.put(15, "minecraft:blindness");
|
|
int2ObjectOpenHashMap.put(16, "minecraft:night_vision");
|
|
int2ObjectOpenHashMap.put(17, "minecraft:hunger");
|
|
int2ObjectOpenHashMap.put(18, "minecraft:weakness");
|
|
int2ObjectOpenHashMap.put(19, "minecraft:poison");
|
|
int2ObjectOpenHashMap.put(20, "minecraft:wither");
|
|
int2ObjectOpenHashMap.put(21, "minecraft:health_boost");
|
|
int2ObjectOpenHashMap.put(22, "minecraft:absorption");
|
|
int2ObjectOpenHashMap.put(23, "minecraft:saturation");
|
|
int2ObjectOpenHashMap.put(24, "minecraft:glowing");
|
|
int2ObjectOpenHashMap.put(25, "minecraft:levitation");
|
|
int2ObjectOpenHashMap.put(26, "minecraft:luck");
|
|
int2ObjectOpenHashMap.put(27, "minecraft:unluck");
|
|
int2ObjectOpenHashMap.put(28, "minecraft:slow_falling");
|
|
int2ObjectOpenHashMap.put(29, "minecraft:conduit_power");
|
|
int2ObjectOpenHashMap.put(30, "minecraft:dolphins_grace");
|
|
int2ObjectOpenHashMap.put(31, "minecraft:bad_omen");
|
|
int2ObjectOpenHashMap.put(32, "minecraft:hero_of_the_village");
|
|
int2ObjectOpenHashMap.put(33, "minecraft:darkness");
|
|
});
|
|
private static final Set<String> MOB_EFFECT_INSTANCE_CARRIER_ITEMS = Set.of(
|
|
"minecraft:potion", "minecraft:splash_potion", "minecraft:lingering_potion", "minecraft:tipped_arrow"
|
|
);
|
|
|
|
public MobEffectIdFix(Schema outputSchema) {
|
|
super(outputSchema, false);
|
|
}
|
|
|
|
private static <T> Optional<Dynamic<T>> getAndConvertMobEffectId(Dynamic<T> dynamic, String key) {
|
|
return dynamic.get(key).asNumber().result().map(number -> ID_MAP.get(number.intValue())).map(dynamic::createString);
|
|
}
|
|
|
|
private static <T> Dynamic<T> updateMobEffectIdField(Dynamic<T> oldDynamic, String oldName, Dynamic<T> newDynamic, String newName) {
|
|
Optional<Dynamic<T>> optional = getAndConvertMobEffectId(oldDynamic, oldName);
|
|
return newDynamic.replaceField(oldName, newName, optional);
|
|
}
|
|
|
|
private static <T> Dynamic<T> updateMobEffectIdField(Dynamic<T> dynamic, String oldName, String newName) {
|
|
return updateMobEffectIdField(dynamic, oldName, dynamic, newName);
|
|
}
|
|
|
|
private static <T> Dynamic<T> updateMobEffectInstance(Dynamic<T> dynamic) {
|
|
dynamic = updateMobEffectIdField(dynamic, "Id", "id");
|
|
dynamic = dynamic.renameField("Ambient", "ambient");
|
|
dynamic = dynamic.renameField("Amplifier", "amplifier");
|
|
dynamic = dynamic.renameField("Duration", "duration");
|
|
dynamic = dynamic.renameField("ShowParticles", "show_particles");
|
|
dynamic = dynamic.renameField("ShowIcon", "show_icon");
|
|
Optional<Dynamic<T>> optional = dynamic.get("HiddenEffect").result().map(MobEffectIdFix::updateMobEffectInstance);
|
|
return dynamic.replaceField("HiddenEffect", "hidden_effect", optional);
|
|
}
|
|
|
|
private static <T> Dynamic<T> updateMobEffectInstanceList(Dynamic<T> tag, String oldName, String newName) {
|
|
Optional<Dynamic<T>> optional = tag.get(oldName).asStreamOpt().result().map(stream -> tag.createList(stream.map(MobEffectIdFix::updateMobEffectInstance)));
|
|
return tag.replaceField(oldName, newName, optional);
|
|
}
|
|
|
|
private static <T> Dynamic<T> updateSuspiciousStewEntry(Dynamic<T> oldDynamic, Dynamic<T> newDynamic) {
|
|
newDynamic = updateMobEffectIdField(oldDynamic, "EffectId", newDynamic, "id");
|
|
Optional<Dynamic<T>> optional = oldDynamic.get("EffectDuration").result();
|
|
return newDynamic.replaceField("EffectDuration", "duration", optional);
|
|
}
|
|
|
|
private static <T> Dynamic<T> updateSuspiciousStewEntry(Dynamic<T> suspiciousStewEntry) {
|
|
return updateSuspiciousStewEntry(suspiciousStewEntry, suspiciousStewEntry);
|
|
}
|
|
|
|
private Typed<?> updateNamedChoice(Typed<?> typed, TypeReference reference, String id, Function<Dynamic<?>, Dynamic<?>> fixer) {
|
|
Type<?> type = this.getInputSchema().getChoiceType(reference, id);
|
|
Type<?> type2 = this.getOutputSchema().getChoiceType(reference, id);
|
|
return typed.updateTyped(DSL.namedChoice(id, type), type2, typedx -> typedx.update(DSL.remainderFinder(), fixer));
|
|
}
|
|
|
|
private TypeRewriteRule blockEntityFixer() {
|
|
Type<?> type = this.getInputSchema().getType(References.BLOCK_ENTITY);
|
|
return this.fixTypeEverywhereTyped(
|
|
"BlockEntityMobEffectIdFix", type, typed -> this.updateNamedChoice(typed, References.BLOCK_ENTITY, "minecraft:beacon", dynamic -> {
|
|
dynamic = updateMobEffectIdField(dynamic, "Primary", "primary_effect");
|
|
return updateMobEffectIdField(dynamic, "Secondary", "secondary_effect");
|
|
})
|
|
);
|
|
}
|
|
|
|
private static <T> Dynamic<T> fixMooshroomTag(Dynamic<T> mooshroomTag) {
|
|
Dynamic<T> dynamic = mooshroomTag.emptyMap();
|
|
Dynamic<T> dynamic2 = updateSuspiciousStewEntry(mooshroomTag, dynamic);
|
|
if (!dynamic2.equals(dynamic)) {
|
|
mooshroomTag = mooshroomTag.set("stew_effects", mooshroomTag.createList(Stream.of(dynamic2)));
|
|
}
|
|
|
|
return mooshroomTag.remove("EffectId").remove("EffectDuration");
|
|
}
|
|
|
|
private static <T> Dynamic<T> fixArrowTag(Dynamic<T> arrowTag) {
|
|
return updateMobEffectInstanceList(arrowTag, "CustomPotionEffects", "custom_potion_effects");
|
|
}
|
|
|
|
private static <T> Dynamic<T> fixAreaEffectCloudTag(Dynamic<T> areaEffectCloudTag) {
|
|
return updateMobEffectInstanceList(areaEffectCloudTag, "Effects", "effects");
|
|
}
|
|
|
|
private static Dynamic<?> updateLivingEntityTag(Dynamic<?> livingEntityTag) {
|
|
return updateMobEffectInstanceList(livingEntityTag, "ActiveEffects", "active_effects");
|
|
}
|
|
|
|
private TypeRewriteRule entityFixer() {
|
|
Type<?> type = this.getInputSchema().getType(References.ENTITY);
|
|
return this.fixTypeEverywhereTyped("EntityMobEffectIdFix", type, typed -> {
|
|
typed = this.updateNamedChoice(typed, References.ENTITY, "minecraft:mooshroom", MobEffectIdFix::fixMooshroomTag);
|
|
typed = this.updateNamedChoice(typed, References.ENTITY, "minecraft:arrow", MobEffectIdFix::fixArrowTag);
|
|
typed = this.updateNamedChoice(typed, References.ENTITY, "minecraft:area_effect_cloud", MobEffectIdFix::fixAreaEffectCloudTag);
|
|
return typed.update(DSL.remainderFinder(), MobEffectIdFix::updateLivingEntityTag);
|
|
});
|
|
}
|
|
|
|
private TypeRewriteRule playerFixer() {
|
|
Type<?> type = this.getInputSchema().getType(References.PLAYER);
|
|
return this.fixTypeEverywhereTyped("PlayerMobEffectIdFix", type, typed -> typed.update(DSL.remainderFinder(), MobEffectIdFix::updateLivingEntityTag));
|
|
}
|
|
|
|
private static <T> Dynamic<T> fixSuspiciousStewTag(Dynamic<T> suspiciousStewTag) {
|
|
Optional<Dynamic<T>> optional = suspiciousStewTag.get("Effects")
|
|
.asStreamOpt()
|
|
.result()
|
|
.map(stream -> suspiciousStewTag.createList(stream.map(MobEffectIdFix::updateSuspiciousStewEntry)));
|
|
return suspiciousStewTag.replaceField("Effects", "effects", optional);
|
|
}
|
|
|
|
private TypeRewriteRule itemStackFixer() {
|
|
OpticFinder<Pair<String, String>> opticFinder = DSL.fieldFinder("id", DSL.named(References.ITEM_NAME.typeName(), NamespacedSchema.namespacedString()));
|
|
Type<?> type = this.getInputSchema().getType(References.ITEM_STACK);
|
|
OpticFinder<?> opticFinder2 = type.findField("tag");
|
|
return this.fixTypeEverywhereTyped(
|
|
"ItemStackMobEffectIdFix",
|
|
type,
|
|
typed -> {
|
|
Optional<Pair<String, String>> optional = typed.getOptional(opticFinder);
|
|
if (optional.isPresent()) {
|
|
String string = (String)((Pair)optional.get()).getSecond();
|
|
if (string.equals("minecraft:suspicious_stew")) {
|
|
return typed.updateTyped(opticFinder2, typedx -> typedx.update(DSL.remainderFinder(), MobEffectIdFix::fixSuspiciousStewTag));
|
|
}
|
|
|
|
if (MOB_EFFECT_INSTANCE_CARRIER_ITEMS.contains(string)) {
|
|
return typed.updateTyped(
|
|
opticFinder2,
|
|
typedx -> typedx.update(DSL.remainderFinder(), dynamic -> updateMobEffectInstanceList(dynamic, "CustomPotionEffects", "custom_potion_effects"))
|
|
);
|
|
}
|
|
}
|
|
|
|
return typed;
|
|
}
|
|
);
|
|
}
|
|
|
|
@Override
|
|
protected TypeRewriteRule makeRule() {
|
|
return TypeRewriteRule.seq(this.blockEntityFixer(), this.entityFixer(), this.playerFixer(), this.itemStackFixer());
|
|
}
|
|
}
|