mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 09:59:20 +00:00
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
package net.momirealms.craftengine.core.util;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentIteratorType;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
@@ -29,6 +35,21 @@ public class AdventureHelper {
|
||||
private final MiniMessage miniMessageCustom;
|
||||
private final GsonComponentSerializer gsonComponentSerializer;
|
||||
private final NBTComponentSerializer nbtComponentSerializer;
|
||||
private static final TextReplacementConfig REPLACE_LF = TextReplacementConfig.builder().matchLiteral("\n").replacement(Component.newline()).build();
|
||||
/**
|
||||
* This iterator slices a component into individual parts that
|
||||
* <ul>
|
||||
* <li>Can be used individually without style loss</li>
|
||||
* <li>Can be concatenated to form the original component, given that children are dropped</li>
|
||||
* </ul>
|
||||
* Any {@link net.kyori.adventure.text.ComponentIteratorFlag}s are ignored.
|
||||
*/
|
||||
private static final ComponentIteratorType SLICER = (component, deque, flags) -> {
|
||||
final List<Component> children = component.children();
|
||||
for (int i = children.size() - 1; i >= 0; i--) {
|
||||
deque.addFirst(children.get(i).applyFallbackStyle(component.style()));
|
||||
}
|
||||
};
|
||||
|
||||
private AdventureHelper() {
|
||||
this.miniMessage = MiniMessage.builder().build();
|
||||
@@ -209,6 +230,24 @@ public class AdventureHelper {
|
||||
return getNBT().deserialize(tag);
|
||||
}
|
||||
|
||||
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(SLICER); it.hasNext(); ) {
|
||||
Component child = it.next().children(Collections.emptyList());
|
||||
if (child instanceof TextComponent text && text.content().equals(Component.newline().content())) {
|
||||
result.add(line.compact());
|
||||
line = Component.empty();
|
||||
} else {
|
||||
line = line.append(child);
|
||||
}
|
||||
}
|
||||
if (Component.IS_NOT_EMPTY.test(line)) {
|
||||
result.add(line.compact());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a character is a legacy color code.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user