package net.minecraft.util.datafix.fixes; import com.mojang.datafixers.DSL; import com.mojang.datafixers.DataFix; import com.mojang.datafixers.TypeRewriteRule; import com.mojang.datafixers.schemas.Schema; import com.mojang.datafixers.types.Type; import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Unit; import com.mojang.serialization.Dynamic; import com.mojang.serialization.DynamicOps; import java.net.URI; import java.net.URISyntaxException; import java.util.List; import java.util.Locale; import java.util.Optional; import javax.annotation.Nullable; import net.minecraft.Util; import net.minecraft.util.datafix.ExtraDataFixUtils; public class TextComponentHoverAndClickEventFix extends DataFix { public TextComponentHoverAndClickEventFix(Schema p_392221_) { super(p_392221_, true); } @Override protected TypeRewriteRule makeRule() { Type> type = (Type>)this.getInputSchema().getType(References.TEXT_COMPONENT).findFieldType("hoverEvent"); return this.createFixer(this.getInputSchema().getTypeRaw(References.TEXT_COMPONENT), this.getOutputSchema().getType(References.TEXT_COMPONENT), type); } private > TypeRewriteRule createFixer(Type p_394191_, Type p_396398_, Type p_393938_) { Type>, Pair, Unit>, Pair, Pair, Dynamic>>>>>> type = DSL.named( References.TEXT_COMPONENT.typeName(), DSL.or( DSL.or(DSL.string(), DSL.list(p_394191_)), DSL.and( DSL.optional(DSL.field("extra", DSL.list(p_394191_))), DSL.optional(DSL.field("separator", p_394191_)), DSL.optional(DSL.field("hoverEvent", p_393938_)), DSL.remainderType() ) ) ); if (!type.equals(this.getInputSchema().getType(References.TEXT_COMPONENT))) { throw new IllegalStateException( "Text component type did not match, expected " + type + " but got " + this.getInputSchema().getType(References.TEXT_COMPONENT) ); } else { Type type1 = ExtraDataFixUtils.patchSubType(type, type, p_396398_); return this.fixTypeEverywhere( "TextComponentHoverAndClickEventFix", type, p_396398_, p_392390_ -> p_396871_ -> { boolean flag = p_396871_.getSecond().map(p_396868_ -> false, p_392755_ -> { Pair, Dynamic> pair = p_392755_.getSecond().getSecond(); boolean flag1 = pair.getFirst().left().isPresent(); boolean flag2 = pair.getSecond().get("clickEvent").result().isPresent(); return flag1 || flag2; }); return (C2)(!flag ? p_396871_ : Util.writeAndReadTypedOrThrow(ExtraDataFixUtils.cast(type1, p_396871_, p_392390_), p_396398_, TextComponentHoverAndClickEventFix::fixTextComponent) .getValue()); } ); } } private static Dynamic fixTextComponent(Dynamic p_393778_) { return p_393778_.renameAndFixField("hoverEvent", "hover_event", TextComponentHoverAndClickEventFix::fixHoverEvent) .renameAndFixField("clickEvent", "click_event", TextComponentHoverAndClickEventFix::fixClickEvent); } private static Dynamic copyFields(Dynamic p_394161_, Dynamic p_393015_, String... p_396190_) { for (String s : p_396190_) { p_394161_ = Dynamic.copyField(p_393015_, s, p_394161_, s); } return p_394161_; } private static Dynamic fixHoverEvent(Dynamic p_393225_) { String s = p_393225_.get("action").asString(""); return switch (s) { case "show_text" -> p_393225_.renameField("contents", "value"); case "show_item" -> { Dynamic dynamic1 = p_393225_.get("contents").orElseEmptyMap(); Optional optional = dynamic1.asString().result(); yield optional.isPresent() ? p_393225_.renameField("contents", "id") : copyFields(p_393225_.remove("contents"), dynamic1, "id", "count", "components"); } case "show_entity" -> { Dynamic dynamic = p_393225_.get("contents").orElseEmptyMap(); yield copyFields(p_393225_.remove("contents"), dynamic, "id", "type", "name").renameField("id", "uuid").renameField("type", "id"); } default -> p_393225_; }; } @Nullable private static Dynamic fixClickEvent(Dynamic p_397814_) { String s = p_397814_.get("action").asString(""); String s1 = p_397814_.get("value").asString(""); return switch (s) { case "open_url" -> !validateUri(s1) ? null : p_397814_.renameField("value", "url"); case "open_file" -> p_397814_.renameField("value", "path"); case "run_command", "suggest_command" -> !validateChat(s1) ? null : p_397814_.renameField("value", "command"); case "change_page" -> { Integer integer = p_397814_.get("value").result().map(TextComponentHoverAndClickEventFix::parseOldPage).orElse(null); if (integer == null) { yield null; } else { int i = Math.max(integer, 1); yield p_397814_.remove("value").set("page", p_397814_.createInt(i)); } } default -> p_397814_; }; } @Nullable private static Integer parseOldPage(Dynamic p_396464_) { Optional optional = p_396464_.asNumber().result(); if (optional.isPresent()) { return optional.get().intValue(); } else { try { return Integer.parseInt(p_396464_.asString("")); } catch (Exception exception) { return null; } } } private static boolean validateUri(String p_395339_) { try { URI uri = new URI(p_395339_); String s = uri.getScheme(); if (s == null) { return false; } else { String s1 = s.toLowerCase(Locale.ROOT); return "http".equals(s1) || "https".equals(s1); } } catch (URISyntaxException urisyntaxexception) { return false; } } private static boolean validateChat(String p_394600_) { for (int i = 0; i < p_394600_.length(); i++) { char c0 = p_394600_.charAt(i); if (c0 == 167 || c0 < ' ' || c0 == 127) { return false; } } return true; } }