mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-24 17:39:30 +00:00
refactor images
This commit is contained in:
@@ -53,4 +53,14 @@ command.search_recipe.not_found: "<red>No recipe found for this item</red>"
|
||||
command.search_usage.not_found: "<red>No usage found for this item</red>"
|
||||
command.search_recipe.no_item: "<red>Please hold an item before running this command</red>"
|
||||
command.search_usage.no_item: "<red>Please hold an item before running this command</red>"
|
||||
command.totem.not_totem: "<red>'<arg:0>' is not type of totem_of_undying</red>"
|
||||
command.totem.not_totem: "<red>'<arg:0>' is not type of totem_of_undying</red>"
|
||||
|
||||
warning.config.image.lack_height: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is missing the required 'height' argument.</yellow>"
|
||||
warning.config.image.height_smaller_than_ascent: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' violates the bitmap image rule: 'height' should be no lower than 'ascent'.</yellow>"
|
||||
warning.config.image.no_file: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is missing the required 'file' argument.</yellow>"
|
||||
warning.config.image.invalid_resource_location: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' has a 'file' argument [<arg:2>] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters</yellow>"
|
||||
warning.config.image.invalid_font_name: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' has a 'font' argument [<arg:2>] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters</yellow>"
|
||||
warning.config.image.lack_char: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is missing the required 'char' argument.</yellow>"
|
||||
warning.config.image.codepoint_in_use: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is using a character[<arg:3>(<arg:4>)] in font <arg:2> that has been used by another image '<arg:5>'.</yellow>"
|
||||
warning.config.image.invalid_codepoint_grid: "<yellow>Issue found in file <arg:0> - Image '<arg:1>' has an invalid 'chars' codepoint grind.</yellow>"
|
||||
warning.config.image.file_not_exist: "<yellow>Issue found in file <arg:0> - PNG file <arg:2> not found for image '<arg:1>'.</yellow>"
|
||||
@@ -6,7 +6,6 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
@@ -14,7 +13,6 @@ import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
|
||||
@@ -8,7 +8,6 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.PushReaction;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
@@ -29,7 +28,10 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.*;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.world.GenericGameEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@@ -13,14 +13,13 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
import net.momirealms.craftengine.core.util.Tuple;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.context.ContextKey;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.Vec3i;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
@@ -29,7 +28,6 @@ import org.bukkit.World;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@@ -4,8 +4,8 @@ import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent;
|
||||
import io.papermc.paper.event.player.AsyncChatDecorateEvent;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.font.AbstractImageManager;
|
||||
import net.momirealms.craftengine.core.font.ImageManager;
|
||||
import net.momirealms.craftengine.core.font.AbstractFontManager;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.util.CharacterUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -19,11 +19,11 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BukkitImageManager extends AbstractImageManager implements Listener {
|
||||
public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
private final BukkitCraftEngine plugin;
|
||||
private final Object serializer;
|
||||
|
||||
public BukkitImageManager(BukkitCraftEngine plugin) {
|
||||
public BukkitFontManager(BukkitCraftEngine plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
try {
|
||||
@@ -63,7 +63,7 @@ public class BukkitImageManager extends AbstractImageManager implements Listener
|
||||
public void onCommand(PlayerCommandPreprocessEvent event) {
|
||||
if (!ConfigManager.filterCommand()) return;
|
||||
if (!this.isDefaultFontInUse()) return;
|
||||
if (event.getPlayer().hasPermission(ImageManager.BYPASS_COMMAND)) {
|
||||
if (event.getPlayer().hasPermission(FontManager.BYPASS_COMMAND)) {
|
||||
return;
|
||||
}
|
||||
runIfContainsIllegalCharacter(event.getMessage(), event::setMessage);
|
||||
@@ -74,7 +74,7 @@ public class BukkitImageManager extends AbstractImageManager implements Listener
|
||||
Player player = event.player();
|
||||
if (player == null) return;
|
||||
if (!this.isDefaultFontInUse()) return;
|
||||
if (player.hasPermission(ImageManager.BYPASS_CHAT)) {
|
||||
if (player.hasPermission(FontManager.BYPASS_CHAT)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -101,7 +101,7 @@ public class BukkitImageManager extends AbstractImageManager implements Listener
|
||||
boolean hasIllegal = false;
|
||||
for (int i = 0; i < codepoints.length; i++) {
|
||||
int codepoint = codepoints[i];
|
||||
if (!isIllegalCharacter(codepoint)) {
|
||||
if (!isIllegalCodepoint(codepoint)) {
|
||||
newCodepoints[i] = codepoint;
|
||||
} else {
|
||||
newCodepoints[i] = '*';
|
||||
@@ -7,7 +7,7 @@ import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.papi.PlaceholderAPIUtils;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.BukkitHitBoxTypes;
|
||||
import net.momirealms.craftengine.bukkit.font.BukkitImageManager;
|
||||
import net.momirealms.craftengine.bukkit.font.BukkitFontManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BukkitItemBehaviors;
|
||||
import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
|
||||
@@ -154,7 +154,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
super.worldManager = new BukkitWorldManager(this);
|
||||
super.soundManager = new BukkitSoundManager(this);
|
||||
super.vanillaLootManager = new BukkitVanillaLootManager(this);
|
||||
this.imageManager = new BukkitImageManager(this);
|
||||
this.fontManager = new BukkitFontManager(this);
|
||||
super.enable();
|
||||
// tick task
|
||||
if (VersionHelper.isFolia()) {
|
||||
@@ -216,7 +216,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
// register template parser
|
||||
this.packManager.registerConfigSectionParser(this.templateManager);
|
||||
// register font parser
|
||||
this.packManager.registerConfigSectionParser(this.imageManager);
|
||||
this.packManager.registerConfigSectionParsers(this.fontManager.parsers());
|
||||
// register item parser
|
||||
this.packManager.registerConfigSectionParser(this.itemManager);
|
||||
// register furniture parser
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.sender.Sender;
|
||||
import net.momirealms.craftengine.core.plugin.command.sender.SenderFactory;
|
||||
import net.momirealms.craftengine.core.util.Tristate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.command.RemoteConsoleCommandSender;
|
||||
@@ -79,6 +80,12 @@ public class BukkitSenderFactory extends SenderFactory<BukkitCraftEngine, Comman
|
||||
return sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected <C extends CommandSender> C consoleCommandSender() {
|
||||
return (C) Bukkit.getConsoleSender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
|
||||
@@ -18,7 +18,7 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.font.ImageManager;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
@@ -777,10 +777,10 @@ public class PacketConsumers {
|
||||
if (!ConfigManager.filterAnvil()) return;
|
||||
String message = (String) Reflections.field$ServerboundRenameItemPacket$name.get(packet);
|
||||
if (message != null && !message.isEmpty()) {
|
||||
ImageManager manager = CraftEngine.instance().imageManager();
|
||||
FontManager manager = CraftEngine.instance().imageManager();
|
||||
if (!manager.isDefaultFontInUse()) return;
|
||||
// check bypass
|
||||
if (((BukkitServerPlayer) user).hasPermission(ImageManager.BYPASS_ANVIL)) {
|
||||
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_ANVIL)) {
|
||||
return;
|
||||
}
|
||||
runIfContainsIllegalCharacter(message, manager, (s) -> {
|
||||
@@ -801,10 +801,10 @@ public class PacketConsumers {
|
||||
try {
|
||||
if (!ConfigManager.filterSign()) return;
|
||||
String[] lines = (String[]) Reflections.field$ServerboundSignUpdatePacket$lines.get(packet);
|
||||
ImageManager manager = CraftEngine.instance().imageManager();
|
||||
FontManager manager = CraftEngine.instance().imageManager();
|
||||
if (!manager.isDefaultFontInUse()) return;
|
||||
// check bypass
|
||||
if (((BukkitServerPlayer) user).hasPermission(ImageManager.BYPASS_SIGN)) {
|
||||
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_SIGN)) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
@@ -827,10 +827,10 @@ public class PacketConsumers {
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> EDIT_BOOK = (user, event, packet) -> {
|
||||
try {
|
||||
if (!ConfigManager.filterBook()) return;
|
||||
ImageManager manager = CraftEngine.instance().imageManager();
|
||||
FontManager manager = CraftEngine.instance().imageManager();
|
||||
if (!manager.isDefaultFontInUse()) return;
|
||||
// check bypass
|
||||
if (((BukkitServerPlayer) user).hasPermission(ImageManager.BYPASS_BOOK)) {
|
||||
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_BOOK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -879,7 +879,7 @@ public class PacketConsumers {
|
||||
}
|
||||
};
|
||||
|
||||
private static Pair<Boolean, String> processClientString(String original, ImageManager manager) {
|
||||
private static Pair<Boolean, String> processClientString(String original, FontManager manager) {
|
||||
if (original.isEmpty()) {
|
||||
return Pair.of(false, original);
|
||||
}
|
||||
@@ -888,7 +888,7 @@ public class PacketConsumers {
|
||||
boolean hasIllegal = false;
|
||||
for (int i = 0; i < codepoints.length; i++) {
|
||||
int codepoint = codepoints[i];
|
||||
if (manager.isIllegalCharacter(codepoint)) {
|
||||
if (manager.isIllegalCodepoint(codepoint)) {
|
||||
newCodepoints[i] = '*';
|
||||
hasIllegal = true;
|
||||
} else {
|
||||
@@ -898,14 +898,14 @@ public class PacketConsumers {
|
||||
return hasIllegal ? Pair.of(true, new String(newCodepoints, 0, newCodepoints.length)) : Pair.of(false, original);
|
||||
}
|
||||
|
||||
private static void runIfContainsIllegalCharacter(String string, ImageManager manager, Consumer<String> callback) {
|
||||
private static void runIfContainsIllegalCharacter(String string, FontManager manager, Consumer<String> callback) {
|
||||
if (string.isEmpty()) return;
|
||||
int[] codepoints = CharacterUtils.charsToCodePoints(string.toCharArray());
|
||||
int[] newCodepoints = new int[codepoints.length];
|
||||
boolean hasIllegal = false;
|
||||
for (int i = 0; i < codepoints.length; i++) {
|
||||
int codepoint = codepoints[i];
|
||||
if (!manager.isIllegalCharacter(codepoint)) {
|
||||
if (!manager.isIllegalCodepoint(codepoint)) {
|
||||
newCodepoints[i] = codepoint;
|
||||
} else {
|
||||
newCodepoints[i] = '*';
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.pack.ResourceLocation;
|
||||
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.CharacterUtils;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class AbstractFontManager implements FontManager {
|
||||
private final CraftEngine plugin;
|
||||
// namespace:font font
|
||||
private final Map<Key, Font> fonts = new HashMap<>();
|
||||
// namespace:id image
|
||||
private final Map<Key, BitmapImage> images = new HashMap<>();
|
||||
private final Set<Integer> illegalChars = new HashSet<>();
|
||||
private final ImageParser imageParser;
|
||||
private final EmojiParser emojiParser;
|
||||
|
||||
private OffsetFont offsetFont;
|
||||
|
||||
public AbstractFontManager(CraftEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
this.imageParser = new ImageParser();
|
||||
this.emojiParser = new EmojiParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
this.offsetFont = Optional.ofNullable(plugin.configManager().settings().getSection("offset-characters"))
|
||||
.map(OffsetFont::new)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
this.fonts.clear();
|
||||
this.images.clear();
|
||||
this.illegalChars.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigSectionParser[] parsers() {
|
||||
return new ConfigSectionParser[] {this.imageParser, this.emojiParser};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delayedLoad() {
|
||||
Optional.ofNullable(this.fonts.get(DEFAULT_FONT)).ifPresent(font -> this.illegalChars.addAll(font.codepointsInUse()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultFontInUse() {
|
||||
return !this.illegalChars.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIllegalCodepoint(int codepoint) {
|
||||
return this.illegalChars.contains(codepoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Font> fonts() {
|
||||
return new ArrayList<>(this.fonts.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BitmapImage> bitmapImageByCodepoint(Key font, int codepoint) {
|
||||
return fontById(font).map(f -> f.bitmapImageByCodepoint(codepoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BitmapImage> bitmapImageByImageId(Key id) {
|
||||
return Optional.ofNullable(this.images.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int codepointByImageId(Key key, int x, int y) {
|
||||
BitmapImage image = this.images.get(key);
|
||||
if (image == null) return -1;
|
||||
return image.codepointAt(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createOffsets(int offset, FontTagFormatter tagFormatter) {
|
||||
return Optional.ofNullable(this.offsetFont).map(it -> it.createOffset(offset, tagFormatter)).orElse("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Font> fontById(Key id) {
|
||||
return Optional.ofNullable(this.fonts.get(id));
|
||||
}
|
||||
|
||||
private Font getOrCreateFont(Key key) {
|
||||
return this.fonts.computeIfAbsent(key, Font::new);
|
||||
}
|
||||
|
||||
public class EmojiParser implements ConfigSectionParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[] {"emoji", "emojis"};
|
||||
|
||||
@Override
|
||||
public String[] sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int loadingSequence() {
|
||||
return LoadingSequence.EMOJI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class ImageParser implements ConfigSectionParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[] {"images", "image"};
|
||||
|
||||
@Override
|
||||
public String[] sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int loadingSequence() {
|
||||
return LoadingSequence.IMAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
Object heightObj = section.get("height");
|
||||
if (heightObj == null) {
|
||||
TranslationManager.instance().log("warning.config.image.lack_height", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
int height = MiscUtils.getAsInt(heightObj);
|
||||
int ascent = MiscUtils.getAsInt(section.getOrDefault("ascent", height - 1));
|
||||
if (height < ascent) {
|
||||
TranslationManager.instance().log("warning.config.image.height_smaller_than_ascent", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
Object file = section.get("file");
|
||||
if (file == null) {
|
||||
TranslationManager.instance().log("warning.config.image.no_file", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
String resourceLocation = file.toString().replace("\\", "/");
|
||||
if (!ResourceLocation.isValid(resourceLocation)) {
|
||||
TranslationManager.instance().log("warning.config.image.invalid_resource_location", path.toString(), id.toString(), resourceLocation);
|
||||
return;
|
||||
}
|
||||
|
||||
String fontName = (String) section.getOrDefault("font", "minecraft:default");
|
||||
if (!ResourceLocation.isValid(fontName)) {
|
||||
TranslationManager.instance().log("warning.config.image.invalid_font_name", path.toString(), id.toString(), fontName);
|
||||
return;
|
||||
}
|
||||
|
||||
Key fontKey = Key.withDefaultNamespace(fontName, id.namespace());
|
||||
Font font = getOrCreateFont(fontKey);
|
||||
List<char[]> chars;
|
||||
if (section.containsKey("chars")) {
|
||||
chars = MiscUtils.getAsStringList(section.get("chars")).stream().map(it -> {
|
||||
if (it.startsWith("\\u")) {
|
||||
return CharacterUtils.decodeUnicodeToChars(it);
|
||||
} else {
|
||||
return it.toCharArray();
|
||||
}
|
||||
}).toList();
|
||||
} else {
|
||||
String character = (String) section.get("char");
|
||||
if (character == null) {
|
||||
TranslationManager.instance().log("warning.config.image.lack_char", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
if (character.length() == 1) {
|
||||
chars = List.of(character.toCharArray());
|
||||
} else {
|
||||
chars = List.of(CharacterUtils.decodeUnicodeToChars(character));
|
||||
}
|
||||
}
|
||||
|
||||
int size = -1;
|
||||
int[][] codepointGrid = new int[chars.size()][];
|
||||
for (int i = 0; i < chars.size(); ++i) {
|
||||
int[] codepoints = CharacterUtils.charsToCodePoints(chars.get(i));
|
||||
for (int codepoint : codepoints) {
|
||||
if (font.isCodepointInUse(codepoint)) {
|
||||
BitmapImage image = font.bitmapImageByCodepoint(codepoint);
|
||||
TranslationManager.instance().log("warning.config.image.codepoint_in_use",
|
||||
path.toString(),
|
||||
id.toString(),
|
||||
fontKey.toString(),
|
||||
CharacterUtils.encodeCharsToUnicode(Character.toChars(codepoint)),
|
||||
new String(Character.toChars(codepoint)),
|
||||
image.id().toString()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
codepointGrid[i] = codepoints;
|
||||
if (size == -1) size = codepoints.length;
|
||||
if (size != codepoints.length) {
|
||||
TranslationManager.instance().log("warning.config.image.invalid_codepoint_grid", path.toString(), id.toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!resourceLocation.endsWith(".png")) resourceLocation += ".png";
|
||||
Key namespacedPath = Key.of(resourceLocation);
|
||||
Path targetImagePath = pack.resourcePackFolder()
|
||||
.resolve("assets")
|
||||
.resolve(namespacedPath.namespace())
|
||||
.resolve("textures")
|
||||
.resolve(namespacedPath.value());
|
||||
|
||||
if (!Files.exists(targetImagePath)) {
|
||||
TranslationManager.instance().log("warning.config.image.file_not_exist", path.toString(), id.toString(), targetImagePath.toString());
|
||||
// DO NOT RETURN, JUST GIVE WARNINGS
|
||||
}
|
||||
|
||||
BitmapImage bitmapImage = new BitmapImage(id, fontKey, height, ascent, resourceLocation, codepointGrid);
|
||||
for (int[] y : codepointGrid) {
|
||||
for (int x : y) {
|
||||
font.addBitMapImage(x, bitmapImage);
|
||||
}
|
||||
}
|
||||
|
||||
AbstractFontManager.this.images.put(id, bitmapImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.CharacterUtils;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.PreConditions;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public abstract class AbstractImageManager implements ImageManager {
|
||||
private final CraftEngine plugin;
|
||||
// namespace:font font
|
||||
private final HashMap<Key, Font> fonts = new HashMap<>();
|
||||
// namespace:id image
|
||||
private final HashMap<Key, BitmapImage> images = new HashMap<>();
|
||||
private final Set<Integer> illegalChars = new HashSet<>();
|
||||
|
||||
private OffsetFont offsetFont;
|
||||
|
||||
public AbstractImageManager(CraftEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
this.offsetFont = Optional.ofNullable(plugin.configManager().settings().getSection("offset-characters"))
|
||||
.map(OffsetFont::new)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
this.fonts.clear();
|
||||
this.images.clear();
|
||||
this.illegalChars.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delayedLoad() {
|
||||
Optional.ofNullable(this.fonts.get(DEFAULT_FONT)).ifPresent(font -> {
|
||||
this.illegalChars.addAll(font.codepointsInUse());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultFontInUse() {
|
||||
return !this.illegalChars.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIllegalCharacter(int codepoint) {
|
||||
return this.illegalChars.contains(codepoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
int height = MiscUtils.getAsInt(section.get("height"));
|
||||
int ascent = MiscUtils.getAsInt(section.get("ascent"));
|
||||
if (PreConditions.runIfTrue(height < ascent,
|
||||
() -> this.plugin.logger().warn(path, "Illegal ascent found at " + id + ". Height should be no lower than ascent"))) return;
|
||||
|
||||
String file = (String) section.get("file");
|
||||
if (PreConditions.isNull(file,
|
||||
() -> this.plugin.logger().warn(path, "`file` option is not set in image " + id))) return;
|
||||
|
||||
String fontName = (String) section.getOrDefault("font", "minecraft:default");
|
||||
if (PreConditions.isNull(fontName,
|
||||
() -> this.plugin.logger().warn(path, "`font` option is not set in image " + id))) return;
|
||||
|
||||
Key fontKey = Key.withDefaultNamespace(fontName, id.namespace());
|
||||
// get the font
|
||||
Font font = this.getOrCreateFont(fontKey);
|
||||
List<char[]> chars;
|
||||
if (section.containsKey("chars")) {
|
||||
chars = MiscUtils.getAsStringList(section.get("chars")).stream().map(it -> {
|
||||
if (it.startsWith("\\u")) {
|
||||
return CharacterUtils.decodeUnicodeToChars(it);
|
||||
} else {
|
||||
return it.toCharArray();
|
||||
}
|
||||
}).toList();
|
||||
} else {
|
||||
String character = (String) section.get("char");
|
||||
if (PreConditions.isNull(character,
|
||||
() -> this.plugin.logger().warn(path, "`char` option is not set in image " + id))) return;
|
||||
if (character.length() == 1) {
|
||||
chars = List.of(character.toCharArray());
|
||||
} else {
|
||||
chars = List.of(CharacterUtils.decodeUnicodeToChars(character));
|
||||
}
|
||||
}
|
||||
|
||||
int size = -1;
|
||||
int[][] codepointGrid = new int[chars.size()][];
|
||||
for (int i = 0; i < chars.size(); ++i) {
|
||||
int[] codepoints = CharacterUtils.charsToCodePoints(chars.get(i));
|
||||
for (int codepoint : codepoints) {
|
||||
if (PreConditions.runIfTrue(font.isCodepointInUse(codepoint),
|
||||
() -> this.plugin.logger().warn(path, String.format("Codepoint [%s (%s)] is already used in font [%s]", CharacterUtils.encodeCharsToUnicode(Character.toChars(codepoint)), new String(Character.toChars(codepoint)), font.key().toString())))) return;
|
||||
}
|
||||
codepointGrid[i] = codepoints;
|
||||
if (size == -1) size = codepoints.length;
|
||||
if (PreConditions.runIfTrue(size != codepoints.length,
|
||||
() -> this.plugin.logger().warn(path, "Illegal chars format found at " + id))) return;
|
||||
}
|
||||
|
||||
if (PreConditions.runIfTrue(size == -1,
|
||||
() -> this.plugin.logger().warn(path, "Illegal chars format found at " + id))) return;
|
||||
|
||||
if (!file.endsWith(".png")) file += ".png";
|
||||
file = file.replace("\\", "/");
|
||||
Key namespacedPath = Key.of(file);
|
||||
Path targetImageFile = pack.resourcePackFolder()
|
||||
.resolve("assets")
|
||||
.resolve(namespacedPath.namespace())
|
||||
.resolve("textures")
|
||||
.resolve(namespacedPath.value());
|
||||
|
||||
if (PreConditions.runIfTrue(!Files.exists(targetImageFile),
|
||||
() -> this.plugin.logger().warn(targetImageFile, "PNG file not found for image " + id))) return;
|
||||
|
||||
BitmapImage bitmapImage = new BitmapImage(id, fontKey, height, ascent, file, codepointGrid);
|
||||
for (int[] y : codepointGrid) {
|
||||
for (int x : y) {
|
||||
font.registerCodepoint(x, bitmapImage);
|
||||
}
|
||||
}
|
||||
|
||||
this.images.put(id, bitmapImage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Font> fontsInUse() {
|
||||
return new ArrayList<>(this.fonts.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BitmapImage> bitmapImageByCodepoint(Key font, int codepoint) {
|
||||
return getFontInUse(font).map(f -> f.getImageByCodepoint(codepoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BitmapImage> bitmapImageByImageId(Key id) {
|
||||
return Optional.ofNullable(this.images.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int codepointByImageId(Key key, int x, int y) {
|
||||
BitmapImage image = this.images.get(key);
|
||||
if (image == null) return -1;
|
||||
return image.codepointAt(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createOffsets(int offset, BiFunction<String, String, String> tagFormatter) {
|
||||
return Optional.ofNullable(this.offsetFont).map(it -> it.createOffset(offset, tagFormatter)).orElse("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Font> getFontInUse(Key key) {
|
||||
return Optional.ofNullable(fonts.get(key));
|
||||
}
|
||||
|
||||
private Font getOrCreateFont(Key key) {
|
||||
return this.fonts.computeIfAbsent(key, Font::new);
|
||||
}
|
||||
}
|
||||
@@ -7,15 +7,15 @@ import net.momirealms.craftengine.core.util.CharacterUtils;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
public class BitmapImage implements FontProvider {
|
||||
private final Key imageId;
|
||||
private final Key id;
|
||||
private final Key font;
|
||||
private final int height;
|
||||
private final int ascent;
|
||||
private final String file;
|
||||
private final int[][] codepointGrid;
|
||||
|
||||
public BitmapImage(Key imageId, Key font, int height, int ascent, String file, int[][] codepointGrid) {
|
||||
this.imageId = imageId;
|
||||
public BitmapImage(Key id, Key font, int height, int ascent, String file, int[][] codepointGrid) {
|
||||
this.id = id;
|
||||
this.font = font;
|
||||
this.height = height;
|
||||
this.ascent = ascent;
|
||||
@@ -39,16 +39,16 @@ public class BitmapImage implements FontProvider {
|
||||
return font;
|
||||
}
|
||||
|
||||
public Key imageId() {
|
||||
return imageId;
|
||||
public Key id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int[][] codepointGrid() {
|
||||
return codepointGrid;
|
||||
return codepointGrid.clone();
|
||||
}
|
||||
|
||||
public int codepointAt(int row, int column) {
|
||||
if (row < 0 || row >= codepointGrid.length || column < 0 || column >= codepointGrid[row].length) {
|
||||
if (!isValidCoordinate(row, column)) {
|
||||
throw new IndexOutOfBoundsException("Invalid index: (" + row + ", " + column + ")");
|
||||
}
|
||||
return codepointGrid[row][column];
|
||||
@@ -69,16 +69,16 @@ public class BitmapImage implements FontProvider {
|
||||
if (this == object) return true;
|
||||
if (object == null || getClass() != object.getClass()) return false;
|
||||
BitmapImage image = (BitmapImage) object;
|
||||
return imageId.equals(image.imageId);
|
||||
return id.equals(image.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return imageId.hashCode();
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject getJson() {
|
||||
public JsonObject get() {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("type", "bitmap");
|
||||
jsonObject.addProperty("height", height);
|
||||
|
||||
@@ -4,12 +4,12 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Font {
|
||||
private final Key key;
|
||||
private final HashMap<Integer, BitmapImage> idToCodepoint = new LinkedHashMap<>();
|
||||
private final Map<Integer, BitmapImage> idToCodepoint = new LinkedHashMap<>();
|
||||
|
||||
public Font(Key key) {
|
||||
this.key = key;
|
||||
@@ -24,11 +24,11 @@ public class Font {
|
||||
return Collections.unmodifiableCollection(this.idToCodepoint.keySet());
|
||||
}
|
||||
|
||||
public BitmapImage getImageByCodepoint(int codepoint) {
|
||||
public BitmapImage bitmapImageByCodepoint(int codepoint) {
|
||||
return this.idToCodepoint.get(codepoint);
|
||||
}
|
||||
|
||||
public void registerCodepoint(int codepoint, BitmapImage image) {
|
||||
public void addBitMapImage(int codepoint, BitmapImage image) {
|
||||
this.idToCodepoint.put(codepoint, image);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Font {
|
||||
}
|
||||
|
||||
public Collection<BitmapImage> bitmapImages() {
|
||||
return idToCodepoint.values().stream().distinct().toList();
|
||||
return this.idToCodepoint.values().stream().distinct().toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.plugin.Reloadable;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.util.CharacterUtils;
|
||||
@@ -9,10 +8,8 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public interface ImageManager extends Reloadable, ConfigSectionParser {
|
||||
String[] CONFIG_SECTION_NAME = new String[] {"images", "image"};
|
||||
public interface FontManager extends Reloadable {
|
||||
Key DEFAULT_FONT = Key.of("minecraft:default");
|
||||
String BYPASS_BOOK = "craftengine.filter.bypass.book";
|
||||
String BYPASS_SIGN = "craftengine.filter.bypass.sign";
|
||||
@@ -20,29 +17,23 @@ public interface ImageManager extends Reloadable, ConfigSectionParser {
|
||||
String BYPASS_COMMAND = "craftengine.filter.bypass.command";
|
||||
String BYPASS_ANVIL = "craftengine.filter.bypass.anvil";
|
||||
|
||||
default String[] sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
|
||||
default int loadingSequence() {
|
||||
return LoadingSequence.FONT;
|
||||
}
|
||||
ConfigSectionParser[] parsers();
|
||||
|
||||
boolean isDefaultFontInUse();
|
||||
|
||||
boolean isIllegalCharacter(int codepoint);
|
||||
boolean isIllegalCodepoint(int codepoint);
|
||||
|
||||
Collection<Font> fontsInUse();
|
||||
Collection<Font> fonts();
|
||||
|
||||
Optional<BitmapImage> bitmapImageByCodepoint(Key font, int codepoint);
|
||||
|
||||
default Optional<BitmapImage> getBitmapImageByChars(Key font, char[] chars) {
|
||||
default Optional<BitmapImage> bitmapImageByChars(Key font, char[] chars) {
|
||||
return bitmapImageByCodepoint(font, CharacterUtils.charsToCodePoint(chars));
|
||||
}
|
||||
|
||||
Optional<BitmapImage> bitmapImageByImageId(Key imageId);
|
||||
|
||||
Optional<Font> getFontInUse(Key font);
|
||||
Optional<Font> fontById(Key font);
|
||||
|
||||
int codepointByImageId(Key imageId, int x, int y);
|
||||
|
||||
@@ -50,15 +41,15 @@ public interface ImageManager extends Reloadable, ConfigSectionParser {
|
||||
return this.codepointByImageId(imageId, 0, 0);
|
||||
}
|
||||
|
||||
default char[] getCharsByImageId(Key imageId) {
|
||||
return getCharsByImageId(imageId, 0, 0);
|
||||
default char[] charsByImageId(Key imageId) {
|
||||
return charsByImageId(imageId, 0, 0);
|
||||
}
|
||||
|
||||
default char[] getCharsByImageId(Key imageId, int x, int y) {
|
||||
default char[] charsByImageId(Key imageId, int x, int y) {
|
||||
return Character.toChars(this.codepointByImageId(imageId, x, y));
|
||||
}
|
||||
|
||||
String createOffsets(int offset, BiFunction<String, String, String> tagFormatter);
|
||||
String createOffsets(int offset, FontTagFormatter tagFormatter);
|
||||
|
||||
default String createMiniMessageOffsets(int offset) {
|
||||
return createOffsets(offset, FormatUtils::miniMessageFont);
|
||||
@@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.font;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public interface FontProvider {
|
||||
import java.util.function.Supplier;
|
||||
|
||||
JsonObject getJson();
|
||||
public interface FontProvider extends Supplier<JsonObject> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public interface FontTagFormatter extends BiFunction<String, String, String> {
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package net.momirealms.craftengine.core.font.emoji;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
|
||||
public abstract class AbstractEmojiManager implements EmojiManager {
|
||||
protected CraftEngine plugin;
|
||||
|
||||
public AbstractEmojiManager(CraftEngine plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package net.momirealms.craftengine.core.font.emoji;
|
||||
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.plugin.Reloadable;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
|
||||
public interface EmojiManager extends Reloadable, ConfigSectionParser {
|
||||
String[] CONFIG_SECTION_NAME = new String[] {"emoji", "emojis"};
|
||||
|
||||
default String[] sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
|
||||
default int loadingSequence() {
|
||||
return LoadingSequence.EMOJI;
|
||||
}
|
||||
}
|
||||
@@ -1024,7 +1024,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
|
||||
private void generateFonts(Path generatedPackPath) {
|
||||
// generate image font json
|
||||
for (Font font : plugin.imageManager().fontsInUse()) {
|
||||
for (Font font : plugin.imageManager().fonts()) {
|
||||
Key namespacedKey = font.key();
|
||||
Path fontPath = generatedPackPath.resolve("assets")
|
||||
.resolve(namespacedKey.namespace())
|
||||
@@ -1058,7 +1058,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
}
|
||||
|
||||
for (BitmapImage image : font.bitmapImages()) {
|
||||
providers.add(image.getJson());
|
||||
providers.add(image.get());
|
||||
}
|
||||
|
||||
try (FileWriter fileWriter = new FileWriter(fontPath.toFile())) {
|
||||
|
||||
@@ -7,7 +7,7 @@ public class LoadingSequence {
|
||||
public static final int BLOCK = 30;
|
||||
public static final int ITEM = 40;
|
||||
public static final int FURNITURE = 50;
|
||||
public static final int FONT = 60;
|
||||
public static final int IMAGE = 60;
|
||||
public static final int RECIPE = 70;
|
||||
public static final int CATEGORY = 80;
|
||||
public static final int SOUND = 90;
|
||||
|
||||
@@ -14,6 +14,12 @@ public interface PackManager extends Reloadable {
|
||||
|
||||
boolean registerConfigSectionParser(ConfigSectionParser parser);
|
||||
|
||||
default void registerConfigSectionParsers(ConfigSectionParser[] parsers) {
|
||||
for (ConfigSectionParser parser : parsers) {
|
||||
registerConfigSectionParser(parser);
|
||||
}
|
||||
}
|
||||
|
||||
boolean unregisterConfigSectionParser(String id);
|
||||
|
||||
default void unregisterConfigSectionParser(ConfigSectionParser parser) {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package net.momirealms.craftengine.core.pack;
|
||||
|
||||
public class ResourceLocation {
|
||||
|
||||
public static boolean isValid(final String resourceLocation) {
|
||||
int index = resourceLocation.indexOf(":");
|
||||
if (index == -1) {
|
||||
return isValidPath(resourceLocation);
|
||||
} else {
|
||||
return isValidNamespace(resourceLocation.substring(0, index)) && isValidPath(resourceLocation.substring(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean validPathChar(char character) {
|
||||
return character == '_' || character == '-' || character >= 'a' && character <= 'z' || character >= '0' && character <= '9' || character == '/' || character == '.';
|
||||
}
|
||||
|
||||
private static boolean validNamespaceChar(char character) {
|
||||
return character == '_' || character == '-' || character >= 'a' && character <= 'z' || character >= '0' && character <= '9' || character == '.';
|
||||
}
|
||||
|
||||
private static boolean isValidNamespace(String namespace) {
|
||||
for(int i = 0; i < namespace.length(); ++i) {
|
||||
if (!validNamespaceChar(namespace.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isValidPath(String path) {
|
||||
for(int i = 0; i < path.length(); ++i) {
|
||||
if (!validPathChar(path.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.plugin;
|
||||
|
||||
import net.momirealms.craftengine.core.block.BlockManager;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureManager;
|
||||
import net.momirealms.craftengine.core.font.ImageManager;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.item.ItemManager;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeManager;
|
||||
import net.momirealms.craftengine.core.loot.VanillaLootManager;
|
||||
@@ -45,7 +45,7 @@ public abstract class CraftEngine implements Plugin {
|
||||
protected SchedulerAdapter<?> scheduler;
|
||||
protected NetworkManager networkManager;
|
||||
protected ClassPathAppender classPathAppender;
|
||||
protected ImageManager imageManager;
|
||||
protected FontManager fontManager;
|
||||
protected PackManager packManager;
|
||||
protected ConfigManager configManager;
|
||||
protected ItemManager<?> itemManager;
|
||||
@@ -106,7 +106,7 @@ public abstract class CraftEngine implements Plugin {
|
||||
this.translationManager.reload();
|
||||
this.templateManager.reload();
|
||||
this.furnitureManager.reload();
|
||||
this.imageManager.reload();
|
||||
this.fontManager.reload();
|
||||
this.itemManager.reload();
|
||||
this.soundManager.reload();
|
||||
this.recipeManager.reload();
|
||||
@@ -124,7 +124,7 @@ public abstract class CraftEngine implements Plugin {
|
||||
this.furnitureManager.delayedLoad();
|
||||
this.itemBrowserManager.delayedLoad();
|
||||
this.soundManager.delayedLoad();
|
||||
this.imageManager.delayedLoad();
|
||||
this.fontManager.delayedLoad();
|
||||
// reset debugger
|
||||
if (ConfigManager.debug()) {
|
||||
this.debugger = (s) -> logger.info("[Debug] " + s.get());
|
||||
@@ -153,7 +153,7 @@ public abstract class CraftEngine implements Plugin {
|
||||
this.worldManager.delayedInit();
|
||||
this.packManager.delayedInit();
|
||||
this.furnitureManager.delayedInit();
|
||||
this.imageManager.delayedInit();
|
||||
this.fontManager.delayedInit();
|
||||
this.vanillaLootManager.delayedInit();
|
||||
this.delayedEnable();
|
||||
});
|
||||
@@ -164,7 +164,7 @@ public abstract class CraftEngine implements Plugin {
|
||||
if (this.senderFactory != null) this.senderFactory.close();
|
||||
if (this.commandManager != null) this.commandManager.unregisterFeatures();
|
||||
if (this.networkManager != null) this.networkManager.shutdown();
|
||||
if (this.imageManager != null) this.imageManager.disable();
|
||||
if (this.fontManager != null) this.fontManager.disable();
|
||||
if (this.packManager != null) this.packManager.disable();
|
||||
if (this.itemManager != null) this.itemManager.disable();
|
||||
if (this.blockManager != null) this.blockManager.disable();
|
||||
@@ -241,8 +241,8 @@ public abstract class CraftEngine implements Plugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageManager imageManager() {
|
||||
return imageManager;
|
||||
public FontManager imageManager() {
|
||||
return fontManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.momirealms.craftengine.core.plugin;
|
||||
import net.momirealms.craftengine.core.block.BlockManager;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureManager;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.font.ImageManager;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.item.ItemManager;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeManager;
|
||||
import net.momirealms.craftengine.core.loot.VanillaLootManager;
|
||||
@@ -55,7 +55,7 @@ public interface Plugin extends Reloadable {
|
||||
|
||||
NetworkManager networkManager();
|
||||
|
||||
ImageManager imageManager();
|
||||
FontManager imageManager();
|
||||
|
||||
ConfigManager configManager();
|
||||
|
||||
|
||||
@@ -10,9 +10,11 @@ import java.util.UUID;
|
||||
|
||||
public abstract class SenderFactory<P extends Plugin, T> {
|
||||
private final P plugin;
|
||||
private final Sender console;
|
||||
|
||||
public SenderFactory(P plugin) {
|
||||
this.plugin = plugin;
|
||||
this.console = wrap(consoleCommandSender());
|
||||
}
|
||||
|
||||
protected P plugin() {
|
||||
@@ -35,10 +37,16 @@ public abstract class SenderFactory<P extends Plugin, T> {
|
||||
|
||||
protected abstract boolean isConsole(T sender);
|
||||
|
||||
protected abstract <C extends T> C consoleCommandSender();
|
||||
|
||||
protected boolean consoleHasAllPermissions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Sender console() {
|
||||
return console;
|
||||
}
|
||||
|
||||
public <C extends T> Sender wrap(C sender) {
|
||||
Objects.requireNonNull(sender, "sender");
|
||||
return new AbstractSender<>(this.plugin, this, sender);
|
||||
|
||||
@@ -45,4 +45,6 @@ public interface TranslationManager extends Reloadable, ConfigSectionParser {
|
||||
default String[] sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
|
||||
void log(String id, String... args);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.Plugin;
|
||||
import net.momirealms.craftengine.core.plugin.PluginProperties;
|
||||
import net.momirealms.craftengine.core.plugin.config.StringKeyConstructor;
|
||||
import net.momirealms.craftengine.core.plugin.text.minimessage.IndexedArgumentTag;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -235,6 +236,13 @@ public class TranslationManagerImpl implements TranslationManager {
|
||||
return clientLangManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String id, String... args) {
|
||||
String translation = miniMessageTranslation(id);
|
||||
if (translation == null) translation = id;
|
||||
this.plugin.senderFactory().console().sendMessage(AdventureHelper.miniMessage().deserialize(translation, new IndexedArgumentTag(Arrays.stream(args).map(Component::text).toList())));
|
||||
}
|
||||
|
||||
private Map<String, Object> updateLangFile(Map<String, Object> previous, Path translationFile) throws IOException {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
|
||||
Reference in New Issue
Block a user