mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 18:09:27 +00:00
Merge branch 'Xiao-MoMi:dev' into dev
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
templates:
|
||||
default:emoji/basic:
|
||||
content: "<hover:show_text:'<i18n:emoji.tip>'><arg:emoji></hover>"
|
||||
default:emoji/addition_info:
|
||||
content: "<hover:show_text:'<i18n:emoji.tip>'>{text}<arg:emoji></hover>"
|
||||
|
||||
emoji:
|
||||
default:emoji_location:
|
||||
template: "default:emoji/addition_info"
|
||||
arguments:
|
||||
text: "<i18n:emoji.location>"
|
||||
overrides:
|
||||
image: "default:icons:0:0"
|
||||
permission: emoji.location
|
||||
keywords:
|
||||
- ":location:"
|
||||
- ":pos:"
|
||||
default:emoji_time:
|
||||
template: "default:emoji/addition_info"
|
||||
arguments:
|
||||
text: "<i18n:emoji.time>"
|
||||
overrides:
|
||||
image: "default:icons:0:1"
|
||||
permission: emoji.time
|
||||
keywords:
|
||||
- ":time:"
|
||||
@@ -39,6 +39,9 @@ i18n:
|
||||
category.topaz: "Topaz"
|
||||
category.furniture: "Furniture"
|
||||
category.misc: "Misc"
|
||||
emoji.tip: "Use <yellow>'<arg:keyword>'</yellow> to send the '<arg:emoji>' emoji"
|
||||
emoji.time: "<bold>Current time: <papi:player_world_time_12></bold>"
|
||||
emoji.location: "<bold>Current coordinates: <papi:player_x>,<papi:player_y>,<papi:player_z></bold>"
|
||||
zh_cn:
|
||||
item.chinese_lantern: "灯笼"
|
||||
item.fairy_flower: "仙灵花"
|
||||
@@ -78,4 +81,7 @@ i18n:
|
||||
category.palm_tree: "棕榈树"
|
||||
category.topaz: "黄玉"
|
||||
category.furniture: "家具"
|
||||
category.misc: "杂项"
|
||||
category.misc: "杂项"
|
||||
emoji.tip: "使用<yellow>'<arg:keyword>'</yellow>来发送表情'<arg:emoji>'"
|
||||
emoji.time: "<bold>当前时间: <papi:player_world_time_12></bold>"
|
||||
emoji.location: "<bold>当前坐标: <papi:player_x>,<papi:player_y>,<papi:player_z></bold>"
|
||||
@@ -102,4 +102,7 @@ warning.config.block.state.model.lack_path: "<yellow>Issue found in file <arg:0>
|
||||
warning.config.block.state.model.invalid_resource_location: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' has a 'path' argument [<arg:2>] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>Issue found in file <arg:0> - Failed to generate model for '<arg:1>' as two or more configurations attempt to generate different json models with the same path: '<arg:2>'</yellow>"
|
||||
warning.config.model.generation.texture.invalid_resource_location: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a '<arg:2>' texture argument [<arg:3>] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters</yellow>"
|
||||
warning.config.model.generation.parent.invalid_resource_location: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a parent argument [<arg:2>] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters</yellow>"
|
||||
warning.config.model.generation.parent.invalid_resource_location: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a parent argument [<arg:2>] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters</yellow>"
|
||||
warning.config.emoji.lack_keywords: "<yellow>Issue found in file <arg:0> - The emoji '<arg:1>' is missing the required 'keywords' argument.</yellow>"
|
||||
warning.config.emoji.duplicated: "<yellow>Issue found in file <arg:0> - Duplicated emoji '<arg:1>'.</yellow>"
|
||||
warning.config.emoji.invalid_image: "<yellow>Issue found in file <arg:0> - The emoji '<arg:1>' has an invalid 'image' argument '<arg:2>'.</yellow>"
|
||||
@@ -102,4 +102,7 @@ warning.config.block.state.model.lack_path: "<yellow>在文件 <arg:0> 中发现
|
||||
warning.config.block.state.model.invalid_resource_location: "<yellow>在文件 <arg:0> 中发现问题 - 方块 '<arg:1>' 的 'path' 路径参数 [<arg:2>] 包含非法字符,请参考资源路径规范:https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>在文件 <arg:0> 中发现问题 - 无法为 '<arg:1>' 生成模型,多个配置尝试用相同路径 '<arg:2>' 生成不同的JSON模型</yellow>"
|
||||
warning.config.model.generation.texture.invalid_resource_location: "<yellow>在文件 <arg:0> 中发现问题 - 配置项 '<arg:1>' 的 '<arg:2>' 纹理参数 [<arg:3>] 包含非法字符,请参考资源路径规范:https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6</yellow>"
|
||||
warning.config.model.generation.parent.invalid_resource_location: "<yellow>在文件 <arg:0> 中发现问题 - 配置项 '<arg:1>' 的父模型参数 [<arg:2>] 包含非法字符,请参考资源路径规范:https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6</yellow>"
|
||||
warning.config.model.generation.parent.invalid_resource_location: "<yellow>在文件 <arg:0> 中发现问题 - 配置项 '<arg:1>' 的父模型参数 [<arg:2>] 包含非法字符,请参考资源路径规范:https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6</yellow>"
|
||||
warning.config.emoji.lack_keywords: "<yellow>在文件 <arg:0> 中发现问题 - 表情 '<arg:1>' 缺少必要的 'keywords' 配置</yellow>"
|
||||
warning.config.emoji.duplicated: "<yellow>在文件 <arg:0> 中发现问题 - 表情 '<arg:1>' 重复定义</yellow>"
|
||||
warning.config.emoji.invalid_image: "<yellow>在文件 <arg:0> 中发现问题 - 表情 '<arg:1>' 使用了无效的 'image' 图片参数 '<arg:2>'.</yellow>"
|
||||
@@ -2,7 +2,6 @@ package net.momirealms.craftengine.bukkit.font;
|
||||
|
||||
import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent;
|
||||
import io.papermc.paper.event.player.AsyncChatDecorateEvent;
|
||||
import io.papermc.paper.event.player.PlayerSignCommandPreprocessEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
@@ -17,11 +16,10 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
private final BukkitCraftEngine plugin;
|
||||
@@ -59,10 +57,12 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onCommand(PlayerCommandPreprocessEvent event) {
|
||||
if (!Config.filterCommand()) return;
|
||||
if (event.getPlayer().hasPermission(FontManager.BYPASS_COMMAND)) {
|
||||
return;
|
||||
if (!event.getPlayer().hasPermission(FontManager.BYPASS_COMMAND)) {
|
||||
IllegalCharacterProcessResult result = processIllegalCharacters(event.getMessage());
|
||||
if (result.has()) {
|
||||
event.setMessage(result.newText());
|
||||
}
|
||||
}
|
||||
runIfContainsIllegalCharacter(event.getMessage(), event::setMessage);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@@ -71,23 +71,28 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
if (player == null) return;
|
||||
try {
|
||||
Object originalMessage = Reflections.field$AsyncChatDecorateEvent$originalMessage.get(event);
|
||||
String jsonMessage = ComponentUtils.paperAdventureToJson(originalMessage);
|
||||
String rawJsonMessage = ComponentUtils.paperAdventureToJson(originalMessage);
|
||||
String jsonMessage = replaceJsonEmoji(rawJsonMessage, this.plugin.adapt(player));
|
||||
boolean hasChanged = !rawJsonMessage.equals(jsonMessage);
|
||||
if (!player.hasPermission(FontManager.BYPASS_CHAT)) {
|
||||
runIfContainsIllegalCharacter(jsonMessage, (json) -> {
|
||||
Object component = ComponentUtils.jsonToPaperAdventure(json);
|
||||
try {
|
||||
Reflections.method$AsyncChatDecorateEvent$result.invoke(event, component);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
IllegalCharacterProcessResult result = processIllegalCharacters(jsonMessage);
|
||||
if (result.has()) {
|
||||
Object component = ComponentUtils.jsonToPaperAdventure(result.newText());
|
||||
Reflections.method$AsyncChatDecorateEvent$result.invoke(event, component);
|
||||
} else if (hasChanged) {
|
||||
Object component = ComponentUtils.jsonToPaperAdventure(jsonMessage);
|
||||
Reflections.method$AsyncChatDecorateEvent$result.invoke(event, component);
|
||||
}
|
||||
} else if (hasChanged) {
|
||||
Object component = ComponentUtils.jsonToPaperAdventure(jsonMessage);
|
||||
Reflections.method$AsyncChatDecorateEvent$result.invoke(event, component);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void runIfContainsIllegalCharacter(String raw, Consumer<String> callback) {
|
||||
private IllegalCharacterProcessResult processIllegalCharacters(String raw) {
|
||||
boolean hasIllegal = false;
|
||||
// replace illegal image usage
|
||||
Map<String, Component> tokens = matchTags(raw);
|
||||
@@ -113,11 +118,24 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
hasIllegal = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasIllegal) {
|
||||
callback.accept(new String(newCodepoints, 0, newCodepoints.length));
|
||||
return IllegalCharacterProcessResult.has(new String(newCodepoints, 0, newCodepoints.length));
|
||||
}
|
||||
} else if (hasIllegal) {
|
||||
callback.accept(raw);
|
||||
return IllegalCharacterProcessResult.has(raw);
|
||||
}
|
||||
return IllegalCharacterProcessResult.not();
|
||||
}
|
||||
|
||||
public record IllegalCharacterProcessResult(boolean has, String newText) {
|
||||
|
||||
public static IllegalCharacterProcessResult has(String newText) {
|
||||
return new IllegalCharacterProcessResult(true, newText);
|
||||
}
|
||||
|
||||
public static IllegalCharacterProcessResult not() {
|
||||
return new IllegalCharacterProcessResult(false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.pack.ResourceLocation;
|
||||
@@ -8,6 +9,8 @@ import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.context.PlayerContext;
|
||||
import org.ahocorasick.trie.Token;
|
||||
import org.ahocorasick.trie.Trie;
|
||||
|
||||
@@ -28,8 +31,10 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
private final EmojiParser emojiParser;
|
||||
|
||||
private OffsetFont offsetFont;
|
||||
private Trie trie;
|
||||
private Trie imageTagTrie;
|
||||
private Trie emojiKeywordTrie;
|
||||
private Map<String, Component> tagMapper;
|
||||
private Map<String, Emoji> emojiMapper;
|
||||
|
||||
public AbstractFontManager(CraftEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -49,15 +54,16 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
this.fonts.clear();
|
||||
this.images.clear();
|
||||
this.illegalChars.clear();
|
||||
this.emojis.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Component> matchTags(String json) {
|
||||
if (this.trie == null) {
|
||||
if (this.imageTagTrie == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, Component> tags = new HashMap<>();
|
||||
for (Token token : this.trie.tokenize(json)) {
|
||||
for (Token token : this.imageTagTrie.tokenize(json)) {
|
||||
if (token.isMatch()) {
|
||||
tags.put(token.getFragment(), this.tagMapper.get(token.getFragment()));
|
||||
}
|
||||
@@ -67,11 +73,11 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
|
||||
@Override
|
||||
public String stripTags(String text) {
|
||||
if (this.trie == null) {
|
||||
if (this.imageTagTrie == null) {
|
||||
return text;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Token token : this.trie.tokenize(text)) {
|
||||
for (Token token : this.imageTagTrie.tokenize(text)) {
|
||||
if (token.isMatch()) {
|
||||
builder.append("*");
|
||||
} else {
|
||||
@@ -81,6 +87,58 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String replaceMiniMessageEmoji(String miniMessage, Player player) {
|
||||
if (this.emojiKeywordTrie == null) {
|
||||
return miniMessage;
|
||||
}
|
||||
for (Token token : this.emojiKeywordTrie.tokenize(miniMessage)) {
|
||||
if (!token.isMatch()) continue;
|
||||
Emoji emoji = this.emojiMapper.get(token.getFragment());
|
||||
if (emoji == null) continue;
|
||||
Component content = AdventureHelper.miniMessage().deserialize(
|
||||
emoji.content(),
|
||||
PlayerContext.of(player, ContextHolder.builder()
|
||||
.withOptionalParameter(EmojiParameters.EMOJI, emoji.emojiImage())
|
||||
.withParameter(EmojiParameters.KEYWORD, emoji.keywords().get(0))
|
||||
.build()).tagResolvers()
|
||||
);
|
||||
miniMessage = miniMessage.replace(token.getFragment(), AdventureHelper.componentToMiniMessage(content));
|
||||
}
|
||||
return miniMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String replaceJsonEmoji(String jsonText, Player player) {
|
||||
if (this.emojiKeywordTrie == null) {
|
||||
return jsonText;
|
||||
}
|
||||
Map<String, Emoji> emojis = new HashMap<>();
|
||||
for (Token token : this.emojiKeywordTrie.tokenize(jsonText)) {
|
||||
if (token.isMatch()) {
|
||||
emojis.put(token.getFragment(), this.emojiMapper.get(token.getFragment()));
|
||||
}
|
||||
}
|
||||
if (emojis.isEmpty()) return jsonText;
|
||||
Component component = AdventureHelper.jsonToComponent(jsonText);
|
||||
for (Map.Entry<String, Emoji> entry : emojis.entrySet()) {
|
||||
Emoji emoji = entry.getValue();
|
||||
if (player != null && emoji.permission() != null && !player.hasPermission(emoji.permission())) {
|
||||
continue;
|
||||
}
|
||||
component = component.replaceText(builder -> builder.matchLiteral(entry.getKey())
|
||||
.replacement(
|
||||
AdventureHelper.miniMessage().deserialize(
|
||||
emoji.content(),
|
||||
PlayerContext.of(player, ContextHolder.builder()
|
||||
.withOptionalParameter(EmojiParameters.EMOJI, emoji.emojiImage())
|
||||
.withParameter(EmojiParameters.KEYWORD, emoji.keywords().get(0))
|
||||
.build()).tagResolvers())
|
||||
));
|
||||
}
|
||||
return AdventureHelper.componentToJson(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigSectionParser[] parsers() {
|
||||
return new ConfigSectionParser[] {this.imageParser, this.emojiParser};
|
||||
@@ -89,10 +147,24 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
@Override
|
||||
public void delayedLoad() {
|
||||
Optional.ofNullable(this.fonts.get(DEFAULT_FONT)).ifPresent(font -> this.illegalChars.addAll(font.codepointsInUse()));
|
||||
this.buildTrie();
|
||||
this.buildImageTagTrie();
|
||||
this.buildEmojiKeywordsTrie();
|
||||
}
|
||||
|
||||
private void buildTrie() {
|
||||
private void buildEmojiKeywordsTrie() {
|
||||
this.emojiMapper = new HashMap<>();
|
||||
for (Emoji emoji : this.emojis.values()) {
|
||||
for (String keyword : emoji.keywords()) {
|
||||
this.emojiMapper.put(keyword, emoji);
|
||||
}
|
||||
}
|
||||
this.emojiKeywordTrie = Trie.builder()
|
||||
.ignoreOverlaps()
|
||||
.addKeywords(this.emojiMapper.keySet())
|
||||
.build();
|
||||
}
|
||||
|
||||
private void buildImageTagTrie() {
|
||||
this.tagMapper = new HashMap<>();
|
||||
for (BitmapImage image : this.images.values()) {
|
||||
String id = image.id().toString();
|
||||
@@ -109,7 +181,7 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
this.tagMapper.put("<shift:" + i + ">", AdventureHelper.miniMessage().deserialize(this.offsetFont.createOffset(i, FormatUtils::miniMessageFont)));
|
||||
this.tagMapper.put("\\<shift:" + i + ">", Component.text("<shift:" + i + ">"));
|
||||
}
|
||||
this.trie = Trie.builder()
|
||||
this.imageTagTrie = Trie.builder()
|
||||
.ignoreOverlaps()
|
||||
.addKeywords(this.tagMapper.keySet())
|
||||
.build();
|
||||
@@ -180,7 +252,47 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
|
||||
if (emojis.containsKey(id)) {
|
||||
TranslationManager.instance().log("warning.config.emoji.duplicated", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
String permission = (String) section.get("permission");
|
||||
Object keywordsRaw = section.get("keywords");
|
||||
if (keywordsRaw == null) {
|
||||
TranslationManager.instance().log("warning.config.emoji.lack_keywords", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
List<String> keywords = MiscUtils.getAsStringList(keywordsRaw);
|
||||
String content = section.getOrDefault("content", "<arg:emoji>").toString();
|
||||
String image = null;
|
||||
if (section.containsKey("image")) {
|
||||
String rawImage = section.get("image").toString();
|
||||
String[] split = rawImage.split(":");
|
||||
if (split.length == 2) {
|
||||
Key imageId = new Key(split[0], split[1]);
|
||||
Optional<BitmapImage> bitmapImage = bitmapImageByImageId(imageId);
|
||||
if (bitmapImage.isPresent()) {
|
||||
image = bitmapImage.get().miniMessage(0, 0);
|
||||
} else {
|
||||
TranslationManager.instance().log("warning.config.emoji.invalid_image", path.toString(), id.toString(), rawImage);
|
||||
return;
|
||||
}
|
||||
} else if (split.length == 4) {
|
||||
Key imageId = new Key(split[0], split[1]);
|
||||
Optional<BitmapImage> bitmapImage = bitmapImageByImageId(imageId);
|
||||
if (bitmapImage.isPresent()) {
|
||||
image = bitmapImage.get().miniMessage(Integer.parseInt(split[2]), Integer.parseInt(split[3]));
|
||||
} else {
|
||||
TranslationManager.instance().log("warning.config.emoji.invalid_image", path.toString(), id.toString(), rawImage);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
TranslationManager.instance().log("warning.config.emoji.invalid_image", path.toString(), id.toString(), rawImage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Emoji emoji = new Emoji(content, permission, image, keywords);
|
||||
emojis.put(id, emoji);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class Emoji {
|
||||
private final Key font;
|
||||
private final String image;
|
||||
private final String content;
|
||||
private final String permission;
|
||||
private final String image;
|
||||
private final List<String> keywords;
|
||||
|
||||
public Emoji(Key font, String image, String permission) {
|
||||
this.font = font;
|
||||
public Emoji(String content, String permission, String image, List<String> keywords) {
|
||||
this.content = content;
|
||||
this.image = image;
|
||||
this.permission = permission;
|
||||
this.keywords = keywords;
|
||||
}
|
||||
|
||||
public Key font() {
|
||||
return font;
|
||||
public String content() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public String image() {
|
||||
@Nullable
|
||||
public String emojiImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -27,4 +29,8 @@ public class Emoji {
|
||||
public String permission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public List<String> keywords() {
|
||||
return keywords;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.context.ContextKey;
|
||||
|
||||
public class EmojiParameters {
|
||||
public static final ContextKey<String> KEYWORD = new ContextKey<>(Key.of("keyword"));
|
||||
public static final ContextKey<String> EMOJI = new ContextKey<>(Key.of("emoji"));
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.Manageable;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.util.CharacterUtils;
|
||||
@@ -23,6 +24,10 @@ public interface FontManager extends Manageable {
|
||||
|
||||
ConfigSectionParser[] parsers();
|
||||
|
||||
String replaceMiniMessageEmoji(String miniMessage, Player player);
|
||||
|
||||
String replaceJsonEmoji(String jsonText, Player player);
|
||||
|
||||
boolean isDefaultFontInUse();
|
||||
|
||||
boolean isIllegalCodepoint(int codepoint);
|
||||
|
||||
@@ -1,43 +1,20 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.text.minimessage.*;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.context.PlayerContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ItemBuildContext implements MiniMessageTextContext {
|
||||
public class ItemBuildContext extends PlayerContext {
|
||||
public static final ItemBuildContext EMPTY = new ItemBuildContext(null, ContextHolder.EMPTY);
|
||||
private final Player player;
|
||||
private final ContextHolder contexts;
|
||||
private TagResolver[] tagResolvers;
|
||||
|
||||
public ItemBuildContext(@Nullable Player player, @NotNull ContextHolder contexts) {
|
||||
this.player = player;
|
||||
this.contexts = contexts;
|
||||
super(player, contexts);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ItemBuildContext of(@Nullable Player player, @NotNull ContextHolder contexts) {
|
||||
return new ItemBuildContext(player, contexts);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Player player() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ContextHolder contexts() {
|
||||
return this.contexts;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TagResolver[] tagResolvers() {
|
||||
if (this.tagResolvers == null) {
|
||||
this.tagResolvers = new TagResolver[]{ShiftTag.INSTANCE, ImageTag.INSTANCE, new PlaceholderTag(this.player), new I18NTag(this), new NamedArgumentTag(this)};
|
||||
}
|
||||
return this.tagResolvers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,6 +300,8 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
plugin.saveResource("resources/default/resourcepack/pack.png");
|
||||
// templates
|
||||
plugin.saveResource("resources/default/configuration/templates.yml");
|
||||
// emoji
|
||||
plugin.saveResource("resources/default/configuration/emoji.yml");
|
||||
// i18n
|
||||
plugin.saveResource("resources/default/configuration/i18n.yml");
|
||||
// block_name
|
||||
|
||||
@@ -16,6 +16,7 @@ import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.context.PlayerContext;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
@@ -175,7 +176,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.BROWSER_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.BROWSER_TITLE, PlayerContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
@@ -290,7 +291,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.CATEGORY_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.CATEGORY_TITLE, PlayerContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
@@ -351,7 +352,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_NONE_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_NONE_TITLE, PlayerContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
@@ -576,7 +577,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_SMITHING_TRANSFORM_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_SMITHING_TRANSFORM_TITLE, PlayerContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
@@ -709,7 +710,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_STONECUTTING_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_STONECUTTING_TITLE, PlayerContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
@@ -859,7 +860,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(title, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.title(AdventureHelper.miniMessage().deserialize(title, PlayerContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
@@ -1054,7 +1055,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_CRAFTING_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_CRAFTING_TITLE, PlayerContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
|
||||
@@ -28,15 +28,12 @@ public class NamedArgumentTag implements TagResolver {
|
||||
if (!has(name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String argumentKey = arguments.popOr("No argument key provided").toString();
|
||||
|
||||
ContextKey<String> key = ContextKey.of(Key.of(argumentKey));
|
||||
if (!this.context.contexts().has(key)) {
|
||||
throw ctx.newException("Invalid argument key", arguments);
|
||||
}
|
||||
|
||||
return Tag.inserting(AdventureHelper.miniMessage().deserialize(this.context.contexts().getOrThrow(key), this.context.tagResolvers()));
|
||||
return Tag.selfClosingInserting(AdventureHelper.miniMessage().deserialize(this.context.contexts().getOrThrow(key), this.context.tagResolvers()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -126,6 +126,10 @@ public class AdventureHelper {
|
||||
return getInstance().miniMessageStrict.serialize(getInstance().gsonComponentSerializer.deserialize(json));
|
||||
}
|
||||
|
||||
public static String componentToMiniMessage(Component component) {
|
||||
return getInstance().miniMessageStrict.serialize(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JSON string to a Component.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.momirealms.craftengine.core.util.context;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.text.minimessage.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PlayerContext implements MiniMessageTextContext {
|
||||
public static final PlayerContext EMPTY = new PlayerContext(null, ContextHolder.EMPTY);
|
||||
private final Player player;
|
||||
private final ContextHolder contexts;
|
||||
private TagResolver[] tagResolvers;
|
||||
|
||||
public PlayerContext(@Nullable Player player, @NotNull ContextHolder contexts) {
|
||||
this.player = player;
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PlayerContext of(@Nullable Player player, @NotNull ContextHolder contexts) {
|
||||
return new PlayerContext(player, contexts);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Player player() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ContextHolder contexts() {
|
||||
return this.contexts;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TagResolver[] tagResolvers() {
|
||||
if (this.tagResolvers == null) {
|
||||
this.tagResolvers = new TagResolver[]{ShiftTag.INSTANCE, ImageTag.INSTANCE, new PlaceholderTag(this.player), new I18NTag(this), new NamedArgumentTag(this)};
|
||||
}
|
||||
return this.tagResolvers;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user