TextComponentHoverAndClickEventFix.java
net.minecraft.util.datafix.fixes.TextComponentHoverAndClickEventFix
信息
- 全限定名:net.minecraft.util.datafix.fixes.TextComponentHoverAndClickEventFix
- 类型:public class
- 包:net.minecraft.util.datafix.fixes
- 源码路径:src/main/java/net/minecraft/util/datafix/fixes/TextComponentHoverAndClickEventFix.java
- 起始行号:L21
- 继承:DataFix
- 职责:
TODO
字段/常量
- 无
内部类/嵌套类型
- 无
构造器
public TextComponentHoverAndClickEventFix(Schema outputSchema) @ L22
- 构造器名:TextComponentHoverAndClickEventFix
- 源码定位:L22
- 修饰符:public
参数:
- outputSchema: Schema
说明:
TODO
方法
下面的方法块按源码顺序生成。
protected TypeRewriteRule makeRule() @ L26
- 方法名:makeRule
- 源码定位:L26
- 返回类型:TypeRewriteRule
- 修饰符:protected
参数:
- 无
说明:
TODO
private <C1,C2,H extends Pair<String,?>> TypeRewriteRule createFixer(Type<C1> oldRawTextComponentType, Type<C2> newTextComponentType, Type<H> hoverEventType) @ L36
- 方法名:createFixer
- 源码定位:L36
- 返回类型:<C1,C2,H extends Pair<String,?>> TypeRewriteRule
- 修饰符:private
参数:
- oldRawTextComponentType: Type
- newTextComponentType: Type
- hoverEventType: Type
说明:
TODO
private static Dynamic<?> fixTextComponent(Dynamic<?> dynamic) @ L81
- 方法名:fixTextComponent
- 源码定位:L81
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- dynamic: Dynamic<?>
说明:
TODO
private static Dynamic<?> copyFields(Dynamic<?> target, Dynamic<?> source, String... fields) @ L86
- 方法名:copyFields
- 源码定位:L86
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- target: Dynamic<?>
- source: Dynamic<?>
- fields: String…
说明:
TODO
private static Dynamic<?> fixHoverEvent(Dynamic<?> dynamic) @ L94
- 方法名:fixHoverEvent
- 源码定位:L94
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- dynamic: Dynamic<?>
说明:
TODO
private static <T> Dynamic<T> fixClickEvent(Dynamic<T> dynamic) @ L114
- 方法名:fixClickEvent
- 源码定位:L114
- 返回类型:
Dynamic - 修饰符:private static
参数:
- dynamic: Dynamic
说明:
TODO
private static Integer parseOldPage(Dynamic<?> value) @ L135
- 方法名:parseOldPage
- 源码定位:L135
- 返回类型:Integer
- 修饰符:private static
参数:
- value: Dynamic<?>
说明:
TODO
private static boolean validateUri(String uri) @ L148
- 方法名:validateUri
- 源码定位:L148
- 返回类型:boolean
- 修饰符:private static
参数:
- uri: String
说明:
TODO
private static boolean validateChat(String string) @ L163
- 方法名:validateChat
- 源码定位:L163
- 返回类型:boolean
- 修饰符:private static
参数:
- string: String
说明:
TODO
代码
public class TextComponentHoverAndClickEventFix extends DataFix {
public TextComponentHoverAndClickEventFix(Schema outputSchema) {
super(outputSchema, true);
}
@Override
protected TypeRewriteRule makeRule() {
Type<? extends Pair<String, ?>> hoverEventType = (Type<? extends Pair<String, ?>>)this.getInputSchema()
.getType(References.TEXT_COMPONENT)
.findFieldType("hoverEvent");
return this.createFixer(
this.getInputSchema().getTypeRaw(References.TEXT_COMPONENT), this.getOutputSchema().getType(References.TEXT_COMPONENT), hoverEventType
);
}
private <C1, C2, H extends Pair<String, ?>> TypeRewriteRule createFixer(
Type<C1> oldRawTextComponentType, Type<C2> newTextComponentType, Type<H> hoverEventType
) {
Type<Pair<String, Either<Either<String, List<C1>>, Pair<Either<List<C1>, Unit>, Pair<Either<C1, Unit>, Pair<Either<H, Unit>, Dynamic<?>>>>>>> oldTextComponentType = DSL.named(
References.TEXT_COMPONENT.typeName(),
DSL.or(
DSL.or(DSL.string(), DSL.list(oldRawTextComponentType)),
DSL.and(
DSL.optional(DSL.field("extra", DSL.list(oldRawTextComponentType))),
DSL.optional(DSL.field("separator", oldRawTextComponentType)),
DSL.optional(DSL.field("hoverEvent", hoverEventType)),
DSL.remainderType()
)
)
);
if (!oldTextComponentType.equals(this.getInputSchema().getType(References.TEXT_COMPONENT))) {
throw new IllegalStateException(
"Text component type did not match, expected " + oldTextComponentType + " but got " + this.getInputSchema().getType(References.TEXT_COMPONENT)
);
} else {
Type<?> patchedInputType = ExtraDataFixUtils.patchSubType(oldTextComponentType, oldTextComponentType, newTextComponentType);
return this.fixTypeEverywhere(
"TextComponentHoverAndClickEventFix",
oldTextComponentType,
newTextComponentType,
ops -> textComponent -> {
boolean hasHoverOrClick = textComponent.getSecond().map(simple -> false, full -> {
Pair<Either<H, Unit>, Dynamic<?>> hoverAndRemainder = full.getSecond().getSecond();
boolean hasHover = hoverAndRemainder.getFirst().left().isPresent();
boolean hasClick = hoverAndRemainder.getSecond().get("clickEvent").result().isPresent();
return hasHover || hasClick;
});
return (C2)(!hasHoverOrClick
? textComponent
: Util.writeAndReadTypedOrThrow(
ExtraDataFixUtils.cast(patchedInputType, textComponent, ops),
newTextComponentType,
TextComponentHoverAndClickEventFix::fixTextComponent
)
.getValue());
}
);
}
}
private static Dynamic<?> fixTextComponent(Dynamic<?> dynamic) {
return dynamic.renameAndFixField("hoverEvent", "hover_event", TextComponentHoverAndClickEventFix::fixHoverEvent)
.renameAndFixField("clickEvent", "click_event", TextComponentHoverAndClickEventFix::fixClickEvent);
}
private static Dynamic<?> copyFields(Dynamic<?> target, Dynamic<?> source, String... fields) {
for (String field : fields) {
target = Dynamic.copyField(source, field, target, field);
}
return target;
}
private static Dynamic<?> fixHoverEvent(Dynamic<?> dynamic) {
String action = dynamic.get("action").asString("");
return switch (action) {
case "show_text" -> dynamic.renameField("contents", "value");
case "show_item" -> {
Dynamic<?> contents = dynamic.get("contents").orElseEmptyMap();
Optional<String> simpleId = contents.asString().result();
yield simpleId.isPresent()
? dynamic.renameField("contents", "id")
: copyFields(dynamic.remove("contents"), contents, "id", "count", "components");
}
case "show_entity" -> {
Dynamic<?> contents = dynamic.get("contents").orElseEmptyMap();
yield copyFields(dynamic.remove("contents"), contents, "id", "type", "name").renameField("id", "uuid").renameField("type", "id");
}
default -> dynamic;
};
}
private static <T> @Nullable Dynamic<T> fixClickEvent(Dynamic<T> dynamic) {
String action = dynamic.get("action").asString("");
String value = dynamic.get("value").asString("");
return switch (action) {
case "open_url" -> !validateUri(value) ? null : dynamic.renameField("value", "url");
case "open_file" -> dynamic.renameField("value", "path");
case "run_command", "suggest_command" -> !validateChat(value) ? null : dynamic.renameField("value", "command");
case "change_page" -> {
Integer oldPage = dynamic.get("value").result().map(TextComponentHoverAndClickEventFix::parseOldPage).orElse(null);
if (oldPage == null) {
yield null;
} else {
int page = Math.max(oldPage, 1);
yield dynamic.remove("value").set("page", dynamic.createInt(page));
}
}
default -> dynamic;
};
}
private static @Nullable Integer parseOldPage(Dynamic<?> value) {
Optional<Number> numberValue = value.asNumber().result();
if (numberValue.isPresent()) {
return numberValue.get().intValue();
} else {
try {
return Integer.parseInt(value.asString(""));
} catch (Exception var3) {
return null;
}
}
}
private static boolean validateUri(String uri) {
try {
URI parsedUri = new URI(uri);
String scheme = parsedUri.getScheme();
if (scheme == null) {
return false;
} else {
String protocol = scheme.toLowerCase(Locale.ROOT);
return "http".equals(protocol) || "https".equals(protocol);
}
} catch (URISyntaxException var4) {
return false;
}
}
private static boolean validateChat(String string) {
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (c == 167 || c < ' ' || c == 127) {
return false;
}
}
return true;
}
}引用的其他类
-
- 引用位置:
参数/返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.writeAndReadTypedOrThrow()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ExtraDataFixUtils.cast(), ExtraDataFixUtils.patchSubType()
- 引用位置:
-
- 引用位置:
参数/方法调用/返回值 - 关联成员:
Dynamic.copyField()
- 引用位置: