9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-28 11:29:17 +00:00

feat: better split lore impl

This commit is contained in:
ᑕᖇEEᑭYᑕᖇEEᑭEᖇ
2025-07-19 22:32:37 +08:00
parent 453c1f5c1f
commit 17b531c56c
8 changed files with 97 additions and 34 deletions

View File

@@ -90,7 +90,11 @@ public class ComponentItemFactory1_21_5 extends ComponentItemFactory1_21_4 {
if (lore == null || lore.isEmpty()) {
item.resetComponent(ComponentTypes.LORE);
} else {
item.setSparrowNBTComponent(ComponentTypes.LORE, new ListTag(lore.stream().map(AdventureHelper::split).flatMap(List::stream).map(AdventureHelper::componentToTag).toList()));
List<Tag> loreTags = new ArrayList<>();
for (Component component : lore) {
loreTags.add(AdventureHelper.componentToTag(component));
}
item.setSparrowNBTComponent(ComponentTypes.LORE, new ListTag(loreTags));
}
}

View File

@@ -534,15 +534,26 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
return new CustomNameModifier<>(name);
}, "custom-name", "item-name", "display-name");
}
Function<Object, List<LoreModification>> loreModificationListParser = (obj) -> {
if (obj instanceof List<?> list) {
List<LoreModification> modifications = new ArrayList<>(list.size());
for (Object entry : list) {
if (entry instanceof Map<?, ?> map) {
modifications.add(new LoreModification(ResourceConfigUtils.getAsEnumOrDefault(map.get("action").toString().toUpperCase(Locale.ROOT), LoreModification.Action.class, LoreModification.Action.SET), ResourceConfigUtils.getAsInt(map.get("priority"), "priority"), ResourceConfigUtils.getAsBoolean(map.get("split-lines"), "split-lines"), MiscUtils.getAsStringList(map.get("content"))));
} else {
modifications.add(new LoreModification(List.of(entry.toString())));
}
}
return modifications;
}
return Collections.emptyList();
};
registerDataType((obj) -> new LoreModifier<>(loreModificationListParser.apply(obj)), "lore", "display-lore", "description");
registerDataType((obj) -> {
List<String> lore = MiscUtils.getAsStringList(obj);
return new LoreModifier<>(lore);
}, "lore", "display-lore", "description");
registerDataType((obj) -> {
Map<String, List<String>> dynamicLore = new LinkedHashMap<>();
Map<String, List<LoreModification>> dynamicLore = new LinkedHashMap<>();
if (obj instanceof Map<?, ?> map) {
for (Map.Entry<?, ?> entry : map.entrySet()) {
dynamicLore.put(entry.getKey().toString(), MiscUtils.getAsStringList(entry.getValue()));
dynamicLore.put(entry.getKey().toString(), loreModificationListParser.apply(entry.getValue()));
}
}
return new DynamicLoreModifier<>(dynamicLore);

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.core.item;
import com.google.gson.JsonElement;
import java.util.stream.Collectors;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.item.data.Enchantment;
import net.momirealms.craftengine.core.item.data.FireworkExplosion;
@@ -111,7 +112,7 @@ public abstract class ItemFactory<W extends ItemWrapper<I>, I> {
protected void loreComponent(W item, List<Component> component) {
if (component != null && !component.isEmpty()) {
loreJson(item, component.stream().map(AdventureHelper::split).flatMap(List::stream).map(AdventureHelper::componentToJson).toList());
loreJson(item, component.stream().map(AdventureHelper::componentToJson).collect(Collectors.toList()));
} else {
loreJson(item, null);
}

View File

@@ -1,10 +1,11 @@
package net.momirealms.craftengine.core.item.modifier;
import java.util.stream.Stream;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.item.ComponentKeys;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.item.NetworkItemHandler;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.sparrow.nbt.CompoundTag;
import net.momirealms.sparrow.nbt.Tag;
@@ -16,15 +17,15 @@ import java.util.Optional;
public class DynamicLoreModifier<I> implements ItemDataModifier<I> {
public static final String CONTEXT_TAG_KEY = "craftengine:display_context";
private final Map<String, List<String>> displayContexts;
private final Map<String, List<LoreModification>> displayContexts;
private final String defaultContext;
public DynamicLoreModifier(Map<String, List<String>> displayContexts) {
public DynamicLoreModifier(Map<String, List<LoreModification>> displayContexts) {
this.defaultContext = displayContexts.keySet().iterator().next();
this.displayContexts = displayContexts;
}
public Map<String, List<String>> displayContexts() {
public Map<String, List<LoreModification>> displayContexts() {
return Collections.unmodifiableMap(this.displayContexts);
}
@@ -36,11 +37,11 @@ public class DynamicLoreModifier<I> implements ItemDataModifier<I> {
@Override
public Item<I> apply(Item<I> item, ItemBuildContext context) {
String displayContext = Optional.ofNullable(item.getJavaTag(CONTEXT_TAG_KEY)).orElse(this.defaultContext).toString();
List<String> lore = this.displayContexts.get(displayContext);
List<LoreModification> lore = this.displayContexts.get(displayContext);
if (lore == null) {
lore = this.displayContexts.get(this.defaultContext);
}
item.loreComponent(lore.stream().map(it -> AdventureHelper.miniMessage().deserialize(it, context.tagResolvers())).toList());
item.loreComponent(lore.stream().reduce(Stream.<Component>empty(), (stream, modification) -> modification.apply(stream, context), Stream::concat).toList());
return item;
}

View File

@@ -0,0 +1,45 @@
package net.momirealms.craftengine.core.item.modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.util.AdventureHelper;
public record LoreModification(Action action, int priority, boolean split, List<String> content) implements Comparable<LoreModification> {
public LoreModification(List<String> content) {
this(Action.SET, 0, false, content);
}
public LoreModification(Action action, int priority, boolean split, List<String> content) {
this.action = action;
this.priority = priority;
this.split = split;
if (Config.addNonItalicTag()) {
List<String> processed = new ArrayList<>(content.size());
for (String arg : content) {
processed.add(arg.startsWith("<!i>") ? arg : "<!i>" + arg);
}
this.content = processed;
} else {
this.content = content;
}
}
public Stream<Component> apply(Stream<Component> lore, ItemBuildContext context) {
return switch (action) {
case PREPEND -> Stream.concat(parseContent(context), lore);
case APPEND -> Stream.concat(lore, parseContent(context));
default -> parseContent(context);
};
}
private Stream<Component> parseContent(ItemBuildContext context) {
Stream<Component> parsed = content.stream().map(string -> AdventureHelper.miniMessage().deserialize(string, context.tagResolvers()));
return split ? parsed.map(AdventureHelper::splitLines).flatMap(List::stream) : parsed;
}
@Override
public int compareTo(LoreModification other) {
return Integer.compare(priority, other.priority);
}
public enum Action {
SET, PREPEND, APPEND
}
}

View File

@@ -1,35 +1,25 @@
package net.momirealms.craftengine.core.item.modifier;
import java.util.ArrayList;
import java.util.stream.Stream;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.item.ComponentKeys;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.item.NetworkItemHandler;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.sparrow.nbt.CompoundTag;
import net.momirealms.sparrow.nbt.Tag;
import java.util.ArrayList;
import java.util.List;
public class LoreModifier<I> implements ItemDataModifier<I> {
private final List<String> argument;
private final List<LoreModification> argument;
public LoreModifier(List<String> argument) {
if (Config.addNonItalicTag()) {
List<String> processed = new ArrayList<>(argument.size());
for (String arg : argument) {
if (arg.startsWith("<!i>")) {
processed.add(arg);
} else {
processed.add("<!i>" + arg);
}
}
this.argument = processed;
} else {
this.argument = argument;
}
public LoreModifier(List<LoreModification> argument) {
argument = new ArrayList<>(argument);
argument.sort(null);
this.argument = List.copyOf(argument);
}
@Override
@@ -39,7 +29,7 @@ public class LoreModifier<I> implements ItemDataModifier<I> {
@Override
public Item<I> apply(Item<I> item, ItemBuildContext context) {
item.loreComponent(this.argument.stream().map(it -> AdventureHelper.miniMessage().deserialize(it, context.tagResolvers())).toList());
item.loreComponent(argument.stream().reduce(Stream.<Component>empty(), (stream, modification) -> modification.apply(stream, context), Stream::concat).toList());
return item;
}

View File

@@ -216,7 +216,7 @@ public class AdventureHelper {
return getNBT().deserialize(tag);
}
public static List<Component> split(Component component) {
public static List<Component> splitLines(Component component) {
List<Component> result = new ArrayList<>(1);
Component line = Component.empty();
for (Iterator<Component> it = component.replaceText(REPLACE_LF).iterator(ComponentIteratorType.DEPTH_FIRST); it.hasNext(); ) {

View File

@@ -20,6 +20,17 @@ public final class ResourceConfigUtils {
return raw != null ? function.apply(raw) : defaultValue;
}
public static <E extends Enum<E>> E getAsEnumOrDefault(Object o, Class<E> clazz, E defaultValue) {
if (o == null) {
return defaultValue;
}
try {
return Enum.valueOf(clazz, o.toString());
} catch (IllegalArgumentException e) {
return defaultValue;
}
}
public static <T> T requireNonNullOrThrow(T obj, String node) {
if (obj == null)
throw new LocalizedResourceConfigException(node);