refactor: refactored Glyphs library + refactored resources
This commit is contained in:
parent
4299b8efa6
commit
4877ea4547
@ -1,22 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api;
|
|
||||||
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import net.minestom.server.entity.GameMode;
|
|
||||||
import ru.dragonestia.msb3.api.module.FlatWorldModule;
|
|
||||||
import ru.dragonestia.msb3.api.module.MotdModule;
|
|
||||||
import ru.dragonestia.msb3.api.module.ResourcePackRepositoryModule;
|
|
||||||
|
|
||||||
@Log4j2
|
|
||||||
public class Bootstrap {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
var boot = new ServerBootstrap();
|
|
||||||
|
|
||||||
MotdModule.init("logo.png", "<gradient:#ff0059:#e06806><bold>msb3 server</bold></gradient>");
|
|
||||||
FlatWorldModule.init(GameMode.ADVENTURE);
|
|
||||||
|
|
||||||
ResourcePackRepositoryModule.init(boot, "0.0.0.0", 7270);
|
|
||||||
|
|
||||||
boot.start("0.0.0.0", 25565);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import net.minestom.server.MinecraftServer;
|
|
||||||
import ru.dragonestia.msb3.api.item.ItemPrefabManager;
|
|
||||||
import ru.dragonestia.msb3.api.item.ItemUtil;
|
|
||||||
import ru.dragonestia.msb3.api.resource.ResourcePackManager;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
|
|
||||||
@Log4j2
|
|
||||||
public class ServerBootstrap {
|
|
||||||
|
|
||||||
public static final ClassLoader CLASS_LOADER = ServerBootstrap.class.getClassLoader();
|
|
||||||
|
|
||||||
private static final String[] LOGO = {
|
|
||||||
"==============================================",
|
|
||||||
"Minestom Server Base v3 - by ScarletRedMan",
|
|
||||||
"",
|
|
||||||
" 8b d8 .dP\"Y8 88\"\"Yb 88888 ",
|
|
||||||
" 88b d88 `Ybo.\" 88__dP .dP ",
|
|
||||||
" 88YbdP88 o.`Y8b 88\"\"Yb o `Yb ",
|
|
||||||
" 88 YY 88 8bodP' 88oodP YbodP ",
|
|
||||||
"",
|
|
||||||
"Minecraft version: " + MinecraftServer.VERSION_NAME + " (protocol: " + MinecraftServer.PROTOCOL_VERSION + ")",
|
|
||||||
"==============================================",
|
|
||||||
};
|
|
||||||
|
|
||||||
@Getter private static ServerBootstrap instance;
|
|
||||||
@Getter private static boolean started = false;
|
|
||||||
|
|
||||||
private final MinecraftServer server;
|
|
||||||
@Getter private final ResourcePackManager resourcePackManager;
|
|
||||||
@Getter private final ItemPrefabManager itemPrefabManager;
|
|
||||||
|
|
||||||
public ServerBootstrap() {
|
|
||||||
instance = this;
|
|
||||||
|
|
||||||
for (var line: LOGO) log.info(line);
|
|
||||||
|
|
||||||
server = MinecraftServer.init();
|
|
||||||
|
|
||||||
MinecraftServer.setBrandName("Dragonestia");
|
|
||||||
|
|
||||||
resourcePackManager = new ResourcePackManager();
|
|
||||||
itemPrefabManager = new ItemPrefabManager();
|
|
||||||
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start(String address, int port) {
|
|
||||||
started = true;
|
|
||||||
server.start(new InetSocketAddress(address, port));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
ItemUtil.init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
package ru.dragonestia.msb3.api.boot;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import net.minestom.server.MinecraftServer;
|
||||||
|
import net.minestom.server.entity.GameMode;
|
||||||
|
import net.minestom.server.event.player.PlayerChatEvent;
|
||||||
|
import ru.dragonestia.msb3.api.module.FlatWorldModule;
|
||||||
|
import ru.dragonestia.msb3.api.module.MotdModule;
|
||||||
|
import ru.dragonestia.msb3.api.module.ResourcePackRepositoryModule;
|
||||||
|
import ru.dragonestia.msb3.api.resource.dialog.ButtonNumber;
|
||||||
|
import ru.dragonestia.msb3.api.talk.dialogue.DialogueRenderer;
|
||||||
|
import ru.dragonestia.msb3.api.talk.dialogue.DialogueTheme;
|
||||||
|
import team.unnamed.creative.ResourcePack;
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
public class DefaultBootstrap extends ServerInitializer {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ServerBootstrap.start("0.0.0.0", 25565, new DefaultBootstrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDefaultModulesLoaded() {
|
||||||
|
MotdModule.init("logo.png", "<gradient:#ff0059:#e06806><bold>msb3 server</bold></gradient>");
|
||||||
|
FlatWorldModule.init(GameMode.ADVENTURE);
|
||||||
|
|
||||||
|
MinecraftServer.getGlobalEventHandler().addListener(PlayerChatEvent.class, event -> {
|
||||||
|
var player = event.getPlayer();
|
||||||
|
|
||||||
|
var render = new DialogueRenderer(player, DialogueTheme.builder().build());
|
||||||
|
render.setText("""
|
||||||
|
Абсолютно точно.
|
||||||
|
Я знаю точнo - невозможное возможно
|
||||||
|
Сойти с ума, влюбиться так неосторoжно
|
||||||
|
Найти тебя, не отпускать ни днём, ни ночью
|
||||||
|
Всё невозможное - возможно, знаю точно!
|
||||||
|
А где тебя искать, прошу ты мне ответь
|
||||||
|
В какие города мне за тобой лететь
|
||||||
|
Я готов на край Земли, я всё должен объяснить
|
||||||
|
Пойми, что без тебя я не умею жить
|
||||||
|
Я знаю точно - невозможное возможно
|
||||||
|
Сойти с ума, влюбиться так неосторожно
|
||||||
|
Найти тебя, не отпускать ни днём, ни ночью
|
||||||
|
Всё невозможное - возможно, знаю точно!
|
||||||
|
На-на-на-на (на-на-на-на), а-а, а-а
|
||||||
|
На-на-на-на (на-на-на-на), а-а, а-а
|
||||||
|
Всё готов делить, с тобой я пополам
|
||||||
|
Ты только мне поверь, я сделал выбор сам
|
||||||
|
Дай же мне последний шанс, я всё должен объяснить
|
||||||
|
Пойми, что без тебя я не умею жить
|
||||||
|
Я знаю точно - невозможное возможно
|
||||||
|
Сойти с ума, влюбиться так неосторожно
|
||||||
|
Найти тебя, не отпускать ни днём, ни ночью
|
||||||
|
Всё невозможное - возможно, знаю точно!
|
||||||
|
На-на-на-на (на-на-на-на), а-а, а-а
|
||||||
|
На-на-на-на (на-на-на-на), а-а, а-а
|
||||||
|
Я знаю точно - невозможное возможно
|
||||||
|
Сойти с ума, влюбиться так неосторожно
|
||||||
|
Найти тебя, не отпускать ни днём, ни ночью
|
||||||
|
Всё невозможное - возможно, знаю точно!
|
||||||
|
На-на-на-на (на-на-на-на), а-а, а-а
|
||||||
|
На-на-на-на (на-на-на-на), а-а, а-а""");
|
||||||
|
|
||||||
|
render.setButton(ButtonNumber.BUTTON_1, "Hello world!\nHello world!\nHello world!\nHello world!\nHello world!", ctx -> {});
|
||||||
|
render.setButton(ButtonNumber.BUTTON_2, "I am a teapot", ctx -> {});
|
||||||
|
render.setButton(ButtonNumber.BUTTON_3, "I love pizza\nMamma mia\nPeperoni\nPapa carlo\nZaebumba\nZaebumba", ctx -> {});
|
||||||
|
render.setButton(ButtonNumber.BUTTON_4, "msb3 is top!", ctx -> {});
|
||||||
|
|
||||||
|
render.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitializeResources(ResourcePack resourcePack) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResourcePackCompiled(ResourcePack resourcePack) {
|
||||||
|
ResourcePackRepositoryModule.init("0.0.0.0", 7270);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,143 @@
|
|||||||
|
package ru.dragonestia.msb3.api.boot;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.minestom.server.MinecraftServer;
|
||||||
|
import ru.dragonestia.msb3.api.item.ItemUtil;
|
||||||
|
import ru.dragonestia.msb3.api.resource.DialogueResources;
|
||||||
|
import ru.dragonestia.msb3.api.resource.MonologueResources;
|
||||||
|
import ru.dragonestia.msb3.api.title.BlackScreen;
|
||||||
|
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
||||||
|
import ru.dragonestia.msb3.resource.Resources;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.GlyphCharacterFactory;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.MinecraftFont;
|
||||||
|
import ru.dragonestia.msb3.resource.utils.ClassPreLoader;
|
||||||
|
import team.unnamed.creative.lang.Language;
|
||||||
|
import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackWriter;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@UtilityClass
|
||||||
|
public final class ServerBootstrap {
|
||||||
|
|
||||||
|
public static final ClassLoader CLASS_LOADER = ServerBootstrap.class.getClassLoader();
|
||||||
|
|
||||||
|
private static final String[] LOGO = {
|
||||||
|
"==============================================",
|
||||||
|
"Minestom Server Base v3 - by ScarletRedMan",
|
||||||
|
"",
|
||||||
|
" 8b d8 .dP\"Y8 88\"\"Yb 88888 ",
|
||||||
|
" 88b d88 `Ybo.\" 88__dP .dP ",
|
||||||
|
" 88YbdP88 o.`Y8b 88\"\"Yb o `Yb ",
|
||||||
|
" 88 YY 88 8bodP' 88oodP YbodP ",
|
||||||
|
"",
|
||||||
|
"Minecraft version: " + MinecraftServer.VERSION_NAME + " (protocol: " + MinecraftServer.PROTOCOL_VERSION + ")",
|
||||||
|
"==============================================",
|
||||||
|
};
|
||||||
|
|
||||||
|
@Getter private boolean started = false;
|
||||||
|
|
||||||
|
private final MinecraftServer server = preInitialize();
|
||||||
|
|
||||||
|
private MinecraftServer preInitialize() {
|
||||||
|
for (var line: LOGO) log.info(line);
|
||||||
|
|
||||||
|
var server = MinecraftServer.init();
|
||||||
|
MinecraftServer.setBrandName("Dragonestia");
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void start(String address, int port, ServerInitializer initializer) {
|
||||||
|
if (started) return;
|
||||||
|
|
||||||
|
started = true;
|
||||||
|
init(initializer);
|
||||||
|
server.start(new InetSocketAddress(address, port));
|
||||||
|
initializer.onServerStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(ServerInitializer initializer) {
|
||||||
|
initializer.onLoad();
|
||||||
|
|
||||||
|
initDefaultModules();
|
||||||
|
initializer.onDefaultModulesLoaded();
|
||||||
|
|
||||||
|
initDefaultGlyphs();
|
||||||
|
initializer.onInitializeResources(Resources.getResourcePack());
|
||||||
|
|
||||||
|
compileResourcePack();
|
||||||
|
initializer.onResourcePackCompiled(Resources.getResourcePack());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDefaultModules() {
|
||||||
|
ItemUtil.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void compileResourcePack() {
|
||||||
|
var resourcePack = Resources.compile();
|
||||||
|
|
||||||
|
log.info("Used {}/{} glyphs", GlyphCharacterFactory.countUsedChars(), GlyphCharacterFactory.countCharRange());
|
||||||
|
|
||||||
|
var file = new File("./resource-pack.zip");
|
||||||
|
MinecraftResourcePackWriter.minecraft().writeToZipFile(file, resourcePack);
|
||||||
|
|
||||||
|
log.info("Compiled resource pack. File: ./resource-pack.zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDefaultGlyphs() {
|
||||||
|
ClassPreLoader.preload(BlackScreen.class);
|
||||||
|
|
||||||
|
MonologueResources.registerAvatar(MonologueResources.DEFAULT, ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/monologue/default_avatar.png"));
|
||||||
|
MonologueResources.registerFrame(MonologueResources.DEFAULT, ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/monologue/avatar_frame.png"));
|
||||||
|
|
||||||
|
DialogueResources.registerAvatar(DialogueResources.DEFAULT, ResourceFromJar.of("glyphs/dialogue/default_avatar.png"));
|
||||||
|
DialogueResources.registerAvatarFrame(DialogueResources.DEFAULT, ResourceFromJar.of("glyphs/dialogue/avatar_frame.png"));
|
||||||
|
DialogueResources.registerScrollUp(DialogueResources.DEFAULT, ResourceFromJar.of("glyphs/dialogue/scroll_phrase_up_button.png"));
|
||||||
|
DialogueResources.registerScrollDown(DialogueResources.DEFAULT, ResourceFromJar.of("glyphs/dialogue/scroll_phrase_down_button.png"));
|
||||||
|
DialogueResources.registerBackground(DialogueResources.DEFAULT, ResourceFromJar.of("glyphs/dialogue/background.png"));
|
||||||
|
DialogueResources.registerSubstrate(DialogueResources.DEFAULT, ResourceFromJar.of("glyphs/dialogue/phrase_substrate.png"));
|
||||||
|
DialogueResources.registerActiveTextField(DialogueResources.DEFAULT, ResourceFromJar.of("glyphs/dialogue/answer_active_text_field.png"));
|
||||||
|
DialogueResources.registerNotActiveTextField(DialogueResources.DEFAULT, ResourceFromJar.of("glyphs/dialogue/answer_not_active_text_field.png"));
|
||||||
|
DialogueResources.registerButton(DialogueResources.DEFAULT + 1, ResourceFromJar.of("glyphs/dialogue/answer_button_active_1.png"));
|
||||||
|
DialogueResources.registerButton(DialogueResources.DEFAULT + 2, ResourceFromJar.of("glyphs/dialogue/answer_button_active_2.png"));
|
||||||
|
DialogueResources.registerButton(DialogueResources.DEFAULT + 3, ResourceFromJar.of("glyphs/dialogue/answer_button_active_3.png"));
|
||||||
|
DialogueResources.registerButton(DialogueResources.DEFAULT + 4, ResourceFromJar.of("glyphs/dialogue/answer_button_active_4.png"));
|
||||||
|
initDialogueFont();
|
||||||
|
initLocales();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDialogueFont() {
|
||||||
|
MinecraftFont.compileFontProvider(8, -28);
|
||||||
|
MinecraftFont.compileFontProvider(8, -37);
|
||||||
|
MinecraftFont.compileFontProvider(8, -46);
|
||||||
|
MinecraftFont.compileFontProvider(8, -55);
|
||||||
|
MinecraftFont.compileFontProvider(8, -64);
|
||||||
|
MinecraftFont.compileFontProvider(8, -73);
|
||||||
|
MinecraftFont.compileFontProvider(8, -82);
|
||||||
|
|
||||||
|
MinecraftFont.compileFontProvider(8, -122);
|
||||||
|
MinecraftFont.compileFontProvider(8, -131);
|
||||||
|
MinecraftFont.compileFontProvider(8, -140);
|
||||||
|
MinecraftFont.compileFontProvider(8, -149);
|
||||||
|
|
||||||
|
MinecraftFont.compileFontProvider(8, -170);
|
||||||
|
MinecraftFont.compileFontProvider(8, -179);
|
||||||
|
MinecraftFont.compileFontProvider(8, -188);
|
||||||
|
MinecraftFont.compileFontProvider(8, -197);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initLocales() {
|
||||||
|
var locales = new HashMap<String, String>();
|
||||||
|
locales.put("container.inventory", " ");
|
||||||
|
|
||||||
|
for (var lang: List.of("en_us", "ru_ru")) {
|
||||||
|
Resources.getResourcePack().language(Language.language(Key.key("minecraft", lang), locales));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
package ru.dragonestia.msb3.api.boot;
|
||||||
|
|
||||||
|
import team.unnamed.creative.ResourcePack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс инициализатора сервера. Здесь имеются все точки состояний сервера.
|
||||||
|
* Создан для того чтобы было проще прописывать логику инициализации сервера
|
||||||
|
*/
|
||||||
|
public abstract class ServerInitializer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запускается при самом старте приложения, когда никакая конфигурация сервера еще не подгружена
|
||||||
|
*/
|
||||||
|
public void onLoad() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запускается после инициализации всех стандартных модулей сервера
|
||||||
|
*/
|
||||||
|
public abstract void onDefaultModulesLoaded();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запускается на стадии подготовки всех ресурсов, которые необходимо скомпилировать и добавить в ресурс-пак.
|
||||||
|
*
|
||||||
|
* <p>Именно на данном этапе необходимо регистрировать глифы.
|
||||||
|
* @param resourcePack Ресурс-пак
|
||||||
|
*/
|
||||||
|
public void onInitializeResources(ResourcePack resourcePack) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запускается после того как все пакеты ресурсов были успешно скомпилированы и готовы к последующей упаковке
|
||||||
|
* и отправке клиенту игрока.
|
||||||
|
*
|
||||||
|
* <p> Сервер в данном состоянии еще не полностью загружен
|
||||||
|
* @param resourcePack Скомпилированный ресурс-пак
|
||||||
|
*/
|
||||||
|
public void onResourcePackCompiled(ResourcePack resourcePack) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сервер полностью запущен и доступен для игры
|
||||||
|
*/
|
||||||
|
public void onServerStarted() {}
|
||||||
|
}
|
||||||
@ -1,7 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph;
|
|
||||||
|
|
||||||
public final class GlyphConstants {
|
|
||||||
|
|
||||||
public static final int CHEST_GUI_WIDTH = 176;
|
|
||||||
public static final int DEFAULT_CHAT_WIDTH = 320;
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.compile;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public interface ArbitraryCharacterFactory {
|
|
||||||
|
|
||||||
@NotNull Character nextCharacter() throws IllegalStateException;
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.compile;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class DefaultArbitraryCharacterFactory implements ArbitraryCharacterFactory {
|
|
||||||
|
|
||||||
private final static Set<Character> reservedCharacters = new HashSet<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
for (char c = 'a'; c <= 'z'; c++) reservedCharacters.add(c);
|
|
||||||
for (char c = 'A'; c <= 'Z'; c++) reservedCharacters.add(c);
|
|
||||||
for (char c = 'а'; c <= 'я'; c++) reservedCharacters.add(c);
|
|
||||||
for (char c = 'А'; c <= 'Я'; c++) reservedCharacters.add(c);
|
|
||||||
for (char c = '0'; c <= '9'; c++) reservedCharacters.add(c);
|
|
||||||
|
|
||||||
reservedCharacters.addAll(Arrays.asList(
|
|
||||||
'!', '?', ':', '$',
|
|
||||||
';', '#', '@', '%',
|
|
||||||
'^', '&', '*', '(',
|
|
||||||
')', '_', '-', '+',
|
|
||||||
'/', '\\', '№', '"',
|
|
||||||
'\'', '{', '}', '[',
|
|
||||||
']', '~', '`', '<', '>',
|
|
||||||
',', '.', '|', '\n', '\r',
|
|
||||||
'\b', '\f', '\t', ' ',
|
|
||||||
'ё', 'Ё', '=')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private char currentChar = '\uA201';
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Character nextCharacter() throws IllegalStateException {
|
|
||||||
if (currentChar == Character.MAX_VALUE) {
|
|
||||||
throw new IllegalStateException("Characters range exceeded");
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
currentChar++;
|
|
||||||
} while (!isCharacterAllowed(currentChar));
|
|
||||||
return currentChar;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isCharacterAllowed(char c) {
|
|
||||||
return !reservedCharacters.contains(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.compile;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import team.unnamed.creative.font.Font;
|
|
||||||
import team.unnamed.creative.font.FontProvider;
|
|
||||||
import team.unnamed.creative.part.ResourcePackPart;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class DefaultGlyphCompiler implements GlyphCompiler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull ResourcePackPart> compile(@NotNull Collection<@NotNull ResourceProducer> producers) {
|
|
||||||
Set<ResourcePackPart> fileResources = new HashSet<>();
|
|
||||||
|
|
||||||
Set<Key> fontKeys = producers
|
|
||||||
.stream()
|
|
||||||
.map(ResourceProducer::fontKey)
|
|
||||||
.collect(Collectors.toUnmodifiableSet());
|
|
||||||
|
|
||||||
for (Key key : fontKeys) {
|
|
||||||
List<FontProvider> fontProviders = new ArrayList<>();
|
|
||||||
ArbitraryCharacterFactory characterFactory = new DefaultArbitraryCharacterFactory();
|
|
||||||
for (ResourceProducer producer : producers) {
|
|
||||||
if (producer.fontKey().equals(key)) {
|
|
||||||
producer.produceResources(characterFactory);
|
|
||||||
// Add font providers for current font key
|
|
||||||
fontProviders.addAll(producer.fontProviders());
|
|
||||||
// Add textures to common set with resources
|
|
||||||
fileResources.addAll(producer.textures());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fileResources.add(Font.font(key, fontProviders));
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileResources;
|
|
||||||
}
|
|
||||||
|
|
||||||
<T> Iterable<T> toIterable(final Stream<T> stream) {
|
|
||||||
return stream::iterator;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.compile;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import team.unnamed.creative.part.ResourcePackPart;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public interface GlyphCompiler {
|
|
||||||
|
|
||||||
static GlyphCompiler instance() {
|
|
||||||
return new DefaultGlyphCompiler();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull Collection<@NotNull ResourcePackPart> compile(@NotNull Collection<@NotNull ResourceProducer> resourceProducerCollection);
|
|
||||||
|
|
||||||
default @NotNull Collection<@NotNull ResourcePackPart> compile(@NotNull ResourceProducer... resourceProducer) {
|
|
||||||
return compile(Arrays.asList(resourceProducer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.compile;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceAlreadyProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import team.unnamed.creative.font.FontProvider;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
public interface ResourceProducer {
|
|
||||||
|
|
||||||
@NotNull Key fontKey();
|
|
||||||
|
|
||||||
boolean produced();
|
|
||||||
|
|
||||||
void produceResources(ArbitraryCharacterFactory characterFactory) throws ResourceAlreadyProducedException;
|
|
||||||
|
|
||||||
@NotNull Collection<@NotNull FontProvider> fontProviders() throws ResourceNotProducedException;
|
|
||||||
|
|
||||||
default @NotNull Collection<@NotNull Texture> textures() throws ResourceNotProducedException {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.font;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.GlyphCompiler;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter.LanguageGlyphCollection;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.SpacesGlyphResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.mojang.MojangSpacesGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
|
||||||
import team.unnamed.creative.base.Writable;
|
|
||||||
import team.unnamed.creative.part.ResourcePackPart;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class GlyphFont {
|
|
||||||
|
|
||||||
public static final SpacesGlyphResourceProducer SPACES = MojangSpacesGlyph.create();
|
|
||||||
private static final Key MINECRAFT_FONT_KEY = Key.key(Glyph.DEFAULT_NAMESPACE, "minecraft_font");
|
|
||||||
private static final Writable MINECRAFT_FONT_IMAGE_WRITABLE = ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/defaults/minecraft_font.png");
|
|
||||||
public static final LanguageGlyphCollection LANGUAGE_GLYPH = minecraftFontGlyphCollection(
|
|
||||||
MINECRAFT_FONT_KEY,
|
|
||||||
Key.key(MINECRAFT_FONT_KEY.asString().concat(".png")),
|
|
||||||
MINECRAFT_FONT_IMAGE_WRITABLE,
|
|
||||||
List.of(new TextureProperties(12,-6),
|
|
||||||
new TextureProperties(8,-24),
|
|
||||||
new TextureProperties(8,8),
|
|
||||||
new TextureProperties(8,-36)));
|
|
||||||
|
|
||||||
private GlyphFont() {}
|
|
||||||
|
|
||||||
public static Collection<ResourcePackPart> compile() {
|
|
||||||
return GlyphCompiler.instance().compile(SPACES, LANGUAGE_GLYPH);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NotNull LanguageGlyphCollection minecraftFontGlyphCollection(@NotNull Key fontKey, @NotNull Key textureKey, @NotNull List<@NotNull TextureProperties> propertiesList) {
|
|
||||||
return minecraftFontGlyphCollection(fontKey, textureKey, MINECRAFT_FONT_IMAGE_WRITABLE, propertiesList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NotNull LanguageGlyphCollection minecraftFontGlyphCollection(
|
|
||||||
@NotNull Key fontKey,
|
|
||||||
@NotNull Key textureKey,
|
|
||||||
@NotNull Writable writable,
|
|
||||||
@NotNull List<@NotNull TextureProperties> propertiesList
|
|
||||||
) {
|
|
||||||
return LanguageGlyphCollection.of(fontKey,
|
|
||||||
Texture.texture(textureKey, writable),
|
|
||||||
propertiesList,
|
|
||||||
List.of(" АБВГДЕЖЗИК",
|
|
||||||
"ЛМНОПРСТУФХЦЧШЩЪ",
|
|
||||||
"ЫЬЭЮЯабвгдежзикл",
|
|
||||||
"мнопрстуфхцчшщъы",
|
|
||||||
"ьэюяйЙёЁ ",
|
|
||||||
"₽!\"#$%&'()*+,-./",
|
|
||||||
"0123456789: <=>?",
|
|
||||||
"@ABCDEFGHIJKLMNO",
|
|
||||||
"PQRSTUVWXYZ[\\]^_",
|
|
||||||
"`abcdefghijklmno",
|
|
||||||
"pqrstuvwxyz{|} ")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph;
|
|
||||||
|
|
||||||
public interface AppendableGlyph extends Glyph {}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph;
|
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class EmptyGlyph implements AppendableGlyph {
|
|
||||||
|
|
||||||
public static final EmptyGlyph INSTANCE = new EmptyGlyph();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Component toAdventure() throws ResourceNotProducedException {
|
|
||||||
return Component.text("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int width() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
|
|
||||||
public interface Glyph {
|
|
||||||
|
|
||||||
String DEFAULT_NAMESPACE = "msb3";
|
|
||||||
|
|
||||||
Key DEFAULT_FONT_KEY = Key.key(DEFAULT_NAMESPACE, "default");
|
|
||||||
|
|
||||||
Key DEFAULT_SPACES_FONT_KEY = Key.key(DEFAULT_NAMESPACE, "spaces");
|
|
||||||
|
|
||||||
int SEPARATOR_WIDTH = 1;
|
|
||||||
|
|
||||||
@NotNull Component toAdventure() throws ResourceNotProducedException;
|
|
||||||
|
|
||||||
int width();
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph;
|
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.SpacesGlyphResourceProducer;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface GlyphComponentBuilder {
|
|
||||||
|
|
||||||
static @NotNull GlyphComponentBuilder universal(SpacesGlyphResourceProducer spacesProducer) {
|
|
||||||
return new GlyphComponentBuilderImpl(spacesProducer, 0, Component.text(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
static @NotNull GlyphComponentBuilder gui(SpacesGlyphResourceProducer spacesProducer) {
|
|
||||||
return new GlyphComponentBuilderImpl(spacesProducer, -8, Component.text("", NamedTextColor.WHITE));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull GlyphComponentBuilder append(PositionType positionType, int position, @NotNull AppendableGlyph glyph);
|
|
||||||
|
|
||||||
default @NotNull GlyphComponentBuilder append(PositionType positionType, @NotNull AppendableGlyph glyph) {
|
|
||||||
return append(positionType, 0, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull GlyphComponentBuilder append(PositionType positionType, int position, @NotNull List<? extends @NotNull AppendableGlyph> glyphList);
|
|
||||||
|
|
||||||
default @NotNull GlyphComponentBuilder append(PositionType positionType, @NotNull List<? extends @NotNull AppendableGlyph> glyphList) {
|
|
||||||
return append(positionType, 0, glyphList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append with default position type
|
|
||||||
|
|
||||||
default @NotNull GlyphComponentBuilder append(int position, @NotNull AppendableGlyph glyph) {
|
|
||||||
return append(PositionType.ABSOLUTE, position, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
default @NotNull GlyphComponentBuilder append(@NotNull AppendableGlyph glyph) {
|
|
||||||
return append(PositionType.ABSOLUTE, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
default @NotNull GlyphComponentBuilder append(int position, @NotNull List<? extends @NotNull AppendableGlyph> glyphList) {
|
|
||||||
return append(PositionType.ABSOLUTE, position, glyphList);
|
|
||||||
}
|
|
||||||
|
|
||||||
default @NotNull GlyphComponentBuilder append(@NotNull List<? extends @NotNull AppendableGlyph> glyphList) {
|
|
||||||
return append(PositionType.ABSOLUTE, glyphList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull Component build(boolean keepInitialPosition);
|
|
||||||
|
|
||||||
default @NotNull Component build() {
|
|
||||||
return build(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PositionType {
|
|
||||||
ABSOLUTE,
|
|
||||||
RELATIVE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph;
|
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.SpacesGlyphResourceProducer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
|
||||||
public class GlyphComponentBuilderImpl implements GlyphComponentBuilder {
|
|
||||||
|
|
||||||
private final SpacesGlyphResourceProducer spacesProducer;
|
|
||||||
private final int initialPosition;
|
|
||||||
private final Component baseComponent;
|
|
||||||
|
|
||||||
private final List<Glyph> glyphs = new ArrayList<>();
|
|
||||||
|
|
||||||
private int previousElementsWidth;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull GlyphComponentBuilder append(PositionType positionType, int position, @NotNull AppendableGlyph glyph) {
|
|
||||||
if (positionType == PositionType.ABSOLUTE && previousElementsWidth != 0) {
|
|
||||||
glyphs.add(spacesProducer.translate((-1) * previousElementsWidth));
|
|
||||||
previousElementsWidth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position != 0) {
|
|
||||||
glyphs.add(spacesProducer.translate(position));
|
|
||||||
}
|
|
||||||
|
|
||||||
glyphs.add(glyph);
|
|
||||||
this.previousElementsWidth += position + glyph.width();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull GlyphComponentBuilder append(PositionType positionType, int position, @NotNull List<? extends @NotNull AppendableGlyph> glyphList) {
|
|
||||||
if (positionType == PositionType.ABSOLUTE && previousElementsWidth != 0) {
|
|
||||||
glyphs.add(spacesProducer.translate((-1) * previousElementsWidth));
|
|
||||||
previousElementsWidth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position != 0) {
|
|
||||||
glyphs.add(spacesProducer.translate(position));
|
|
||||||
}
|
|
||||||
|
|
||||||
int width = 0;
|
|
||||||
for (AppendableGlyph glyph : glyphList) {
|
|
||||||
glyphs.add(glyph);
|
|
||||||
width += glyph.width();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.previousElementsWidth += position + width;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Component build(boolean keepInitialPosition) {
|
|
||||||
if (keepInitialPosition) {
|
|
||||||
previousElementsWidth += initialPosition;
|
|
||||||
|
|
||||||
// Component should have zero width finally
|
|
||||||
if (previousElementsWidth != 0) {
|
|
||||||
glyphs.add(spacesProducer.translate((-1) * previousElementsWidth));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var component = baseComponent;
|
|
||||||
|
|
||||||
if (initialPosition != 0) {
|
|
||||||
component = component.append(spacesProducer.translate(initialPosition).toAdventure());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Glyph glyph : glyphs) {
|
|
||||||
component = component.append(glyph.toAdventure());
|
|
||||||
}
|
|
||||||
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.exception;
|
|
||||||
|
|
||||||
public class ResourceAlreadyProducedException extends RuntimeException {}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.exception;
|
|
||||||
|
|
||||||
public class ResourceNotProducedException extends RuntimeException {}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.AppendableGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
public interface ImageGlyph extends AppendableGlyph, ResourceProducer {
|
|
||||||
|
|
||||||
static @NotNull ImageGlyph of(@NotNull Key key,
|
|
||||||
@NotNull Texture texture,
|
|
||||||
@NotNull TextureProperties properties) {
|
|
||||||
return new ImageGlyphImpl(key, texture, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
static @NotNull ImageGlyph of(@NotNull Texture texture,
|
|
||||||
@NotNull TextureProperties properties) {
|
|
||||||
return of(Glyph.DEFAULT_FONT_KEY, texture, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull Character character() throws ResourceNotProducedException;
|
|
||||||
|
|
||||||
@NotNull Texture texture();
|
|
||||||
|
|
||||||
default @NotNull Component toAdventure() throws ResourceNotProducedException {
|
|
||||||
return Component.text(character()).font(fontKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ArbitraryCharacterFactory;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceAlreadyProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.util.ImageUtil;
|
|
||||||
import team.unnamed.creative.font.FontProvider;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
|
||||||
public class ImageGlyphImpl implements ImageGlyph {
|
|
||||||
|
|
||||||
private final Key fontKey;
|
|
||||||
private final Texture texture;
|
|
||||||
private final TextureProperties properties;
|
|
||||||
|
|
||||||
private Character character;
|
|
||||||
private Set<FontProvider> fontProviders;
|
|
||||||
|
|
||||||
private int width = -1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Key fontKey() {
|
|
||||||
return fontKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean produced() {
|
|
||||||
return fontProviders != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void produceResources(ArbitraryCharacterFactory characterFactory) throws ResourceAlreadyProducedException {
|
|
||||||
if (fontProviders != null) {
|
|
||||||
throw new ResourceAlreadyProducedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
var fontProviderBuilder = FontProvider.bitMap();
|
|
||||||
|
|
||||||
this.character = characterFactory.nextCharacter();
|
|
||||||
|
|
||||||
fontProviderBuilder.characters(String.valueOf(character));
|
|
||||||
fontProviderBuilder.file(texture.key());
|
|
||||||
fontProviderBuilder.ascent(properties.ascent());
|
|
||||||
fontProviderBuilder.height(properties.height());
|
|
||||||
|
|
||||||
this.fontProviders = Collections.singleton(fontProviderBuilder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull FontProvider> fontProviders() throws ResourceNotProducedException {
|
|
||||||
if (fontProviders == null) {
|
|
||||||
throw new ResourceNotProducedException();
|
|
||||||
}
|
|
||||||
return fontProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull Texture> textures() throws ResourceNotProducedException {
|
|
||||||
return Collections.singleton(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int width() {
|
|
||||||
if (width == -1) {
|
|
||||||
try {
|
|
||||||
BufferedImage image = ImageIO.read(new ByteArrayInputStream(texture.data().toByteArray()));
|
|
||||||
int fileHeight = image.getHeight();
|
|
||||||
width = (int) Math.ceil(
|
|
||||||
((double) properties.height() / (double) fileHeight)
|
|
||||||
* ImageUtil.calculateWidth(image)) + Glyph.SEPARATOR_WIDTH;
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Character character() throws ResourceNotProducedException {
|
|
||||||
if (fontProviders == null) {
|
|
||||||
throw new ResourceNotProducedException();
|
|
||||||
}
|
|
||||||
return character;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Texture texture() {
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter;
|
|
||||||
|
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public interface ColorableGlyph {
|
|
||||||
|
|
||||||
@Nullable TextColor color();
|
|
||||||
|
|
||||||
void updateColor(@Nullable TextColor color);
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.AppendableGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface LanguageGlyphCollection extends ResourceProducer {
|
|
||||||
|
|
||||||
static @NotNull LanguageGlyphCollection of(@NotNull Key fontKey,
|
|
||||||
@NotNull Texture texture,
|
|
||||||
@NotNull List<@NotNull TextureProperties> propertiesList,
|
|
||||||
@NotNull List<@NotNull String> charactersMapping) {
|
|
||||||
return new LanguageGlyphCollectionImpl(fontKey, texture, propertiesList, charactersMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
static @NotNull LanguageGlyphCollection of(@NotNull Texture texture,
|
|
||||||
@NotNull List<@NotNull TextureProperties> propertiesList,
|
|
||||||
@NotNull List<@NotNull String> charactersMapping) {
|
|
||||||
return of(Glyph.DEFAULT_FONT_KEY, texture, propertiesList, charactersMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull AppendableGlyph translate(int height, int ascent, @NotNull Character character, @Nullable TextColor color) throws IllegalArgumentException;
|
|
||||||
|
|
||||||
@NotNull List<@NotNull AppendableGlyph> translate(int height, int ascent, @NotNull String text, @Nullable TextColor color) throws IllegalArgumentException;
|
|
||||||
|
|
||||||
@NotNull List<@NotNull AppendableGlyph> translate(int height, int ascent, @NotNull Component text) throws IllegalArgumentException;
|
|
||||||
|
|
||||||
default @NotNull AppendableGlyph translate(int height, int ascent, @NotNull Character character) throws IllegalArgumentException {
|
|
||||||
return translate(height, ascent, character, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
default @NotNull List<@NotNull AppendableGlyph> translate(int height, int ascent, @NotNull String text) throws IllegalArgumentException {
|
|
||||||
return translate(height, ascent, text, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ArbitraryCharacterFactory;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.AppendableGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceAlreadyProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.util.KyoriUtil;
|
|
||||||
import team.unnamed.creative.font.FontProvider;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class LanguageGlyphCollectionImpl implements LanguageGlyphCollection {
|
|
||||||
|
|
||||||
private final Key fontKey;
|
|
||||||
private final Texture texture;
|
|
||||||
|
|
||||||
private final Map<TextureProperties, MulticharacterImageGlyphCollection> propertiesToMulticharacterMap = new HashMap<>();
|
|
||||||
|
|
||||||
private Set<FontProvider> fontProviders;
|
|
||||||
|
|
||||||
LanguageGlyphCollectionImpl(
|
|
||||||
Key fontKey,
|
|
||||||
Texture texture,
|
|
||||||
List<TextureProperties> propertiesList,
|
|
||||||
List<String> charactersMapping
|
|
||||||
) {
|
|
||||||
this.fontKey = fontKey;
|
|
||||||
this.texture = texture;
|
|
||||||
|
|
||||||
for (TextureProperties properties : propertiesList) {
|
|
||||||
propertiesToMulticharacterMap.put(properties, MulticharacterImageGlyphCollection.of(fontKey, texture, properties, charactersMapping));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Key fontKey() {
|
|
||||||
return fontKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean produced() {
|
|
||||||
return fontProviders != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void produceResources(ArbitraryCharacterFactory characterFactory) throws ResourceAlreadyProducedException {
|
|
||||||
if (fontProviders != null) {
|
|
||||||
throw new ResourceAlreadyProducedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
fontProviders = new HashSet<>();
|
|
||||||
|
|
||||||
for (var entry : propertiesToMulticharacterMap.entrySet()) {
|
|
||||||
entry.getValue().produceResources(characterFactory);
|
|
||||||
fontProviders.addAll(entry.getValue().fontProviders());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull FontProvider> fontProviders() throws ResourceNotProducedException {
|
|
||||||
return fontProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull Texture> textures() throws ResourceNotProducedException {
|
|
||||||
return Collections.singleton(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull AppendableGlyph translate(int height, int ascent, @NotNull Character character, @Nullable TextColor color) throws IllegalArgumentException {
|
|
||||||
TextureProperties properties = new TextureProperties(height, ascent);
|
|
||||||
if (!propertiesToMulticharacterMap.containsKey(properties)) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
return propertiesToMulticharacterMap.get(properties).translate(character, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull List<@NotNull AppendableGlyph> translate(int height, int ascent, @NotNull String text, @Nullable TextColor color) throws IllegalArgumentException {
|
|
||||||
TextureProperties properties = new TextureProperties(height, ascent);
|
|
||||||
if (!propertiesToMulticharacterMap.containsKey(properties)) {
|
|
||||||
throw new IllegalArgumentException(properties.toString());
|
|
||||||
}
|
|
||||||
return propertiesToMulticharacterMap.get(properties).translate(text, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull List<@NotNull AppendableGlyph> translate(int height, int ascent, @NotNull Component component) throws IllegalArgumentException {
|
|
||||||
var property = new TextureProperties(height, ascent);
|
|
||||||
var glyphCollection = Objects.requireNonNull(propertiesToMulticharacterMap.get(property), property.toString());
|
|
||||||
|
|
||||||
var result = new ArrayList<AppendableGlyph>();
|
|
||||||
List<? extends KyoriUtil.ColoredPartsFlattenerListener.ColoredComponentTextPart> textAndColors = KyoriUtil.toColoredParts(component);
|
|
||||||
|
|
||||||
for (var parts: textAndColors) {
|
|
||||||
result.addAll(glyphCollection.translate(parts.text(), parts.color()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.AppendableGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.SpacesGlyph;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface MulticharacterImageGlyphCollection extends ResourceProducer {
|
|
||||||
|
|
||||||
static @NotNull MulticharacterImageGlyphCollection of(@NotNull Key fontKey,
|
|
||||||
@NotNull Texture texture,
|
|
||||||
@NotNull TextureProperties properties,
|
|
||||||
@NotNull List<@NotNull String> charactersMapping) {
|
|
||||||
return new MulticharacterImageGlyphCollectionImpl(fontKey, texture, properties, charactersMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
static @NotNull MulticharacterImageGlyphCollection of(@NotNull Texture texture,
|
|
||||||
@NotNull TextureProperties properties,
|
|
||||||
@NotNull List<@NotNull String> charactersMapping) {
|
|
||||||
return of(Glyph.DEFAULT_FONT_KEY, texture, properties, charactersMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull AppendableGlyph translate(@NotNull Character character, @Nullable TextColor color) throws IllegalArgumentException;
|
|
||||||
|
|
||||||
default @NotNull List<@NotNull AppendableGlyph> translate(@NotNull String text, @Nullable TextColor color) throws IllegalArgumentException {
|
|
||||||
List<AppendableGlyph> glyphs = new ArrayList<>();
|
|
||||||
for (char character : text.toCharArray()) {
|
|
||||||
if (character == ' ') {
|
|
||||||
glyphs.add(SpacesGlyph.DEFAULT_SPACE_GLYPH);
|
|
||||||
} else {
|
|
||||||
glyphs.add(translate(character, color));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return glyphs;
|
|
||||||
}
|
|
||||||
|
|
||||||
default @NotNull AppendableGlyph translate(@NotNull Character character) throws IllegalArgumentException {
|
|
||||||
return translate(character, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
default @NotNull List<@NotNull AppendableGlyph> translate(@NotNull String text) throws IllegalArgumentException {
|
|
||||||
return translate(text, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ArbitraryCharacterFactory;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceAlreadyProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.util.ImageUtil;
|
|
||||||
import team.unnamed.creative.font.FontProvider;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
|
||||||
public class MulticharacterImageGlyphCollectionImpl implements MulticharacterImageGlyphCollection {
|
|
||||||
|
|
||||||
private final Key fontKey;
|
|
||||||
private final Texture texture;
|
|
||||||
private final TextureProperties properties;
|
|
||||||
private final List<String> charactersMapping;
|
|
||||||
|
|
||||||
private final Map<Character, Character> originToArbitraryCharacterMap = new HashMap<>();
|
|
||||||
|
|
||||||
private Set<FontProvider> fontProviders;
|
|
||||||
|
|
||||||
private BufferedImage image;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Key fontKey() {
|
|
||||||
return fontKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean produced() {
|
|
||||||
return fontProviders != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void produceResources(ArbitraryCharacterFactory characterFactory) throws ResourceAlreadyProducedException {
|
|
||||||
if (fontProviders != null) {
|
|
||||||
throw new ResourceAlreadyProducedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
var fontProviderBuilder = FontProvider.bitMap();
|
|
||||||
fontProviderBuilder.file(texture.key());
|
|
||||||
fontProviderBuilder.ascent(properties.ascent());
|
|
||||||
fontProviderBuilder.height(properties.height());
|
|
||||||
|
|
||||||
List<String> mappingLines = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String mappingLine : charactersMapping) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
for (char character : mappingLine.toCharArray()) {
|
|
||||||
char arbitraryCharacter = characterFactory.nextCharacter();
|
|
||||||
originToArbitraryCharacterMap.put(character, arbitraryCharacter);
|
|
||||||
builder.append(arbitraryCharacter);
|
|
||||||
}
|
|
||||||
mappingLines.add(builder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
fontProviderBuilder.characters(mappingLines);
|
|
||||||
|
|
||||||
this.fontProviders = Collections.singleton(fontProviderBuilder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull FontProvider> fontProviders() throws ResourceNotProducedException {
|
|
||||||
return fontProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull Texture> textures() throws ResourceNotProducedException {
|
|
||||||
return Collections.singleton(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull PreparedImageGlyph translate(@NotNull Character character, @Nullable TextColor color) throws IllegalArgumentException {
|
|
||||||
if (!originToArbitraryCharacterMap.containsKey(character)) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
int width = 0;
|
|
||||||
for (int lineIndex = 0; lineIndex < charactersMapping.size(); lineIndex++) {
|
|
||||||
String line = charactersMapping.get(lineIndex);
|
|
||||||
for (int characterIndex = 0; characterIndex < line.toCharArray().length; characterIndex++) {
|
|
||||||
if (line.charAt(characterIndex) == character) {
|
|
||||||
if (image == null) {
|
|
||||||
cacheImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image == null) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
int filePartWidth = image.getWidth() / charactersMapping.get(0).length();
|
|
||||||
int filePartHeight = image.getHeight() / charactersMapping.size();
|
|
||||||
|
|
||||||
width = (int) Math.ceil(
|
|
||||||
((double) properties.height() / (double) filePartHeight)
|
|
||||||
* ImageUtil.calculateWidth(
|
|
||||||
image, filePartWidth * characterIndex, filePartHeight * lineIndex,
|
|
||||||
filePartWidth * (characterIndex + 1), filePartHeight * (lineIndex + 1)
|
|
||||||
)) + Glyph.SEPARATOR_WIDTH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PreparedImageGlyph(fontKey, originToArbitraryCharacterMap.get(character), width, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cacheImage() {
|
|
||||||
try {
|
|
||||||
image = ImageIO.read(new ByteArrayInputStream(texture.data().toByteArray()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.AppendableGlyph;
|
|
||||||
|
|
||||||
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
|
||||||
public class PreparedImageGlyph implements AppendableGlyph, ColorableGlyph {
|
|
||||||
|
|
||||||
private final Key key;
|
|
||||||
private final Character character;
|
|
||||||
private final int width;
|
|
||||||
private @Nullable TextColor color;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Component toAdventure() {
|
|
||||||
return Component.text(character)
|
|
||||||
.font(key)
|
|
||||||
.color(color == null ? NamedTextColor.BLACK : color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int width() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable TextColor color() {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateColor(@Nullable TextColor color) {
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.space;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.EmptyGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.util.ArrayUtil;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public abstract class AbstractSpacesGlyphResourceProducer implements SpacesGlyphResourceProducer {
|
|
||||||
|
|
||||||
private final Key fontKey;
|
|
||||||
|
|
||||||
protected Map<Integer, Character> mapping;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Key fontKey() {
|
|
||||||
return fontKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean produced() {
|
|
||||||
return mapping != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Glyph translate(int length) throws ResourceNotProducedException {
|
|
||||||
if (mapping == null) {
|
|
||||||
throw new ResourceNotProducedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length == 0) {
|
|
||||||
return EmptyGlyph.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sign = length > 0 ? 1 : -1;
|
|
||||||
String binaryString = Integer.toBinaryString(Math.abs(length));
|
|
||||||
|
|
||||||
List<Character> characters = new ArrayList<>();
|
|
||||||
|
|
||||||
int currentRankLength = 1;
|
|
||||||
for (int index = 0; index < binaryString.length(); index++) {
|
|
||||||
char digit = binaryString.charAt(binaryString.length() - index - 1);
|
|
||||||
if (digit == '1') {
|
|
||||||
int partLength = currentRankLength * sign;
|
|
||||||
if (!mapping.containsKey(partLength)) {
|
|
||||||
throw new IllegalArgumentException("Too much length");
|
|
||||||
}
|
|
||||||
characters.add(mapping.get(partLength));
|
|
||||||
}
|
|
||||||
currentRankLength *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SpacesGlyph(fontKey(), ArrayUtil.toCharArray(characters), length);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.space;
|
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.AppendableGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import team.unnamed.creative.font.Font;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
|
||||||
public class DefaultSpaceGlyph implements AppendableGlyph {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Component toAdventure() throws ResourceNotProducedException {
|
|
||||||
return Component.text(" ").font(Font.MINECRAFT_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int width() {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.space;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ArbitraryCharacterFactory;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceAlreadyProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import team.unnamed.creative.base.Writable;
|
|
||||||
import team.unnamed.creative.font.BitMapFontProvider;
|
|
||||||
import team.unnamed.creative.font.FontProvider;
|
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class DefaultSpacesGlyphResourceProducer extends AbstractSpacesGlyphResourceProducer {
|
|
||||||
|
|
||||||
private final Key textureKey;
|
|
||||||
private final Writable writable;
|
|
||||||
|
|
||||||
private Set<Texture> textures;
|
|
||||||
private Set<FontProvider> fontProviders;
|
|
||||||
|
|
||||||
public DefaultSpacesGlyphResourceProducer(Key fontKey, Key textureKey, Writable writable) {
|
|
||||||
super(fontKey);
|
|
||||||
this.textureKey = textureKey;
|
|
||||||
this.writable = writable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean produced() {
|
|
||||||
return textures != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void produceResources(ArbitraryCharacterFactory characterFactory) {
|
|
||||||
if (textures != null) {
|
|
||||||
throw new ResourceAlreadyProducedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mapping = new HashMap<>();
|
|
||||||
|
|
||||||
Set<FontProvider> fontProviders = new HashSet<>();
|
|
||||||
|
|
||||||
for (int length = 1; length <= 2048; length *= 2) {
|
|
||||||
fontProviders.add(prepareBuilder(characterFactory, length).build());
|
|
||||||
fontProviders.add(prepareBuilder(characterFactory, length * (-1)).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
this.textures = Collections.singleton(Texture.texture(textureKey, writable));
|
|
||||||
this.fontProviders = fontProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull FontProvider> fontProviders() throws ResourceNotProducedException {
|
|
||||||
if (fontProviders == null) {
|
|
||||||
throw new ResourceNotProducedException();
|
|
||||||
}
|
|
||||||
return fontProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull Texture> textures() throws ResourceNotProducedException {
|
|
||||||
if (textures == null) {
|
|
||||||
throw new ResourceNotProducedException();
|
|
||||||
}
|
|
||||||
return textures;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private BitMapFontProvider.Builder prepareBuilder(ArbitraryCharacterFactory characterFactory, int length) {
|
|
||||||
var fontProviderBuilder = FontProvider.bitMap();
|
|
||||||
|
|
||||||
char character = characterFactory.nextCharacter();
|
|
||||||
|
|
||||||
fontProviderBuilder.characters(String.valueOf(character));
|
|
||||||
fontProviderBuilder.file(textureKey);
|
|
||||||
|
|
||||||
if (length > 0) {
|
|
||||||
fontProviderBuilder.height(length - 1);
|
|
||||||
fontProviderBuilder.ascent(0);
|
|
||||||
} else {
|
|
||||||
fontProviderBuilder.height(length - 2);
|
|
||||||
fontProviderBuilder.ascent(-32768);
|
|
||||||
}
|
|
||||||
|
|
||||||
mapping.put(length, character);
|
|
||||||
|
|
||||||
return fontProviderBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.space;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import team.unnamed.creative.base.Writable;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
|
||||||
public class SpacesGlyph implements Glyph {
|
|
||||||
|
|
||||||
private static final Key DEFAULT_SPACE_TEXTURE_KEY = Key.key(Glyph.DEFAULT_NAMESPACE, "space");
|
|
||||||
public static final @NotNull DefaultSpaceGlyph DEFAULT_SPACE_GLYPH = new DefaultSpaceGlyph();
|
|
||||||
private final Key key;
|
|
||||||
private final char[] characters;
|
|
||||||
private final int length;
|
|
||||||
|
|
||||||
public static @NotNull SpacesGlyphResourceProducer create(@NotNull Key fontKey,
|
|
||||||
@NotNull Key textureKey,
|
|
||||||
@NotNull Writable spacesWritable) {
|
|
||||||
return new DefaultSpacesGlyphResourceProducer(fontKey, textureKey, spacesWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SpacesGlyphResourceProducer create(@NotNull Writable spacesWritable) {
|
|
||||||
return create(Glyph.DEFAULT_SPACES_FONT_KEY, DEFAULT_SPACE_TEXTURE_KEY, spacesWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Component toAdventure() {
|
|
||||||
return Component.text(new String(characters)).font(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int width() {
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.space;
|
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
|
|
||||||
public interface SpacesGlyphResourceProducer extends ResourceProducer {
|
|
||||||
|
|
||||||
Glyph translate(int length) throws ResourceNotProducedException;
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.space.mojang;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.SpacesGlyphResourceProducer;
|
|
||||||
|
|
||||||
public interface MojangSpacesGlyph extends Glyph, ResourceProducer {
|
|
||||||
|
|
||||||
static @NotNull SpacesGlyphResourceProducer create(@NotNull Key key) {
|
|
||||||
return new MojangSpacesGlyphResourceProducer(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SpacesGlyphResourceProducer create() {
|
|
||||||
return create(Glyph.DEFAULT_SPACES_FONT_KEY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.space.mojang;
|
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ArbitraryCharacterFactory;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceAlreadyProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.exception.ResourceNotProducedException;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.AbstractSpacesGlyphResourceProducer;
|
|
||||||
import team.unnamed.creative.font.FontProvider;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class MojangSpacesGlyphResourceProducer extends AbstractSpacesGlyphResourceProducer {
|
|
||||||
|
|
||||||
private Set<FontProvider> fontProviders;
|
|
||||||
|
|
||||||
public MojangSpacesGlyphResourceProducer(Key key) {
|
|
||||||
super(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean produced() {
|
|
||||||
return fontProviders != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void produceResources(ArbitraryCharacterFactory characterFactory) {
|
|
||||||
if (fontProviders != null) {
|
|
||||||
throw new ResourceAlreadyProducedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
mapping = new HashMap<>();
|
|
||||||
|
|
||||||
var fontProviderBuilder = FontProvider.space();
|
|
||||||
|
|
||||||
for (int length = 1; length <= 2048; length *= 2) {
|
|
||||||
fontProviderBuilder.advance(retrieveCharacter(characterFactory, length), length);
|
|
||||||
fontProviderBuilder.advance(retrieveCharacter(characterFactory, length * (-1)), length * (-1));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fontProviders = Collections.singleton(fontProviderBuilder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull FontProvider> fontProviders() throws ResourceNotProducedException {
|
|
||||||
if (fontProviders == null) {
|
|
||||||
throw new ResourceNotProducedException();
|
|
||||||
}
|
|
||||||
return fontProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Character retrieveCharacter(ArbitraryCharacterFactory characterFactory, int length) {
|
|
||||||
char character = characterFactory.nextCharacter();
|
|
||||||
mapping.put(length, character);
|
|
||||||
return character;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.pack;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.GlyphCompiler;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import team.unnamed.creative.part.ResourcePackPart;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
|
||||||
public class DefaultGlyphResourcePack implements GlyphResourcePack {
|
|
||||||
|
|
||||||
private final Map<String, ResourceProducer> raw = new HashMap<>();
|
|
||||||
private final Map<String, ResourceProducer> compiled = new HashMap<>();
|
|
||||||
|
|
||||||
private final Set<ResourcePackPart> resources = new HashSet<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<@NotNull ResourcePackPart> all() {
|
|
||||||
if (!raw.isEmpty()) {
|
|
||||||
compileAll();
|
|
||||||
}
|
|
||||||
return resources;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void compileAll() {
|
|
||||||
var resources = GlyphCompiler.instance().compile(raw.values());
|
|
||||||
this.resources.addAll(resources);
|
|
||||||
compiled.putAll(raw);
|
|
||||||
raw.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull <T extends ResourceProducer> GlyphResourcePack with(@NotNull ResourceIdentifier<@NotNull T> id, @NotNull T producer) {
|
|
||||||
if (raw.containsKey(id.key()) || compiled.containsKey(id.key())) {
|
|
||||||
throw new IllegalArgumentException("Producer with this identifier already registered");
|
|
||||||
}
|
|
||||||
raw.put(id.key(), producer);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull GlyphResourcePack with(@NotNull ResourcePackPart resource) {
|
|
||||||
resources.add(resource);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends ResourceProducer> @NotNull T get(@NotNull ResourceIdentifier<@NotNull T> id) throws IllegalArgumentException {
|
|
||||||
if (!compiled.containsKey(id.key())) {
|
|
||||||
throw new IllegalArgumentException("Producer with that identifier is not compiled. Provided key: " + id.key());
|
|
||||||
}
|
|
||||||
ResourceProducer producer = compiled.get(id.key());
|
|
||||||
if (!id.getType().isAssignableFrom(producer.getClass())) {
|
|
||||||
throw new IllegalArgumentException("Wrong producer type");
|
|
||||||
}
|
|
||||||
return (T) producer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.pack;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Contract;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.SpacesGlyphResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.mojang.MojangSpacesGlyph;
|
|
||||||
import team.unnamed.creative.ResourcePack;
|
|
||||||
import team.unnamed.creative.part.ResourcePackPart;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public interface GlyphResourcePack {
|
|
||||||
|
|
||||||
@NotNull Collection<@NotNull ResourcePackPart> all();
|
|
||||||
|
|
||||||
void compileAll();
|
|
||||||
|
|
||||||
@Contract("_, _ -> this")
|
|
||||||
<T extends ResourceProducer> @NotNull GlyphResourcePack with(@NotNull ResourceIdentifier<@NotNull T> id, @NotNull T producer);
|
|
||||||
|
|
||||||
@Contract("_ -> this")
|
|
||||||
@NotNull GlyphResourcePack with(@NotNull ResourcePackPart resource);
|
|
||||||
|
|
||||||
@Contract("_ -> this")
|
|
||||||
default @NotNull GlyphResourcePack with(@NotNull ResourcePackPart... resources) {
|
|
||||||
for (ResourcePackPart resource : resources) {
|
|
||||||
with(resource);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("_ -> this")
|
|
||||||
default @NotNull GlyphResourcePack with(@NotNull Collection<@NotNull ResourcePackPart> resources) {
|
|
||||||
resources.forEach(this::with);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("-> this")
|
|
||||||
default @NotNull GlyphResourcePack withMojangSpaces() {
|
|
||||||
with(ResourceIdentifier.SPACES, MojangSpacesGlyph.create());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
<T extends ResourceProducer> @NotNull T get(@NotNull ResourceIdentifier<@NotNull T> id) throws IllegalArgumentException;
|
|
||||||
|
|
||||||
default @NotNull SpacesGlyphResourceProducer spaces() {
|
|
||||||
return get(ResourceIdentifier.SPACES);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void writeAll(@NotNull ResourcePack resourcePack) {
|
|
||||||
all().forEach(resourcePack::part);
|
|
||||||
}
|
|
||||||
|
|
||||||
static @NotNull GlyphResourcePack create() {
|
|
||||||
return new DefaultGlyphResourcePack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.pack;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
|
||||||
|
|
||||||
public interface ImageResourceIdentifier extends ResourceIdentifier<@NotNull ImageGlyph> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default @NotNull Class<@NotNull ImageGlyph> getType() {
|
|
||||||
return ImageGlyph.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.pack;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter.LanguageGlyphCollection;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.space.SpacesGlyphResourceProducer;
|
|
||||||
|
|
||||||
public interface ResourceIdentifier<T extends @NotNull ResourceProducer> {
|
|
||||||
|
|
||||||
@NotNull StringIdentifier<@NotNull SpacesGlyphResourceProducer> SPACES = StringIdentifier.of("spaces", SpacesGlyphResourceProducer.class);
|
|
||||||
|
|
||||||
@NotNull StringIdentifier<@NotNull LanguageGlyphCollection> MINECRAFT_FONT = StringIdentifier.of("minecraft_font", LanguageGlyphCollection.class);
|
|
||||||
|
|
||||||
String STRING_IDENTIFIER_NAMESPACE = "glyphs";
|
|
||||||
|
|
||||||
@NotNull String key();
|
|
||||||
|
|
||||||
@NotNull Class<T> getType();
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.pack;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.ResourceProducer;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
|
||||||
|
|
||||||
public class StringIdentifier<T extends @NotNull ResourceProducer> implements ResourceIdentifier<T> {
|
|
||||||
|
|
||||||
private final @NotNull String id;
|
|
||||||
|
|
||||||
private final @NotNull Class<T> type;
|
|
||||||
|
|
||||||
protected StringIdentifier(@NotNull String id, @NotNull Class<T> type) {
|
|
||||||
this.id = id;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Class<T> getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String key() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends @NotNull ResourceProducer> @NotNull StringIdentifier<@NotNull T> of(
|
|
||||||
@NotNull String id,
|
|
||||||
@NotNull Class<T> type) {
|
|
||||||
return new StringIdentifier<>(id, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NotNull StringIdentifier<@NotNull ImageGlyph> image(@NotNull String id) {
|
|
||||||
return new StringIdentifier<>(id, ImageGlyph.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.util;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class ArrayUtil {
|
|
||||||
|
|
||||||
public char[] toCharArray(@NotNull List<Character> list) {
|
|
||||||
char[] arr = new char[list.size()];
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
|
||||||
arr[i] = list.get(i);
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.util;
|
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class ImageUtil {
|
|
||||||
|
|
||||||
public int calculateWidth(BufferedImage image, int xFrom, int yFrom, int xTo, int yTo) {
|
|
||||||
int width;
|
|
||||||
for (width = xTo - 1; width > xFrom; width--) {
|
|
||||||
for (int height = yFrom; height < yTo; height++) {
|
|
||||||
if (new Color(image.getRGB(width, height), true)
|
|
||||||
.getAlpha() == 255) {
|
|
||||||
return width - xFrom + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return width - xFrom + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int calculateWidth(BufferedImage image) {
|
|
||||||
return calculateWidth(image, 0, 0, image.getWidth(), image.getHeight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.util;
|
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.flattener.ComponentFlattener;
|
|
||||||
import net.kyori.adventure.text.flattener.FlattenerListener;
|
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
|
||||||
import net.kyori.adventure.text.format.Style;
|
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class KyoriUtil {
|
|
||||||
|
|
||||||
public @NotNull List<? extends ColoredPartsFlattenerListener.ColoredComponentTextPart> toColoredParts(@NotNull Component component) {
|
|
||||||
var listener = new ColoredPartsFlattenerListener();
|
|
||||||
ComponentFlattener.basic().flatten(component, listener);
|
|
||||||
return listener.result();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ColoredPartsFlattenerListener implements FlattenerListener {
|
|
||||||
|
|
||||||
private final Deque<TextColor> colors = new LinkedList<>();
|
|
||||||
private final List<ColoredComponentTextPart> result = new ArrayList<>();
|
|
||||||
|
|
||||||
public void pushStyle(@NotNull Style style) {
|
|
||||||
var color = style.color();
|
|
||||||
if (color != null) colors.add(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void component(@NotNull String text) {
|
|
||||||
result.add(new ColoredComponentTextPart(text, current()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void popStyle(@NotNull Style style) {
|
|
||||||
var color = style.color();
|
|
||||||
if (color != null) colors.removeLast();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private TextColor current() {
|
|
||||||
var color = colors.peekLast();
|
|
||||||
return color != null ? color : NamedTextColor.WHITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull List<? extends @NotNull ColoredComponentTextPart> result() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public record ColoredComponentTextPart(String text, TextColor color) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,8 +3,7 @@ package ru.dragonestia.msb3.api.item;
|
|||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
import ru.dragonestia.msb3.api.boot.ServerBootstrap;
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
||||||
import team.unnamed.creative.base.Writable;
|
import team.unnamed.creative.base.Writable;
|
||||||
import team.unnamed.creative.model.*;
|
import team.unnamed.creative.model.*;
|
||||||
@ -32,7 +31,7 @@ public class BlankSlotItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Collection<ResourcePackPart> compile() {
|
public static Collection<ResourcePackPart> compile() {
|
||||||
var modelKey = Key.key(Glyph.DEFAULT_NAMESPACE, "blank_slot");
|
var modelKey = Key.key("msb3", "blank_slot");
|
||||||
var itemKey = Key.key("item/paper");
|
var itemKey = Key.key("item/paper");
|
||||||
|
|
||||||
Model blankSlotModel = Model.model()
|
Model blankSlotModel = Model.model()
|
||||||
@ -52,7 +51,7 @@ public class BlankSlotItem {
|
|||||||
.overrides(ItemOverride.of(modelKey, ItemPredicate.customModelData(1)))
|
.overrides(ItemOverride.of(modelKey, ItemPredicate.customModelData(1)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Texture texture = Texture.texture(Key.key(Glyph.DEFAULT_NAMESPACE, "blank_slot.png"), BLANK_SLOT_IMAGE_WRITABLE);
|
Texture texture = Texture.texture(Key.key("msb3", "blank_slot.png"), BLANK_SLOT_IMAGE_WRITABLE);
|
||||||
return Arrays.asList(blankSlotModel, paperItemModel, texture);
|
return Arrays.asList(blankSlotModel, paperItemModel, texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
package ru.dragonestia.msb3.api.item;
|
package ru.dragonestia.msb3.api.item;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
import ru.dragonestia.msb3.api.boot.ServerBootstrap;
|
||||||
import ru.dragonestia.msb3.api.item.prefab.ItemPrefab;
|
import ru.dragonestia.msb3.api.item.prefab.ItemPrefab;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -9,12 +10,11 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
|
@UtilityClass
|
||||||
public final class ItemPrefabManager {
|
public final class ItemPrefabManager {
|
||||||
|
|
||||||
private final Map<String, ItemPrefab> prefabs = new HashMap<>();
|
private final Map<String, ItemPrefab> prefabs = new HashMap<>();
|
||||||
|
|
||||||
public ItemPrefabManager() {}
|
|
||||||
|
|
||||||
public synchronized void register(ItemPrefab prefab) {
|
public synchronized void register(ItemPrefab prefab) {
|
||||||
if (ServerBootstrap.isStarted()) {
|
if (ServerBootstrap.isStarted()) {
|
||||||
throw new IllegalStateException("Server is already started");
|
throw new IllegalStateException("Server is already started");
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package ru.dragonestia.msb3.api.item.prefab;
|
|||||||
import net.kyori.adventure.nbt.BinaryTag;
|
import net.kyori.adventure.nbt.BinaryTag;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
import ru.dragonestia.msb3.api.item.ItemPrefabManager;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@ -22,12 +22,12 @@ public class ItemPrefab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<ItemPrefab> of(String identifier) {
|
public static Optional<ItemPrefab> of(String identifier) {
|
||||||
return ServerBootstrap.getInstance().getItemPrefabManager().getPrefab(identifier);
|
return ItemPrefabManager.getPrefab(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<ItemPrefab> of(ItemStack item) {
|
public static Optional<ItemPrefab> of(ItemStack item) {
|
||||||
if (item == null || item.hasTag(TAG_IDENTIFIER)) return Optional.empty();
|
if (item == null || item.hasTag(TAG_IDENTIFIER)) return Optional.empty();
|
||||||
return ServerBootstrap.getInstance().getItemPrefabManager().getPrefab(item.getTag(TAG_IDENTIFIER));
|
return ItemPrefabManager.getPrefab(item.getTag(TAG_IDENTIFIER));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getIdentifier() {
|
public final String getIdentifier() {
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
package ru.dragonestia.msb3.api.module;
|
package ru.dragonestia.msb3.api.module;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
import net.kyori.adventure.resource.ResourcePackCallback;
|
import net.kyori.adventure.resource.ResourcePackCallback;
|
||||||
import net.kyori.adventure.resource.ResourcePackInfo;
|
import net.kyori.adventure.resource.ResourcePackInfo;
|
||||||
import net.kyori.adventure.resource.ResourcePackRequest;
|
import net.kyori.adventure.resource.ResourcePackRequest;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.event.player.PlayerSpawnEvent;
|
import net.minestom.server.event.player.PlayerSpawnEvent;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
|
||||||
import team.unnamed.creative.BuiltResourcePack;
|
import team.unnamed.creative.BuiltResourcePack;
|
||||||
import team.unnamed.creative.base.Writable;
|
import team.unnamed.creative.base.Writable;
|
||||||
import team.unnamed.creative.server.ResourcePackServer;
|
import team.unnamed.creative.server.ResourcePackServer;
|
||||||
@ -22,19 +22,16 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class ResourcePackRepositoryModule {
|
public class ResourcePackRepositoryModule {
|
||||||
|
|
||||||
private static boolean used = false;
|
private boolean used = false;
|
||||||
|
|
||||||
private ResourcePackRepositoryModule() {}
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static synchronized void init(ServerBootstrap bootstrap, String address, int port) {
|
public synchronized void init(String address, int port) {
|
||||||
if (used) return;
|
if (used) return;
|
||||||
used = true;
|
used = true;
|
||||||
|
|
||||||
bootstrap.getResourcePackManager().compile();
|
|
||||||
|
|
||||||
var file = new File("./resource-pack.zip");
|
var file = new File("./resource-pack.zip");
|
||||||
var hash = calculateHash(file);
|
var hash = calculateHash(file);
|
||||||
var uuid = UUID.randomUUID();
|
var uuid = UUID.randomUUID();
|
||||||
@ -59,7 +56,7 @@ public class ResourcePackRepositoryModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private static String calculateHash(File file) {
|
private String calculateHash(File file) {
|
||||||
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||||
|
|
||||||
try (InputStream fis = new FileInputStream(file)) {
|
try (InputStream fis = new FileInputStream(file)) {
|
||||||
@ -68,7 +65,7 @@ public class ResourcePackRepositoryModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String byteArray2Hex(final byte[] hash) {
|
private String byteArray2Hex(final byte[] hash) {
|
||||||
Formatter formatter = new Formatter();
|
Formatter formatter = new Formatter();
|
||||||
for (byte b: hash) formatter.format("%02x", b);
|
for (byte b: hash) formatter.format("%02x", b);
|
||||||
return formatter.toString();
|
return formatter.toString();
|
||||||
|
|||||||
@ -1,21 +1,12 @@
|
|||||||
package ru.dragonestia.msb3.api.resource;
|
package ru.dragonestia.msb3.api.resource;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import ru.dragonestia.msb3.api.glyph.font.GlyphFont;
|
import ru.dragonestia.msb3.api.resource.dialog.*;
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
import ru.dragonestia.msb3.resource.Resources;
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter.LanguageGlyphCollection;
|
import ru.dragonestia.msb3.resource.utils.ImageUtils;
|
||||||
import ru.dragonestia.msb3.api.glyph.pack.GlyphResourcePack;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.pack.StringIdentifier;
|
|
||||||
import ru.dragonestia.msb3.api.resource.dialog.Background;
|
|
||||||
import ru.dragonestia.msb3.api.resource.dialog.Button;
|
|
||||||
import ru.dragonestia.msb3.api.resource.dialog.Substrate;
|
|
||||||
import ru.dragonestia.msb3.api.resource.dialog.TextField;
|
|
||||||
import ru.dragonestia.msb3.api.talk.dialogue.DialogGlyphPositions;
|
|
||||||
import ru.dragonestia.msb3.api.util.ImageUtil;
|
|
||||||
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
|
||||||
import team.unnamed.creative.base.Writable;
|
import team.unnamed.creative.base.Writable;
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
@ -24,95 +15,59 @@ import java.io.IOException;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.IntStream;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class DialogueResources {
|
public class DialogueResources {
|
||||||
|
|
||||||
private static final Key DIALOGUE_FONT_KEY = Key.key("msb3", "dialog");
|
|
||||||
public static final String DEFAULT = "default";
|
public static final String DEFAULT = "default";
|
||||||
|
|
||||||
private final GlyphResourcePack glyphResourcePack;
|
private final Map<String, GlyphImage> avatars = new HashMap<>();
|
||||||
private final Map<String, GlyphEntry> avatars = new HashMap<>();
|
private final Map<String, GlyphImage> avatarFrames = new HashMap<>();
|
||||||
private final Map<String, GlyphEntry> avatarFrames = new HashMap<>();
|
private final Map<String, GlyphImage> scrollUp = new HashMap<>();
|
||||||
private final Map<String, GlyphEntry> scrollUp = new HashMap<>();
|
private final Map<String, GlyphImage> scrollDown = new HashMap<>();
|
||||||
private final Map<String, GlyphEntry> scrollDown = new HashMap<>();
|
|
||||||
private final Map<String, Background> backgrounds = new HashMap<>();
|
private final Map<String, Background> backgrounds = new HashMap<>();
|
||||||
private final Map<String, Substrate> substrates = new HashMap<>();
|
private final Map<String, Substrate> substrates = new HashMap<>();
|
||||||
private final Map<String, FontGlyphEntry> fonts = new HashMap<>();
|
|
||||||
private final Map<String, Button> buttons = new HashMap<>();
|
private final Map<String, Button> buttons = new HashMap<>();
|
||||||
private final Map<String, TextField> activeFields = new HashMap<>();
|
private final Map<String, TextField> activeFields = new HashMap<>();
|
||||||
private final Map<String, TextField> notActiveFields = new HashMap<>();
|
private final Map<String, TextField> notActiveFields = new HashMap<>();
|
||||||
|
|
||||||
public DialogueResources(GlyphResourcePack glyphResourcePack) {
|
|
||||||
this.glyphResourcePack = glyphResourcePack;
|
|
||||||
|
|
||||||
registerAvatar(DEFAULT, ResourceFromJar.of("glyphs/dialogue/default_avatar.png"));
|
|
||||||
registerAvatarFrame(DEFAULT, ResourceFromJar.of("glyphs/dialogue/avatar_frame.png"));
|
|
||||||
registerScrollTextUp(DEFAULT, ResourceFromJar.of("glyphs/dialogue/scroll_phrase_up_button.png"));
|
|
||||||
registerScrollTextDown(DEFAULT, ResourceFromJar.of("glyphs/dialogue/scroll_phrase_down_button.png"));
|
|
||||||
registerBackground(DEFAULT, ResourceFromJar.of("glyphs/dialogue/background.png"));
|
|
||||||
registerSubstrate(DEFAULT, ResourceFromJar.of("glyphs/dialogue/phrase_substrate.png"));
|
|
||||||
registerActiveTextField(DEFAULT, ResourceFromJar.of("glyphs/dialogue/answer_active_text_field.png"));
|
|
||||||
registerNotActiveTextField(DEFAULT, ResourceFromJar.of("glyphs/dialogue/answer_not_active_text_field.png"));
|
|
||||||
registerButton(DEFAULT + 1, ResourceFromJar.of("glyphs/dialogue/answer_button_active_1.png"));
|
|
||||||
registerButton(DEFAULT + 2, ResourceFromJar.of("glyphs/dialogue/answer_button_active_2.png"));
|
|
||||||
registerButton(DEFAULT + 3, ResourceFromJar.of("glyphs/dialogue/answer_button_active_3.png"));
|
|
||||||
registerButton(DEFAULT + 4, ResourceFromJar.of("glyphs/dialogue/answer_button_active_4.png"));
|
|
||||||
registerFont(DEFAULT, ResourceFromJar.of("glyphs/defaults/minecraft_font.png"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void compile(GlyphResourcePack resourcePack) {}
|
|
||||||
|
|
||||||
public void registerAvatar(String identifier, Writable writable) {
|
public void registerAvatar(String identifier, Writable writable) {
|
||||||
registerAvatar(identifier, writable, DialogGlyphPositions.DEFAULT);
|
avatars.put(identifier, Resources.createGlyph(
|
||||||
}
|
Key.key("msb3", "dialogue/avatar/" + identifier),
|
||||||
|
writable,
|
||||||
public void registerAvatar(String identifier, Writable writable, DialogGlyphPositions positions) {
|
GlyphPositions.avatar.height(),
|
||||||
var glyph = createGlyph(identifier, writable, "avatar", positions.avatar().height(), positions.avatar().y());
|
GlyphPositions.avatar.y()
|
||||||
var glyphIdentifier = StringIdentifier.image("dialog_avatar__" + identifier);
|
));
|
||||||
avatars.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
|
||||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerAvatarFrame(String identifier, Writable writable) {
|
public void registerAvatarFrame(String identifier, Writable writable) {
|
||||||
registerAvatarFrame(identifier, writable, DialogGlyphPositions.DEFAULT);
|
avatarFrames.put(identifier, Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/avatar_frame/" + identifier),
|
||||||
|
writable,
|
||||||
|
GlyphPositions.avatar.frameHeight(),
|
||||||
|
GlyphPositions.avatar.y() + GlyphPositions.avatar.frameBorderSize()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerAvatarFrame(String identifier, Writable writable, DialogGlyphPositions positions) {
|
public void registerScrollUp(String identifier, Writable writable) {
|
||||||
var glyph = createGlyph(identifier, writable, "avatar_frame", positions.avatar().frameHeight(), positions.avatar().y() + positions.avatar().frameBorderSize());
|
scrollUp.put(identifier, Resources.createGlyph(
|
||||||
var glyphIdentifier = StringIdentifier.image("dialog_avatar_frame__" + identifier);
|
Key.key("msb3", "dialogue/scroll_up/" + identifier),
|
||||||
avatarFrames.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
writable,
|
||||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
GlyphPositions.scrollPhraseButton.height(),
|
||||||
|
GlyphPositions.scrollPhraseButton.buttonY()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerScrollTextUp(String identifier, Writable writable) {
|
public void registerScrollDown(String identifier, Writable writable) {
|
||||||
registerScrollTextUp(identifier, writable, DialogGlyphPositions.DEFAULT);
|
scrollDown.put(identifier, Resources.createGlyph(
|
||||||
}
|
Key.key("msb3", "dialogue/scroll_down/" + identifier),
|
||||||
|
writable,
|
||||||
public void registerScrollTextUp(String identifier, Writable writable, DialogGlyphPositions positions) {
|
GlyphPositions.scrollPhraseButton.height(),
|
||||||
var glyph = createGlyph(identifier, writable, "scroll_up", positions.scrollPhraseButton().height(), positions.scrollPhraseButton().buttonY());
|
GlyphPositions.scrollPhraseButton.buttonY()
|
||||||
var glyphIdentifier = StringIdentifier.image("dialog_scroll_up__" + identifier);
|
));
|
||||||
scrollUp.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
|
||||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerScrollTextDown(String identifier, Writable writable) {
|
|
||||||
registerScrollTextDown(identifier, writable, DialogGlyphPositions.DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerScrollTextDown(String identifier, Writable writable, DialogGlyphPositions positions) {
|
|
||||||
var glyph = createGlyph(identifier, writable, "scroll_down", positions.scrollPhraseButton().height(), positions.scrollPhraseButton().buttonY());
|
|
||||||
var glyphIdentifier = StringIdentifier.image("dialog_scroll_down__" + identifier);
|
|
||||||
scrollDown.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
|
||||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerBackground(String identifier, Writable writable) {
|
public void registerBackground(String identifier, Writable writable) {
|
||||||
registerBackground(identifier, writable, DialogGlyphPositions.DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerBackground(String identifier, Writable writable, DialogGlyphPositions positions) {
|
|
||||||
BufferedImage image;
|
BufferedImage image;
|
||||||
Writable part1;
|
Writable part1;
|
||||||
Writable part2;
|
Writable part2;
|
||||||
@ -124,43 +79,43 @@ public class DialogueResources {
|
|||||||
var w = image.getWidth();
|
var w = image.getWidth();
|
||||||
var h = image.getHeight();
|
var h = image.getHeight();
|
||||||
|
|
||||||
part1 = ImageUtil.imageToWritable(image.getSubimage(0, 0, w / 2, h / 2));
|
part1 = ImageUtils.imageToWritable(image.getSubimage(0, 0, w / 2, h / 2));
|
||||||
part2 = ImageUtil.imageToWritable(image.getSubimage(w / 2, 0, w / 2, h / 2));
|
part2 = ImageUtils.imageToWritable(image.getSubimage(w / 2, 0, w / 2, h / 2));
|
||||||
part3 = ImageUtil.imageToWritable(image.getSubimage(0, h / 2, w / 2, h / 2));
|
part3 = ImageUtils.imageToWritable(image.getSubimage(0, h / 2, w / 2, h / 2));
|
||||||
part4 = ImageUtil.imageToWritable(image.getSubimage(w / 2, h / 2, w / 2, h / 2));
|
part4 = ImageUtils.imageToWritable(image.getSubimage(w / 2, h / 2, w / 2, h / 2));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var glyph1 = new GlyphEntry(
|
var glyph1 = Resources.createGlyph(
|
||||||
StringIdentifier.image("dialog_background1__" + identifier),
|
Key.key("msb3", "dialogue/background/" + identifier + "__1"),
|
||||||
createGlyph(identifier, part1, "background1", positions.guiBackground().height() / 2, positions.guiBackground().topPartsY())
|
part1,
|
||||||
|
GlyphPositions.guiBackground.height() / 2,
|
||||||
|
GlyphPositions.guiBackground.topPartsY()
|
||||||
);
|
);
|
||||||
var glyph2 = new GlyphEntry(
|
var glyph2 = Resources.createGlyph(
|
||||||
StringIdentifier.image("dialog_background2__" + identifier),
|
Key.key("msb3", "dialogue/background/" + identifier + "__2"),
|
||||||
createGlyph(identifier, part2, "background2", positions.guiBackground().height() / 2, positions.guiBackground().topPartsY())
|
part2,
|
||||||
|
GlyphPositions.guiBackground.height() / 2,
|
||||||
|
GlyphPositions.guiBackground.topPartsY()
|
||||||
);
|
);
|
||||||
var glyph3 = new GlyphEntry(
|
var glyph3 = Resources.createGlyph(
|
||||||
StringIdentifier.image("dialog_background3__" + identifier),
|
Key.key("msb3", "dialogue/background/" + identifier + "__3"),
|
||||||
createGlyph(identifier, part3, "background3", positions.guiBackground().height() / 2, positions.guiBackground().bottomPartsY())
|
part3,
|
||||||
|
GlyphPositions.guiBackground.height() / 2,
|
||||||
|
GlyphPositions.guiBackground.bottomPartsY()
|
||||||
);
|
);
|
||||||
var glyph4 = new GlyphEntry(
|
var glyph4 = Resources.createGlyph(
|
||||||
StringIdentifier.image("dialog_background4__" + identifier),
|
Key.key("msb3", "dialogue/background/" + identifier + "__4"),
|
||||||
createGlyph(identifier, part4, "background4", positions.guiBackground().height() / 2, positions.guiBackground().bottomPartsY())
|
part4,
|
||||||
|
GlyphPositions.guiBackground.height() / 2,
|
||||||
|
GlyphPositions.guiBackground.bottomPartsY()
|
||||||
);
|
);
|
||||||
|
|
||||||
backgrounds.put(identifier, new Background(glyph1.glyph(), glyph2.glyph(), glyph3.glyph(), glyph4.glyph()));
|
backgrounds.put(identifier, new Background(glyph1, glyph2, glyph3, glyph4));
|
||||||
glyphResourcePack.with(glyph1.identifier(), glyph1.glyph());
|
|
||||||
glyphResourcePack.with(glyph2.identifier(), glyph2.glyph());
|
|
||||||
glyphResourcePack.with(glyph3.identifier(), glyph3.glyph());
|
|
||||||
glyphResourcePack.with(glyph4.identifier(), glyph4.glyph());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerSubstrate(String identifier, Writable writable) {
|
public void registerSubstrate(String identifier, Writable writable) {
|
||||||
registerSubstrate(identifier, writable, DialogGlyphPositions.DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerSubstrate(String identifier, Writable writable, DialogGlyphPositions positions) {
|
|
||||||
BufferedImage image;
|
BufferedImage image;
|
||||||
Writable part1;
|
Writable part1;
|
||||||
Writable part2;
|
Writable part2;
|
||||||
@ -170,168 +125,129 @@ public class DialogueResources {
|
|||||||
var w = image.getWidth();
|
var w = image.getWidth();
|
||||||
var h = image.getHeight();
|
var h = image.getHeight();
|
||||||
|
|
||||||
part1 = ImageUtil.imageToWritable(image.getSubimage(0, 0, w / 2, h));
|
part1 = ImageUtils.imageToWritable(image.getSubimage(0, 0, w / 2, h));
|
||||||
part2 = ImageUtil.imageToWritable(image.getSubimage(w / 2, 0, w / 2, h));
|
part2 = ImageUtils.imageToWritable(image.getSubimage(w / 2, 0, w / 2, h));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var glyph1 = new GlyphEntry(
|
var glyph1 = Resources.createGlyph(
|
||||||
StringIdentifier.image("dialog_substrate1__" + identifier),
|
Key.key("msb3", "dialogue/substrate/" + identifier + "__1"),
|
||||||
createGlyph(identifier, part1, "substrate1", positions.phraseSubstrate().height(), positions.phraseSubstrate().y())
|
part1,
|
||||||
|
GlyphPositions.phraseSubstrate.height(),
|
||||||
|
GlyphPositions.phraseSubstrate.y()
|
||||||
);
|
);
|
||||||
var glyph2 = new GlyphEntry(
|
var glyph2 = Resources.createGlyph(
|
||||||
StringIdentifier.image("dialog_substrate2__" + identifier),
|
Key.key("msb3", "dialogue/substrate/" + identifier + "__2"),
|
||||||
createGlyph(identifier, part2, "substrate2", positions.phraseSubstrate().height(), positions.phraseSubstrate().y())
|
part2,
|
||||||
|
GlyphPositions.phraseSubstrate.height(),
|
||||||
|
GlyphPositions.phraseSubstrate.y()
|
||||||
);
|
);
|
||||||
|
|
||||||
substrates.put(identifier, new Substrate(glyph1.glyph(), glyph2.glyph()));
|
substrates.put(identifier, new Substrate(glyph1, glyph2));
|
||||||
glyphResourcePack.with(glyph1.identifier(), glyph1.glyph());
|
|
||||||
glyphResourcePack.with(glyph2.identifier(), glyph2.glyph());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerFont(String identifier, Writable writable) {
|
|
||||||
registerFont(identifier, writable, DialogGlyphPositions.DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerFont(String identifier, Writable writable, DialogGlyphPositions positions) {
|
|
||||||
var propertiesList = Stream.concat(Stream.concat(IntStream.range(0, positions.phraseText().maxLines()).map((idx) -> {
|
|
||||||
return idx * (positions.phraseText().fontHeight() + 1) + positions.phraseText().firstLineAscent() * -1;
|
|
||||||
}).boxed().map((ascent) -> {
|
|
||||||
return new TextureProperties(positions.phraseText().fontHeight(), ascent * -1);
|
|
||||||
}), IntStream.range(0, positions.answerText().maxLines()).map((idx) -> {
|
|
||||||
return idx * (positions.answerText().fontHeight() + 1) + positions.answerText().topFirstLineAscent() * -1;
|
|
||||||
}).boxed().map((ascent) -> {
|
|
||||||
return new TextureProperties(positions.answerText().fontHeight(), ascent * -1);
|
|
||||||
})), IntStream.range(0, positions.answerText().maxLines()).map((idx) -> {
|
|
||||||
return idx * (positions.answerText().fontHeight() + 1) + positions.answerText().bottomFirstLineAscent() * -1;
|
|
||||||
}).boxed().map((ascent) -> {
|
|
||||||
return new TextureProperties(positions.answerText().fontHeight(), ascent * -1);
|
|
||||||
})).toList();
|
|
||||||
|
|
||||||
var glyphIdentifier = StringIdentifier.of("dialog_font", LanguageGlyphCollection.class);
|
|
||||||
var font = GlyphFont.minecraftFontGlyphCollection(DIALOGUE_FONT_KEY, Key.key("dialog/font.png"), writable, propertiesList);
|
|
||||||
|
|
||||||
fonts.put(identifier, new FontGlyphEntry(glyphIdentifier, font));
|
|
||||||
glyphResourcePack.with(glyphIdentifier, font);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerButton(String identifier, Writable writable) {
|
public void registerButton(String identifier, Writable writable) {
|
||||||
registerButton(identifier, writable, DialogGlyphPositions.DEFAULT);
|
var glyph1 = Resources.createGlyph(
|
||||||
}
|
Key.key("msb3", "dialogue/button/" + identifier),
|
||||||
|
|
||||||
public void registerButton(String identifier, Writable writable, DialogGlyphPositions positions) {
|
|
||||||
var glyph1 = createGlyph(identifier,
|
|
||||||
writable,
|
writable,
|
||||||
"button1",
|
GlyphPositions.answerButton.height(),
|
||||||
positions.answerButton().height(),
|
GlyphPositions.answerButton.topButtonY()
|
||||||
positions.answerButton().topButtonY());
|
);
|
||||||
var glyph2 = createGlyph(identifier,
|
var glyph2 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/button/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"button2",
|
GlyphPositions.answerButton.height(),
|
||||||
positions.answerButton().height(),
|
GlyphPositions.answerButton.topButtonY()
|
||||||
positions.answerButton().topButtonY());
|
);
|
||||||
var glyph3 = createGlyph(identifier,
|
var glyph3 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/button/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"button3",
|
GlyphPositions.answerButton.height(),
|
||||||
positions.answerButton().height(),
|
GlyphPositions.answerButton.bottomButtonY()
|
||||||
positions.answerButton().bottomButtonY());
|
);
|
||||||
var glyph4 = createGlyph(identifier,
|
var glyph4 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/button/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"button4",
|
GlyphPositions.answerButton.height(),
|
||||||
positions.answerButton().height(),
|
GlyphPositions.answerButton.bottomButtonY()
|
||||||
positions.answerButton().bottomButtonY());
|
);
|
||||||
|
|
||||||
buttons.put(identifier, new Button(glyph1, glyph2, glyph3, glyph4));
|
buttons.put(identifier, new Button(glyph1, glyph2, glyph3, glyph4));
|
||||||
glyphResourcePack
|
|
||||||
.with(StringIdentifier.image("dialog_button1__" + identifier), glyph1)
|
|
||||||
.with(StringIdentifier.image("dialog_button2__" + identifier), glyph2)
|
|
||||||
.with(StringIdentifier.image("dialog_button3__" + identifier), glyph3)
|
|
||||||
.with(StringIdentifier.image("dialog_button4__" + identifier), glyph4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerActiveTextField(String identifier, Writable writable) {
|
public void registerActiveTextField(String identifier, Writable writable) {
|
||||||
registerActiveTextField(identifier, writable, DialogGlyphPositions.DEFAULT);
|
var glyph1 = Resources.createGlyph(
|
||||||
}
|
Key.key("msb3", "dialogue/text_field/" + identifier),
|
||||||
|
|
||||||
public void registerActiveTextField(String identifier, Writable writable, DialogGlyphPositions positions) {
|
|
||||||
var glyph1 = createGlyph(identifier,
|
|
||||||
writable,
|
writable,
|
||||||
"active_field1",
|
GlyphPositions.answerField.height(),
|
||||||
positions.answerField().height(),
|
GlyphPositions.answerField.topFieldY()
|
||||||
positions.answerField().topFieldY());
|
);
|
||||||
var glyph2 = createGlyph(identifier,
|
var glyph2 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/text_field/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"active_field2",
|
GlyphPositions.answerField.height(),
|
||||||
positions.answerField().height(),
|
GlyphPositions.answerField.topFieldY()
|
||||||
positions.answerField().topFieldY());
|
);
|
||||||
var glyph3 = createGlyph(identifier,
|
var glyph3 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/text_field/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"active_field3",
|
GlyphPositions.answerField.height(),
|
||||||
positions.answerField().height(),
|
GlyphPositions.answerField.bottomFieldY()
|
||||||
positions.answerField().bottomFieldY());
|
);
|
||||||
var glyph4 = createGlyph(identifier,
|
var glyph4 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/text_field/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"active_field4",
|
GlyphPositions.answerField.height(),
|
||||||
positions.answerField().height(),
|
GlyphPositions.answerField.bottomFieldY()
|
||||||
positions.answerField().bottomFieldY());
|
);
|
||||||
|
|
||||||
activeFields.put(identifier, new TextField(glyph1, glyph2, glyph3, glyph4));
|
activeFields.put(identifier, new TextField(glyph1, glyph2, glyph3, glyph4));
|
||||||
glyphResourcePack
|
|
||||||
.with(StringIdentifier.image("active_field1__" + identifier), glyph1)
|
|
||||||
.with(StringIdentifier.image("active_field2__" + identifier), glyph2)
|
|
||||||
.with(StringIdentifier.image("active_field3__" + identifier), glyph3)
|
|
||||||
.with(StringIdentifier.image("active_field4__" + identifier), glyph4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerNotActiveTextField(String identifier, Writable writable) {
|
public void registerNotActiveTextField(String identifier, Writable writable) {
|
||||||
registerNotActiveTextField(identifier, writable, DialogGlyphPositions.DEFAULT);
|
var glyph1 = Resources.createGlyph(
|
||||||
}
|
Key.key("msb3", "dialogue/inactive_text_field/" + identifier),
|
||||||
|
|
||||||
public void registerNotActiveTextField(String identifier, Writable writable, DialogGlyphPositions positions) {
|
|
||||||
var glyph1 = createGlyph(identifier,
|
|
||||||
writable,
|
writable,
|
||||||
"not_active_field1",
|
GlyphPositions.answerField.height(),
|
||||||
positions.answerField().height(),
|
GlyphPositions.answerField.topFieldY()
|
||||||
positions.answerField().topFieldY());
|
);
|
||||||
var glyph2 = createGlyph(identifier,
|
var glyph2 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/inactive_text_field/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"not_active_field2",
|
GlyphPositions.answerField.height(),
|
||||||
positions.answerField().height(),
|
GlyphPositions.answerField.topFieldY()
|
||||||
positions.answerField().topFieldY());
|
);
|
||||||
var glyph3 = createGlyph(identifier,
|
var glyph3 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/inactive_text_field/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"not_active_field3",
|
GlyphPositions.answerField.height(),
|
||||||
positions.answerField().height(),
|
GlyphPositions.answerField.bottomFieldY()
|
||||||
positions.answerField().bottomFieldY());
|
);
|
||||||
var glyph4 = createGlyph(identifier,
|
var glyph4 = Resources.createGlyph(
|
||||||
|
Key.key("msb3", "dialogue/inactive_text_field/" + identifier),
|
||||||
writable,
|
writable,
|
||||||
"not_active_field4",
|
GlyphPositions.answerField.height(),
|
||||||
positions.answerField().height(),
|
GlyphPositions.answerField.bottomFieldY()
|
||||||
positions.answerField().bottomFieldY());
|
);
|
||||||
|
|
||||||
notActiveFields.put(identifier, new TextField(glyph1, glyph2, glyph3, glyph4));
|
notActiveFields.put(identifier, new TextField(glyph1, glyph2, glyph3, glyph4));
|
||||||
glyphResourcePack
|
|
||||||
.with(StringIdentifier.image("not_active_field1__" + identifier), glyph1)
|
|
||||||
.with(StringIdentifier.image("not_active_field2__" + identifier), glyph2)
|
|
||||||
.with(StringIdentifier.image("not_active_field3__" + identifier), glyph3)
|
|
||||||
.with(StringIdentifier.image("not_active_field4__" + identifier), glyph4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ImageGlyph> getAvatar(String identifier) {
|
public Optional<GlyphImage> getAvatar(String identifier) {
|
||||||
return getGlyphFromMap(identifier, avatars);
|
return Optional.ofNullable(avatars.get(identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ImageGlyph> getAvatarFrame(String identifier) {
|
public Optional<GlyphImage> getAvatarFrame(String identifier) {
|
||||||
return getGlyphFromMap(identifier, avatarFrames);
|
return Optional.ofNullable(avatarFrames.get(identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ImageGlyph> getScrollUp(String identifier) {
|
public Optional<GlyphImage> getScrollUp(String identifier) {
|
||||||
return getGlyphFromMap(identifier, scrollUp);
|
return Optional.ofNullable(scrollUp.get(identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ImageGlyph> getScrollDown(String identifier) {
|
public Optional<GlyphImage> getScrollDown(String identifier) {
|
||||||
return getGlyphFromMap(identifier, scrollDown);
|
return Optional.ofNullable(scrollDown.get(identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Background> getBackground(String identifier) {
|
public Optional<Background> getBackground(String identifier) {
|
||||||
@ -342,10 +258,6 @@ public class DialogueResources {
|
|||||||
return Optional.ofNullable(substrates.get(identifier));
|
return Optional.ofNullable(substrates.get(identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<LanguageGlyphCollection> getFont(String identifier) {
|
|
||||||
return Optional.ofNullable(fonts.get(identifier)).map(FontGlyphEntry::glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Button> getButton(String identifier) {
|
public Optional<Button> getButton(String identifier) {
|
||||||
return Optional.ofNullable(buttons.get(identifier));
|
return Optional.ofNullable(buttons.get(identifier));
|
||||||
}
|
}
|
||||||
@ -357,21 +269,4 @@ public class DialogueResources {
|
|||||||
public Optional<TextField> getNotActiveTextField(String identifier) {
|
public Optional<TextField> getNotActiveTextField(String identifier) {
|
||||||
return Optional.ofNullable(notActiveFields.get(identifier));
|
return Optional.ofNullable(notActiveFields.get(identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageGlyph createGlyph(String identifier, Writable writable, String element, int height, int ascent) {
|
|
||||||
return ImageGlyph.of(DIALOGUE_FONT_KEY,
|
|
||||||
Texture.texture().key(Key.key("msb3", "dialog/" + identifier + "/" + element + ".png")).data(writable).build(),
|
|
||||||
new TextureProperties(height, ascent));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<ImageGlyph> getGlyphFromMap(String identifier, Map<String, GlyphEntry> map) {
|
|
||||||
return Optional.ofNullable(map.get(identifier))
|
|
||||||
.map(entry -> {
|
|
||||||
try {
|
|
||||||
return glyphResourcePack.get(entry.identifier());
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.resource;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter.LanguageGlyphCollection;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.pack.StringIdentifier;
|
|
||||||
|
|
||||||
public record FontGlyphEntry(StringIdentifier<@NotNull LanguageGlyphCollection> identifier, LanguageGlyphCollection glyph) {}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.resource;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.pack.StringIdentifier;
|
|
||||||
|
|
||||||
public record GlyphEntry(StringIdentifier<@NotNull ImageGlyph> identifier, ImageGlyph glyph) {}
|
|
||||||
@ -1,97 +1,58 @@
|
|||||||
package ru.dragonestia.msb3.api.resource;
|
package ru.dragonestia.msb3.api.resource;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.pack.GlyphResourcePack;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.pack.StringIdentifier;
|
|
||||||
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
||||||
|
import ru.dragonestia.msb3.resource.Resources;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
import team.unnamed.creative.base.Writable;
|
import team.unnamed.creative.base.Writable;
|
||||||
import team.unnamed.creative.texture.Texture;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class MonologueResources {
|
public class MonologueResources {
|
||||||
|
|
||||||
private static final Key MONOLOG_FONT_KEY = Key.key("msb3", "monolog");
|
|
||||||
public static final String DEFAULT = "default";
|
public static final String DEFAULT = "default";
|
||||||
|
|
||||||
private final GlyphResourcePack glyphResourcePack;
|
private final Map<String, GlyphImage> avatars = new HashMap<>();
|
||||||
private final Map<String, GlyphEntry> avatars = new HashMap<>();
|
private final Map<String, GlyphImage> frames = new HashMap<>();
|
||||||
private final Map<String, GlyphEntry> frames = new HashMap<>();
|
@Getter private static final GlyphImage speechIndicator = Resources.createGlyph(
|
||||||
private final GlyphEntry speechIndicator = initSpeechIndicator();
|
Key.key("msb3", "monologue/speech_indicator"),
|
||||||
|
ResourceFromJar.of("glyphs/monologue/speech_indicator.png"),
|
||||||
public MonologueResources(GlyphResourcePack glyphResourcePack) {
|
8,
|
||||||
this.glyphResourcePack = glyphResourcePack;
|
6
|
||||||
|
);
|
||||||
registerAvatar(DEFAULT, ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/monologue/default_avatar.png"));
|
|
||||||
registerFrame(DEFAULT, ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/monologue/avatar_frame.png"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GlyphEntry initSpeechIndicator() {
|
|
||||||
var writable = ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/monologue/speech_indicator.png");
|
|
||||||
var glyph = ImageGlyph.of(MONOLOG_FONT_KEY,
|
|
||||||
Texture.texture().key(Key.key("msb3", "monolog/speech_indicator.png")).data(writable).build(),
|
|
||||||
new TextureProperties(8, 6));
|
|
||||||
var glyphIdentifier = StringIdentifier.image("monolog_speech_indicator");
|
|
||||||
|
|
||||||
return new GlyphEntry(glyphIdentifier, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerAvatar(String identifier, Writable writable) {
|
public void registerAvatar(String identifier, Writable writable) {
|
||||||
var glyph = ImageGlyph.of(MONOLOG_FONT_KEY,
|
var glyph = Resources.createGlyph(
|
||||||
Texture.texture().key(Key.key("msb3", "monolog/avatar_" + identifier + ".png")).data(writable).build(),
|
Key.key("msb3", "monologue/avatar/" + identifier),
|
||||||
new TextureProperties(42, 2));
|
writable,
|
||||||
|
42,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
var glyphIdentifier = StringIdentifier.image("monolog_avatar_" + identifier);
|
avatars.put(identifier, glyph);
|
||||||
|
|
||||||
avatars.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
|
||||||
|
|
||||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerFrame(String identifier, Writable writable) {
|
public void registerFrame(String identifier, Writable writable) {
|
||||||
var glyph = ImageGlyph.of(MONOLOG_FONT_KEY,
|
var glyph = Resources.createGlyph(
|
||||||
Texture.texture().key(Key.key("msb3", "monolog/frame_" + identifier + ".png")).data(writable).build(),
|
Key.key("msb3", "monologue/frame/" + identifier),
|
||||||
new TextureProperties(50, 6));
|
writable,
|
||||||
|
50,
|
||||||
|
6
|
||||||
|
);
|
||||||
|
|
||||||
var glyphIdentifier = StringIdentifier.image("monolog_frame_" + identifier);
|
frames.put(identifier, glyph);
|
||||||
|
|
||||||
frames.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
|
||||||
|
|
||||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ImageGlyph> getAvatar(String identifier) {
|
public Optional<GlyphImage> getAvatar(String identifier) {
|
||||||
return Optional.ofNullable(avatars.get(identifier))
|
return Optional.ofNullable(avatars.get(identifier));
|
||||||
.map(entry -> {
|
|
||||||
try {
|
|
||||||
return glyphResourcePack.get(entry.identifier());
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ImageGlyph> getFrame(String identifier) {
|
public Optional<GlyphImage> getFrame(String identifier) {
|
||||||
return Optional.ofNullable(frames.get(identifier))
|
return Optional.ofNullable(frames.get(identifier));
|
||||||
.map(entry -> {
|
|
||||||
try {
|
|
||||||
return glyphResourcePack.get(entry.identifier());
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImageGlyph getSpeechIndicator() {
|
|
||||||
return glyphResourcePack.get(speechIndicator.identifier());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void compile(GlyphResourcePack resourcePack) {
|
|
||||||
resourcePack.with(speechIndicator.identifier(), speechIndicator.glyph());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,98 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.resource;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import net.kyori.adventure.key.Key;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.compile.GlyphCompiler;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.font.GlyphFont;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.pack.GlyphResourcePack;
|
|
||||||
import ru.dragonestia.msb3.api.item.BlankSlotItem;
|
|
||||||
import ru.dragonestia.msb3.api.talk.dialogue.DialogueRenderer;
|
|
||||||
import ru.dragonestia.msb3.api.title.BlackScreen;
|
|
||||||
import team.unnamed.creative.ResourcePack;
|
|
||||||
import team.unnamed.creative.atlas.Atlas;
|
|
||||||
import team.unnamed.creative.atlas.AtlasSource;
|
|
||||||
import team.unnamed.creative.base.Writable;
|
|
||||||
import team.unnamed.creative.lang.Language;
|
|
||||||
import team.unnamed.creative.model.Model;
|
|
||||||
import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackWriter;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Log4j2
|
|
||||||
public class ResourcePackManager {
|
|
||||||
|
|
||||||
private final ResourcePack resourcePack;
|
|
||||||
private final GlyphResourcePack glyphResourcePack;
|
|
||||||
private final MonologueResources monologueResources;
|
|
||||||
private final DialogueResources dialogueResources;
|
|
||||||
|
|
||||||
public ResourcePackManager() {
|
|
||||||
resourcePack = ResourcePack.resourcePack();
|
|
||||||
resourcePack.packMeta(34, "Dragonestia MSB3 - Resource pack");
|
|
||||||
resourcePack.icon(Writable.resource(getClass().getClassLoader(), "logo.png"));
|
|
||||||
resourcePack.unknownFile("credits.txt", Writable.stringUtf8("dragonestia.ru"));
|
|
||||||
|
|
||||||
glyphResourcePack = GlyphResourcePack.create();
|
|
||||||
monologueResources = new MonologueResources(glyphResourcePack);
|
|
||||||
dialogueResources = new DialogueResources(glyphResourcePack);
|
|
||||||
initDefaultGlyphs();
|
|
||||||
initLocales();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initDefaultGlyphs() {
|
|
||||||
glyphResourcePack.withMojangSpaces();
|
|
||||||
glyphResourcePack.with(BlankSlotItem.compile());
|
|
||||||
glyphResourcePack.with(GlyphCompiler.instance().compile(BlackScreen.GLYPH));
|
|
||||||
glyphResourcePack.with(GlyphFont.compile());
|
|
||||||
monologueResources.compile(glyphResourcePack);
|
|
||||||
dialogueResources.compile(glyphResourcePack);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initLocales() {
|
|
||||||
var locales = new HashMap<String, String>();
|
|
||||||
locales.put("container.inventory", " ");
|
|
||||||
|
|
||||||
for (var lang: List.of("en_us", "ru_ru")) {
|
|
||||||
resourcePack.language(Language.language(Key.key("minecraft", lang), locales));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void compile() {
|
|
||||||
glyphResourcePack.writeAll(resourcePack);
|
|
||||||
generateAtlases();
|
|
||||||
MinecraftResourcePackWriter.minecraft().writeToZipFile(new File("resource-pack.zip"), resourcePack);
|
|
||||||
log.info("Compiled resource pack. File: ./resource-pack.zip");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateAtlases() {
|
|
||||||
Atlas.Builder atlasBuilder = Atlas.atlas();
|
|
||||||
atlasBuilder.key(Key.key("minecraft", "blocks"));
|
|
||||||
Set<String> applicableTextureKeys = new HashSet<>();
|
|
||||||
|
|
||||||
for (Model model: resourcePack.models()) {
|
|
||||||
for (var layer: model.textures().layers()) {
|
|
||||||
var key = layer.key();
|
|
||||||
if (key != null) {
|
|
||||||
applicableTextureKeys.add(key.asString().concat(".png"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var texture: model.textures().variables().values()) {
|
|
||||||
var key = texture.key();
|
|
||||||
if (key != null) {
|
|
||||||
applicableTextureKeys.add(key.asString().concat(".png"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var sources = resourcePack.textures()
|
|
||||||
.stream()
|
|
||||||
//.filter(texture -> !applicableTextureKeys.contains(texture.key().asString()))
|
|
||||||
.map(texture -> (AtlasSource) AtlasSource.single(Key.key(texture.key().toString().replace(".png", "")))).toList();
|
|
||||||
atlasBuilder.sources(sources);
|
|
||||||
resourcePack.atlas(atlasBuilder.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,10 @@
|
|||||||
package ru.dragonestia.msb3.api.resource.dialog;
|
package ru.dragonestia.msb3.api.resource.dialog;
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
|
|
||||||
public record Background(ImageGlyph part1, ImageGlyph part2, ImageGlyph part3, ImageGlyph part4) {}
|
public record Background(
|
||||||
|
GlyphImage part1,
|
||||||
|
GlyphImage part2,
|
||||||
|
GlyphImage part3,
|
||||||
|
GlyphImage part4
|
||||||
|
) {}
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
package ru.dragonestia.msb3.api.resource.dialog;
|
package ru.dragonestia.msb3.api.resource.dialog;
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
|
|
||||||
public record Button(ImageGlyph button1, ImageGlyph button2, ImageGlyph button3, ImageGlyph button4) {
|
public record Button(
|
||||||
|
GlyphImage button1,
|
||||||
|
GlyphImage button2,
|
||||||
|
GlyphImage button3,
|
||||||
|
GlyphImage button4
|
||||||
|
) {
|
||||||
|
|
||||||
public ImageGlyph get(ButtonNumber number) {
|
public GlyphImage get(ButtonNumber number) {
|
||||||
return switch (number) {
|
return switch (number) {
|
||||||
case BUTTON_1 -> button1;
|
case BUTTON_1 -> button1;
|
||||||
case BUTTON_2 -> button2;
|
case BUTTON_2 -> button2;
|
||||||
|
|||||||
@ -0,0 +1,47 @@
|
|||||||
|
package ru.dragonestia.msb3.api.resource.dialog;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class GlyphPositions {
|
||||||
|
|
||||||
|
public final GuiBackground guiBackground = new GuiBackground(35, -96, 262);
|
||||||
|
public final PhraseText phraseText = new PhraseText(11, -11, 340, 8, 8);
|
||||||
|
public final PhraseSubstrate phraseSubstrate = new PhraseSubstrate(-24, 19, 356, 116);
|
||||||
|
public final Avatar avatar = new Avatar(-144, 11, 100, 116);
|
||||||
|
public final AnswerText answerText = new AnswerText(175, 4, 8, -145, 149, -122, -170);
|
||||||
|
public final AnswerField answerField = new AnswerField(-117, -165, -153, 141, 44);
|
||||||
|
public final AnswerButton answerButton = new AnswerButton(-124, -182, 41, 97, 20);
|
||||||
|
public final ScrollPhraseButton scrollPhraseButton = new ScrollPhraseButton(0, 126, -100, 10);
|
||||||
|
public final ChestSlotsButtons chestSlotsButtons = new ChestSlotsButtons(new int[] {45, 46}, new int[] {52, 53}, new int[] {65, 66}, new int[] {68, 69}, new int[] {56, 57}, new int[] {59, 60});
|
||||||
|
|
||||||
|
public record GuiBackground(int topPartsY, int bottomPartsY, int height) {}
|
||||||
|
|
||||||
|
public record PhraseText(int maxLines, int lineX, int lineWidth, int fontHeight, int firstLineAscent) {
|
||||||
|
|
||||||
|
public TextureProperties firstLineProperties() {
|
||||||
|
return new TextureProperties(fontHeight, firstLineAscent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record PhraseSubstrate(int x, int y, int width, int height) {}
|
||||||
|
|
||||||
|
public record Avatar(int x, int y, int height, int frameHeight) {
|
||||||
|
|
||||||
|
public int frameBorderSize() {
|
||||||
|
return (frameHeight - height) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record AnswerText(int lineWidth, int maxLines, int fontHeight, int leftLineX,
|
||||||
|
int rightLineX, int topFirstLineAscent, int bottomFirstLineAscent) {}
|
||||||
|
|
||||||
|
public record AnswerField(int topFieldY, int bottomFieldY, int leftFieldX, int rightFieldX, int height) {}
|
||||||
|
|
||||||
|
public record AnswerButton(int topButtonY, int bottomButtonY, int leftButtonX,
|
||||||
|
int rightButtonX, int height) {}
|
||||||
|
|
||||||
|
public record ScrollPhraseButton(int scrollUpButtonX, int scrollDownButtonX, int buttonY, int height) {}
|
||||||
|
|
||||||
|
public record ChestSlotsButtons(int[] scrollUp, int[] scrollDown, int[] answer1, int[] answer2, int[] answer3, int[] answer4) {}
|
||||||
|
}
|
||||||
@ -1,5 +1,8 @@
|
|||||||
package ru.dragonestia.msb3.api.resource.dialog;
|
package ru.dragonestia.msb3.api.resource.dialog;
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
|
|
||||||
public record Substrate(ImageGlyph part1, ImageGlyph part2) {}
|
public record Substrate(
|
||||||
|
GlyphImage part1,
|
||||||
|
GlyphImage part2
|
||||||
|
) {}
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
package ru.dragonestia.msb3.api.resource.dialog;
|
package ru.dragonestia.msb3.api.resource.dialog;
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
|
|
||||||
public record TextField(ImageGlyph field1, ImageGlyph field2, ImageGlyph field3, ImageGlyph field4) {
|
public record TextField(
|
||||||
|
GlyphImage field1,
|
||||||
|
GlyphImage field2,
|
||||||
|
GlyphImage field3,
|
||||||
|
GlyphImage field4
|
||||||
|
) {
|
||||||
|
|
||||||
public ImageGlyph get(ButtonNumber number) {
|
public GlyphImage get(ButtonNumber number) {
|
||||||
return switch (number) {
|
return switch (number) {
|
||||||
case BUTTON_1 -> field1;
|
case BUTTON_1 -> field1;
|
||||||
case BUTTON_2 -> field2;
|
case BUTTON_2 -> field2;
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
package ru.dragonestia.msb3.api.glyph.glyph.image;
|
package ru.dragonestia.msb3.api.resource.dialog;
|
||||||
|
|
||||||
public record TextureProperties(int height, int ascent) {}
|
public record TextureProperties(int height, int ascent) {}
|
||||||
@ -1,56 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.talk.dialogue;
|
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
|
|
||||||
public record DialogGlyphPositions(GuiBackground guiBackground,
|
|
||||||
PhraseText phraseText,
|
|
||||||
PhraseSubstrate phraseSubstrate,
|
|
||||||
Avatar avatar,
|
|
||||||
AnswerText answerText,
|
|
||||||
AnswerField answerField,
|
|
||||||
AnswerButton answerButton,
|
|
||||||
ScrollPhraseButton scrollPhraseButton,
|
|
||||||
ChestSlotsButtons chestSlotsButtons) {
|
|
||||||
|
|
||||||
public static final DialogGlyphPositions DEFAULT = new DialogGlyphPositions(
|
|
||||||
new GuiBackground(35, -96, 262),
|
|
||||||
new PhraseText(11, -11, 340, 8, 8),
|
|
||||||
new PhraseSubstrate(-24, 19, 356, 116),
|
|
||||||
new Avatar(-144, 11, 100, 116),
|
|
||||||
new AnswerText(175, 4, 8, -145, 149, -122, -170),
|
|
||||||
new AnswerField(-117, -165, -153, 141, 44),
|
|
||||||
new AnswerButton(-124, -182, 41, 97, 20),
|
|
||||||
new ScrollPhraseButton(0, 126, -100, 10),
|
|
||||||
new ChestSlotsButtons(new int[] {45, 46}, new int[] {52, 53}, new int[] {65, 66}, new int[] {68, 69}, new int[] {56, 57}, new int[] {59, 60})
|
|
||||||
);
|
|
||||||
|
|
||||||
public record GuiBackground(int topPartsY, int bottomPartsY, int height) {}
|
|
||||||
|
|
||||||
public record PhraseText(int maxLines, int lineX, int lineWidth, int fontHeight, int firstLineAscent) {
|
|
||||||
|
|
||||||
public TextureProperties firstLineProperties() {
|
|
||||||
return new TextureProperties(fontHeight, firstLineAscent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record PhraseSubstrate(int x, int y, int width, int height) {}
|
|
||||||
|
|
||||||
public record Avatar(int x, int y, int height, int frameHeight) {
|
|
||||||
|
|
||||||
public int frameBorderSize() {
|
|
||||||
return (frameHeight - height) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record AnswerText(int lineWidth, int maxLines, int fontHeight, int leftLineX,
|
|
||||||
int rightLineX, int topFirstLineAscent, int bottomFirstLineAscent) {}
|
|
||||||
|
|
||||||
public record AnswerField(int topFieldY, int bottomFieldY, int leftFieldX, int rightFieldX, int height) {}
|
|
||||||
|
|
||||||
public record AnswerButton(int topButtonY, int bottomButtonY, int leftButtonX,
|
|
||||||
int rightButtonX, int height) {}
|
|
||||||
|
|
||||||
public record ScrollPhraseButton(int scrollUpButtonX, int scrollDownButtonX, int buttonY, int height) {}
|
|
||||||
|
|
||||||
public record ChestSlotsButtons(int[] scrollUp, int[] scrollDown, int[] answer1, int[] answer2, int[] answer3, int[] answer4) {}
|
|
||||||
}
|
|
||||||
@ -21,15 +21,16 @@ import net.minestom.server.item.ItemStack;
|
|||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
import org.apache.commons.text.WordUtils;
|
import org.apache.commons.text.WordUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.AppendableGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.GlyphComponentBuilder;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.pack.GlyphResourcePack;
|
|
||||||
import ru.dragonestia.msb3.api.item.BlankSlotItem;
|
import ru.dragonestia.msb3.api.item.BlankSlotItem;
|
||||||
import ru.dragonestia.msb3.api.item.ItemUtil;
|
import ru.dragonestia.msb3.api.item.ItemUtil;
|
||||||
import ru.dragonestia.msb3.api.resource.dialog.ButtonNumber;
|
import ru.dragonestia.msb3.api.resource.dialog.ButtonNumber;
|
||||||
|
import ru.dragonestia.msb3.api.resource.dialog.GlyphPositions;
|
||||||
|
import ru.dragonestia.msb3.api.resource.dialog.TextureProperties;
|
||||||
import ru.dragonestia.msb3.api.util.StringUtil;
|
import ru.dragonestia.msb3.api.util.StringUtil;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.GlyphComponent;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.GlyphComponentBuilder;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.MinecraftFont;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
@ -42,7 +43,6 @@ public class DialogueRenderer extends Inventory {
|
|||||||
public static final int CHEST_GUI_WIDTH = 176;
|
public static final int CHEST_GUI_WIDTH = 176;
|
||||||
private static final Tag<String> TAG_CLICK_TYPE = Tag.String("msb3_dialogue_click_type");
|
private static final Tag<String> TAG_CLICK_TYPE = Tag.String("msb3_dialogue_click_type");
|
||||||
|
|
||||||
@Getter private final GlyphResourcePack glyphResourcePack = ServerBootstrap.getInstance().getResourcePackManager().getGlyphResourcePack();
|
|
||||||
private final Player player;
|
private final Player player;
|
||||||
@Getter @Setter private DialogueTheme theme;
|
@Getter @Setter private DialogueTheme theme;
|
||||||
@Getter private String text = "";
|
@Getter private String text = "";
|
||||||
@ -74,15 +74,15 @@ public class DialogueRenderer extends Inventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void scrollDown() {
|
public void scrollDown() {
|
||||||
if (maxLines > shifted + theme.getPositions().phraseText().maxLines()) {
|
if (maxLines > shifted + GlyphPositions.phraseText.maxLines()) {
|
||||||
shifted = Math.min(maxLines - theme.getPositions().phraseText().maxLines(), shifted + 3);
|
shifted = Math.min(maxLines - GlyphPositions.phraseText.maxLines(), shifted + 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rerender() {
|
public void rerender() {
|
||||||
setTitle(render());
|
setTitle(render());
|
||||||
|
|
||||||
var slots = getTheme().getPositions().chestSlotsButtons();
|
var slots = GlyphPositions.chestSlotsButtons;
|
||||||
|
|
||||||
for (var slot: slots.scrollUp()) {
|
for (var slot: slots.scrollUp()) {
|
||||||
if (shifted != 0) {
|
if (shifted != 0) {
|
||||||
@ -93,7 +93,7 @@ public class DialogueRenderer extends Inventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (var slot: slots.scrollDown()) {
|
for (var slot: slots.scrollDown()) {
|
||||||
if (maxLines > shifted + theme.getPositions().phraseText().maxLines()) {
|
if (maxLines > shifted + GlyphPositions.phraseText.maxLines()) {
|
||||||
setSlotClickable(slot, null, ClickType.SCROLL_DOWN);
|
setSlotClickable(slot, null, ClickType.SCROLL_DOWN);
|
||||||
} else {
|
} else {
|
||||||
resetClickableSlot(slot);
|
resetClickableSlot(slot);
|
||||||
@ -267,7 +267,7 @@ public class DialogueRenderer extends Inventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Component render() {
|
private Component render() {
|
||||||
var builder = GlyphComponentBuilder.gui(glyphResourcePack.spaces());
|
var builder = new GlyphComponentBuilder();
|
||||||
|
|
||||||
// GUI background
|
// GUI background
|
||||||
builder.append(CHEST_GUI_WIDTH / 2 + 2 - theme.getBackground().part1().width(), theme.getBackground().part1());
|
builder.append(CHEST_GUI_WIDTH / 2 + 2 - theme.getBackground().part1().width(), theme.getBackground().part1());
|
||||||
@ -276,12 +276,12 @@ public class DialogueRenderer extends Inventory {
|
|||||||
builder.append(CHEST_GUI_WIDTH / 2 + 1, theme.getBackground().part4());
|
builder.append(CHEST_GUI_WIDTH / 2 + 1, theme.getBackground().part4());
|
||||||
|
|
||||||
// Phrase substrate
|
// Phrase substrate
|
||||||
builder.append(theme.getPositions().phraseSubstrate().x(), theme.getSubstrate().part1());
|
builder.append(GlyphPositions.phraseSubstrate.x(), theme.getSubstrate().part1());
|
||||||
builder.append(theme.getPositions().phraseSubstrate().x() + theme.getPositions().phraseSubstrate().width() / 2, theme.getSubstrate().part2());
|
builder.append(GlyphPositions.phraseSubstrate.x() + GlyphPositions.phraseSubstrate.width() / 2, theme.getSubstrate().part2());
|
||||||
|
|
||||||
// Frame and avatar
|
// Frame and avatar
|
||||||
builder.append(theme.getPositions().avatar().x() - 8, theme.getAvatarFrame());
|
builder.append(GlyphPositions.avatar.x() - 8, theme.getAvatarFrame());
|
||||||
builder.append(theme.getPositions().avatar().x(), theme.getAvatar());
|
builder.append(GlyphPositions.avatar.x(), theme.getAvatar());
|
||||||
|
|
||||||
// Phrase text
|
// Phrase text
|
||||||
renderText(builder, shifted);
|
renderText(builder, shifted);
|
||||||
@ -289,22 +289,24 @@ public class DialogueRenderer extends Inventory {
|
|||||||
// Scroll phrase buttons (optional)
|
// Scroll phrase buttons (optional)
|
||||||
if (shifted != 0) {
|
if (shifted != 0) {
|
||||||
builder.append(
|
builder.append(
|
||||||
theme.getPositions().scrollPhraseButton().scrollUpButtonX(),
|
GlyphPositions.scrollPhraseButton.scrollUpButtonX(),
|
||||||
theme.getScrollTextUp());
|
theme.getScrollTextUp()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxLines > shifted + theme.getPositions().phraseText().maxLines()) {
|
if (maxLines > shifted + GlyphPositions.phraseText.maxLines()) {
|
||||||
builder.append(
|
builder.append(
|
||||||
theme.getPositions().scrollPhraseButton().scrollDownButtonX(),
|
GlyphPositions.scrollPhraseButton.scrollDownButtonX(),
|
||||||
theme.getScrollTextDown());
|
theme.getScrollTextDown()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Answers
|
// Answers
|
||||||
for (var number: ButtonNumber.values()) {
|
for (var number: ButtonNumber.values()) {
|
||||||
if (buttonsText.containsKey(number)) {
|
if (buttonsText.containsKey(number)) {
|
||||||
builder.append(number.getIndex() % 2 == 0
|
builder.append(number.getIndex() % 2 == 0
|
||||||
? theme.getPositions().answerField().leftFieldX()
|
? GlyphPositions.answerField.leftFieldX()
|
||||||
: theme.getPositions().answerField().rightFieldX(),
|
: GlyphPositions.answerField.rightFieldX(),
|
||||||
switch (number) {
|
switch (number) {
|
||||||
case BUTTON_1 -> theme.getActiveTextField1();
|
case BUTTON_1 -> theme.getActiveTextField1();
|
||||||
case BUTTON_2 -> theme.getActiveTextField2();
|
case BUTTON_2 -> theme.getActiveTextField2();
|
||||||
@ -313,8 +315,8 @@ public class DialogueRenderer extends Inventory {
|
|||||||
});
|
});
|
||||||
|
|
||||||
builder.append(number.getIndex() % 2 == 0
|
builder.append(number.getIndex() % 2 == 0
|
||||||
? theme.getPositions().answerButton().leftButtonX()
|
? GlyphPositions.answerButton.leftButtonX()
|
||||||
: theme.getPositions().answerButton().rightButtonX(),
|
: GlyphPositions.answerButton.rightButtonX(),
|
||||||
switch (number) {
|
switch (number) {
|
||||||
case BUTTON_1 -> theme.getButton1();
|
case BUTTON_1 -> theme.getButton1();
|
||||||
case BUTTON_2 -> theme.getButton2();
|
case BUTTON_2 -> theme.getButton2();
|
||||||
@ -325,19 +327,20 @@ public class DialogueRenderer extends Inventory {
|
|||||||
var lines = breakIntoLines(
|
var lines = breakIntoLines(
|
||||||
buttonsText.get(number),
|
buttonsText.get(number),
|
||||||
number.getIndex() < 2
|
number.getIndex() < 2
|
||||||
? new TextureProperties(theme.getPositions().answerText().fontHeight(), theme.getPositions().answerText().topFirstLineAscent())
|
? new TextureProperties(GlyphPositions.answerText.fontHeight(), GlyphPositions.answerText.topFirstLineAscent())
|
||||||
: new TextureProperties(theme.getPositions().answerText().fontHeight(), theme.getPositions().answerText().bottomFirstLineAscent()),
|
: new TextureProperties(GlyphPositions.answerText.fontHeight(), GlyphPositions.answerText.bottomFirstLineAscent()),
|
||||||
theme.getPositions().answerText().fontHeight(),
|
GlyphPositions.answerText.fontHeight(),
|
||||||
theme.getPositions().answerText().lineWidth());
|
GlyphPositions.answerText.lineWidth());
|
||||||
|
|
||||||
for (int lineIdx = 0; lineIdx < Math.min(lines.size(), theme.getPositions().answerText().maxLines()); lineIdx++) {
|
|
||||||
boolean endWithDots = lineIdx + 1 == theme.getPositions().answerText().maxLines() && lineIdx + 1 != lines.size();
|
for (int lineIdx = 0; lineIdx < Math.min(lines.size(), GlyphPositions.answerText.maxLines()); lineIdx++) {
|
||||||
|
boolean endWithDots = lineIdx + 1 == GlyphPositions.answerText.maxLines() && lineIdx + 1 != lines.size();
|
||||||
var line = lines.get(lineIdx);
|
var line = lines.get(lineIdx);
|
||||||
|
|
||||||
builder.append(
|
builder.append(
|
||||||
number.getIndex() % 2 == 0
|
number.getIndex() % 2 == 0
|
||||||
? theme.getPositions().answerText().leftLineX()
|
? GlyphPositions.answerText.leftLineX()
|
||||||
: theme.getPositions().answerText().rightLineX(),
|
: GlyphPositions.answerText.rightLineX(),
|
||||||
line.toGlyphList(line.textureProperties(), 0, endWithDots, switch (number) {
|
line.toGlyphList(line.textureProperties(), 0, endWithDots, switch (number) {
|
||||||
case BUTTON_1 -> theme.getColorAnswerText1();
|
case BUTTON_1 -> theme.getColorAnswerText1();
|
||||||
case BUTTON_2 -> theme.getColorAnswerText2();
|
case BUTTON_2 -> theme.getColorAnswerText2();
|
||||||
@ -346,10 +349,12 @@ public class DialogueRenderer extends Inventory {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
builder.append(number.getIndex() % 2 == 0
|
builder.append(number.getIndex() % 2 == 0
|
||||||
? theme.getPositions().answerField().leftFieldX()
|
? GlyphPositions.answerField.leftFieldX()
|
||||||
: theme.getPositions().answerField().rightFieldX(),
|
: GlyphPositions.answerField.rightFieldX(),
|
||||||
switch (number) {
|
switch (number) {
|
||||||
case BUTTON_1 -> theme.getNotActiveTextField1();
|
case BUTTON_1 -> theme.getNotActiveTextField1();
|
||||||
case BUTTON_2 -> theme.getNotActiveTextField2();
|
case BUTTON_2 -> theme.getNotActiveTextField2();
|
||||||
@ -362,13 +367,12 @@ public class DialogueRenderer extends Inventory {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<TextLine> breakIntoLines(String input, TextureProperties firstLineProperties, int fontHeight, int maxWidth) throws IllegalStateException {
|
private List<TextLine> breakIntoLines(String input, TextureProperties firstLineProperties, int fontHeight, int maxWidth) throws IllegalStateException {
|
||||||
var resolvedText = MiniMessage.miniMessage().deserialize(input);
|
var resolvedText = MiniMessage.miniMessage().deserialize(input);
|
||||||
var lines = StringUtil.splitIntoParts(resolvedText, maxWidth, line -> {
|
var lines = StringUtil.splitIntoParts(resolvedText, maxWidth, line -> {
|
||||||
int width = 0;
|
int width = 0;
|
||||||
for (var glyph: theme.getFont().translate(firstLineProperties.height(), firstLineProperties.ascent(), line)) {
|
width += MinecraftFont.translate(firstLineProperties.height(), firstLineProperties.ascent(), line).width();
|
||||||
width += glyph.width();
|
|
||||||
}
|
|
||||||
return width;
|
return width;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -381,27 +385,25 @@ public class DialogueRenderer extends Inventory {
|
|||||||
var text = lines[lineIdx];
|
var text = lines[lineIdx];
|
||||||
|
|
||||||
var properties = new TextureProperties(firstLineProperties.height(), firstLineProperties.ascent() - lineIdx * (fontHeight + 1));
|
var properties = new TextureProperties(firstLineProperties.height(), firstLineProperties.ascent() - lineIdx * (fontHeight + 1));
|
||||||
textLines.add(new TextLine(theme, text, properties));
|
textLines.add(new TextLine(theme, ((TextComponent) text).content(), properties));
|
||||||
}
|
}
|
||||||
return textLines;
|
return textLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderText(GlyphComponentBuilder builder, int shift) {
|
private void renderText(GlyphComponentBuilder builder, int shift) {
|
||||||
var positions = DialogGlyphPositions.DEFAULT;
|
|
||||||
|
|
||||||
var textLines = breakIntoLines(
|
var textLines = breakIntoLines(
|
||||||
text,
|
text,
|
||||||
positions.phraseText().firstLineProperties(),
|
GlyphPositions.phraseText.firstLineProperties(),
|
||||||
positions.phraseText().fontHeight(),
|
GlyphPositions.phraseText.fontHeight(),
|
||||||
positions.phraseText().lineWidth());
|
GlyphPositions.phraseText.lineWidth());
|
||||||
maxLines = textLines.size();
|
maxLines = textLines.size();
|
||||||
|
|
||||||
for (int lineIdx = shift; (lineIdx - shift) < Math.min(textLines.size() - shift, positions.phraseText().maxLines()); lineIdx++) {
|
for (int lineIdx = shift; (lineIdx - shift) < Math.min(textLines.size() - shift, GlyphPositions.phraseText.maxLines()); lineIdx++) {
|
||||||
var line = textLines.get(lineIdx);
|
var line = textLines.get(lineIdx);
|
||||||
builder.append(positions.phraseText().lineX(), line.toGlyphList(
|
builder.append(GlyphPositions.phraseText.lineX(), line.toGlyphList(
|
||||||
line.textureProperties(),
|
line.textureProperties(),
|
||||||
shift,
|
shift,
|
||||||
textLines.size() - lineIdx > 0 && lineIdx - shift == positions.phraseText().maxLines() - 1,
|
textLines.size() - lineIdx > 0 && lineIdx - shift == GlyphPositions.phraseText.maxLines() - 1,
|
||||||
getTheme().getColorText()
|
getTheme().getColorText()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -436,23 +438,22 @@ public class DialogueRenderer extends Inventory {
|
|||||||
onAnswerClick.put(buttonNumber, onClick);
|
onAnswerClick.put(buttonNumber, onClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
private record TextLine(DialogueTheme theme, Component text, TextureProperties textureProperties) {
|
private record TextLine(DialogueTheme theme, String text, TextureProperties textureProperties) {
|
||||||
|
|
||||||
public List<@NotNull AppendableGlyph> toGlyphList(TextureProperties parentProperties, int lineShift, boolean cutEnding, TextColor color) {
|
public GlyphComponent toGlyphList(TextureProperties parentProperties, int lineShift, boolean cutEnding, TextColor color) {
|
||||||
var properties = new TextureProperties(
|
var properties = new TextureProperties(
|
||||||
parentProperties.height(),
|
parentProperties.height(),
|
||||||
parentProperties.ascent() + lineShift * (textureProperties().height() + 1)
|
parentProperties.ascent() + lineShift * (textureProperties().height() + 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
Component text = this.text;
|
Component text = Component.text(this.text);
|
||||||
if (cutEnding) text = StringUtil.cutEnding(text, " <...>");
|
if (cutEnding) text = StringUtil.cutEnding(text, " <...>");
|
||||||
text = text.applyFallbackStyle(Style.style(color));
|
|
||||||
|
|
||||||
return toList((TextComponent) text, properties);
|
return toList(((TextComponent) text).content(), properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AppendableGlyph> toList(TextComponent text, TextureProperties properties) {
|
private MinecraftFont.Text toList(String text, TextureProperties properties) {
|
||||||
return theme.getFont().translate(properties.height(), properties.ascent(), text);
|
return MinecraftFont.translate(properties.height(), properties.ascent(), text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,11 +11,9 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
|||||||
import net.kyori.adventure.text.format.TextColor;
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import net.minestom.server.sound.SoundEvent;
|
import net.minestom.server.sound.SoundEvent;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.multicharacter.LanguageGlyphCollection;
|
|
||||||
import ru.dragonestia.msb3.api.resource.DialogueResources;
|
import ru.dragonestia.msb3.api.resource.DialogueResources;
|
||||||
import ru.dragonestia.msb3.api.resource.dialog.*;
|
import ru.dragonestia.msb3.api.resource.dialog.*;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@ -24,28 +22,24 @@ import java.util.function.Consumer;
|
|||||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class DialogueTheme {
|
public class DialogueTheme {
|
||||||
|
|
||||||
private final DialogueResources resources = ServerBootstrap.getInstance().getResourcePackManager().getDialogueResources();
|
|
||||||
|
|
||||||
private final DialogGlyphPositions positions;
|
|
||||||
private final Background background;
|
private final Background background;
|
||||||
private final Substrate substrate;
|
private final Substrate substrate;
|
||||||
private final ImageGlyph avatar;
|
private final GlyphImage avatar;
|
||||||
private final ImageGlyph avatarFrame;
|
private final GlyphImage avatarFrame;
|
||||||
private final ImageGlyph scrollTextUp;
|
private final GlyphImage scrollTextUp;
|
||||||
private final ImageGlyph scrollTextDown;
|
private final GlyphImage scrollTextDown;
|
||||||
private final ImageGlyph activeTextField1;
|
private final GlyphImage activeTextField1;
|
||||||
private final ImageGlyph activeTextField2;
|
private final GlyphImage activeTextField2;
|
||||||
private final ImageGlyph activeTextField3;
|
private final GlyphImage activeTextField3;
|
||||||
private final ImageGlyph activeTextField4;
|
private final GlyphImage activeTextField4;
|
||||||
private final ImageGlyph notActiveTextField1;
|
private final GlyphImage notActiveTextField1;
|
||||||
private final ImageGlyph notActiveTextField2;
|
private final GlyphImage notActiveTextField2;
|
||||||
private final ImageGlyph notActiveTextField3;
|
private final GlyphImage notActiveTextField3;
|
||||||
private final ImageGlyph notActiveTextField4;
|
private final GlyphImage notActiveTextField4;
|
||||||
private final ImageGlyph button1;
|
private final GlyphImage button1;
|
||||||
private final ImageGlyph button2;
|
private final GlyphImage button2;
|
||||||
private final ImageGlyph button3;
|
private final GlyphImage button3;
|
||||||
private final ImageGlyph button4;
|
private final GlyphImage button4;
|
||||||
private final LanguageGlyphCollection font;
|
|
||||||
private final Component textScrollUp;
|
private final Component textScrollUp;
|
||||||
private final Component textScrollDown;
|
private final Component textScrollDown;
|
||||||
private final Component textPrefixAnswer;
|
private final Component textPrefixAnswer;
|
||||||
@ -59,8 +53,6 @@ public class DialogueTheme {
|
|||||||
|
|
||||||
public Builder toBuilder() {
|
public Builder toBuilder() {
|
||||||
return new Builder(
|
return new Builder(
|
||||||
resources,
|
|
||||||
positions,
|
|
||||||
background,
|
background,
|
||||||
substrate,
|
substrate,
|
||||||
avatar,
|
avatar,
|
||||||
@ -79,7 +71,6 @@ public class DialogueTheme {
|
|||||||
button2,
|
button2,
|
||||||
button3,
|
button3,
|
||||||
button4,
|
button4,
|
||||||
font,
|
|
||||||
textScrollUp,
|
textScrollUp,
|
||||||
textScrollDown,
|
textScrollDown,
|
||||||
textPrefixAnswer,
|
textPrefixAnswer,
|
||||||
@ -94,38 +85,30 @@ public class DialogueTheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return builder(DialogGlyphPositions.DEFAULT);
|
return new Builder();
|
||||||
}
|
|
||||||
|
|
||||||
public static Builder builder(DialogGlyphPositions positions) {
|
|
||||||
return new Builder(positions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
@Getter private final DialogueResources resources;
|
|
||||||
private final DialogGlyphPositions positions;
|
|
||||||
|
|
||||||
private Background background;
|
private Background background;
|
||||||
private Substrate substrate;
|
private Substrate substrate;
|
||||||
private ImageGlyph avatar;
|
private GlyphImage avatar;
|
||||||
private ImageGlyph avatarFrame;
|
private GlyphImage avatarFrame;
|
||||||
private ImageGlyph scrollTextUp;
|
private GlyphImage scrollTextUp;
|
||||||
private ImageGlyph scrollTextDown;
|
private GlyphImage scrollTextDown;
|
||||||
private ImageGlyph activeTextField1;
|
private GlyphImage activeTextField1;
|
||||||
private ImageGlyph activeTextField2;
|
private GlyphImage activeTextField2;
|
||||||
private ImageGlyph activeTextField3;
|
private GlyphImage activeTextField3;
|
||||||
private ImageGlyph activeTextField4;
|
private GlyphImage activeTextField4;
|
||||||
private ImageGlyph notActiveTextField1;
|
private GlyphImage notActiveTextField1;
|
||||||
private ImageGlyph notActiveTextField2;
|
private GlyphImage notActiveTextField2;
|
||||||
private ImageGlyph notActiveTextField3;
|
private GlyphImage notActiveTextField3;
|
||||||
private ImageGlyph notActiveTextField4;
|
private GlyphImage notActiveTextField4;
|
||||||
private ImageGlyph button1;
|
private GlyphImage button1;
|
||||||
private ImageGlyph button2;
|
private GlyphImage button2;
|
||||||
private ImageGlyph button3;
|
private GlyphImage button3;
|
||||||
private ImageGlyph button4;
|
private GlyphImage button4;
|
||||||
private LanguageGlyphCollection font;
|
|
||||||
private Component textScrollUp;
|
private Component textScrollUp;
|
||||||
private Component textScrollDown;
|
private Component textScrollDown;
|
||||||
private Component textPrefixAnswer;
|
private Component textPrefixAnswer;
|
||||||
@ -137,31 +120,27 @@ public class DialogueTheme {
|
|||||||
private TextColor colorAnswerText4;
|
private TextColor colorAnswerText4;
|
||||||
private Consumer<Player> onScrollText;
|
private Consumer<Player> onScrollText;
|
||||||
|
|
||||||
private Builder(DialogGlyphPositions positions) {
|
private Builder() {}
|
||||||
resources = ServerBootstrap.getInstance().getResourcePackManager().getDialogueResources();
|
|
||||||
this.positions = positions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DialogueTheme build() {
|
public DialogueTheme build() {
|
||||||
if (background == null) setBackground(resources.getBackground(DialogueResources.DEFAULT).orElseThrow());
|
if (background == null) setBackground(DialogueResources.getBackground(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (substrate == null) setSubstrate(resources.getSubstrate(DialogueResources.DEFAULT).orElseThrow());
|
if (substrate == null) setSubstrate(DialogueResources.getSubstrate(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (avatar == null) setAvatar(resources.getAvatar(DialogueResources.DEFAULT).orElseThrow());
|
if (avatar == null) setAvatar(DialogueResources.getAvatar(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (avatarFrame == null) setAvatarFrame(resources.getAvatarFrame(DialogueResources.DEFAULT).orElseThrow());
|
if (avatarFrame == null) setAvatarFrame(DialogueResources.getAvatarFrame(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (scrollTextUp == null) setScrollTextUp(resources.getScrollUp(DialogueResources.DEFAULT).orElseThrow());
|
if (scrollTextUp == null) setScrollTextUp(DialogueResources.getScrollUp(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (scrollTextDown == null) setScrollTextDown(resources.getScrollDown(DialogueResources.DEFAULT).orElseThrow());
|
if (scrollTextDown == null) setScrollTextDown(DialogueResources.getScrollDown(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (font == null) setFont(resources.getFont(DialogueResources.DEFAULT).orElseThrow());
|
if (activeTextField1 == null) setActiveTextField(ButtonNumber.BUTTON_1, DialogueResources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (activeTextField1 == null) setActiveTextField(ButtonNumber.BUTTON_1, resources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
if (activeTextField2 == null) setActiveTextField(ButtonNumber.BUTTON_2, DialogueResources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (activeTextField2 == null) setActiveTextField(ButtonNumber.BUTTON_2, resources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
if (activeTextField3 == null) setActiveTextField(ButtonNumber.BUTTON_3, DialogueResources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (activeTextField3 == null) setActiveTextField(ButtonNumber.BUTTON_3, resources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
if (activeTextField4 == null) setActiveTextField(ButtonNumber.BUTTON_4, DialogueResources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (activeTextField4 == null) setActiveTextField(ButtonNumber.BUTTON_4, resources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
if (notActiveTextField1 == null) setNotActiveTextField(ButtonNumber.BUTTON_1, DialogueResources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (notActiveTextField1 == null) setNotActiveTextField(ButtonNumber.BUTTON_1, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
if (notActiveTextField2 == null) setNotActiveTextField(ButtonNumber.BUTTON_2, DialogueResources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (notActiveTextField2 == null) setNotActiveTextField(ButtonNumber.BUTTON_2, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
if (notActiveTextField3 == null) setNotActiveTextField(ButtonNumber.BUTTON_3, DialogueResources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (notActiveTextField3 == null) setNotActiveTextField(ButtonNumber.BUTTON_3, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
if (notActiveTextField4 == null) setNotActiveTextField(ButtonNumber.BUTTON_4, DialogueResources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||||
if (notActiveTextField4 == null) setNotActiveTextField(ButtonNumber.BUTTON_4, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
if (button1 == null) setButton(ButtonNumber.BUTTON_1, DialogueResources.getButton(DialogueResources.DEFAULT + 1).orElseThrow());
|
||||||
if (button1 == null) setButton(ButtonNumber.BUTTON_1, resources.getButton(DialogueResources.DEFAULT + 1).orElseThrow());
|
if (button2 == null) setButton(ButtonNumber.BUTTON_2, DialogueResources.getButton(DialogueResources.DEFAULT + 2).orElseThrow());
|
||||||
if (button2 == null) setButton(ButtonNumber.BUTTON_2, resources.getButton(DialogueResources.DEFAULT + 2).orElseThrow());
|
if (button3 == null) setButton(ButtonNumber.BUTTON_3, DialogueResources.getButton(DialogueResources.DEFAULT + 3).orElseThrow());
|
||||||
if (button3 == null) setButton(ButtonNumber.BUTTON_3, resources.getButton(DialogueResources.DEFAULT + 3).orElseThrow());
|
if (button4 == null) setButton(ButtonNumber.BUTTON_4, DialogueResources.getButton(DialogueResources.DEFAULT + 4).orElseThrow());
|
||||||
if (button4 == null) setButton(ButtonNumber.BUTTON_4, resources.getButton(DialogueResources.DEFAULT + 4).orElseThrow());
|
|
||||||
if (textScrollUp == null) setTextScrollUp(
|
if (textScrollUp == null) setTextScrollUp(
|
||||||
Component.text()
|
Component.text()
|
||||||
.append(Component.text("Нажмите сюда чтобы пролистать", NamedTextColor.YELLOW))
|
.append(Component.text("Нажмите сюда чтобы пролистать", NamedTextColor.YELLOW))
|
||||||
@ -195,7 +174,6 @@ public class DialogueTheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new DialogueTheme(
|
return new DialogueTheme(
|
||||||
positions,
|
|
||||||
background,
|
background,
|
||||||
substrate,
|
substrate,
|
||||||
avatar,
|
avatar,
|
||||||
@ -214,7 +192,6 @@ public class DialogueTheme {
|
|||||||
button2,
|
button2,
|
||||||
button3,
|
button3,
|
||||||
button4,
|
button4,
|
||||||
font,
|
|
||||||
textScrollUp,
|
textScrollUp,
|
||||||
textScrollDown,
|
textScrollDown,
|
||||||
textPrefixAnswer,
|
textPrefixAnswer,
|
||||||
@ -238,31 +215,26 @@ public class DialogueTheme {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setAvatar(ImageGlyph avatar) {
|
public Builder setAvatar(GlyphImage avatar) {
|
||||||
this.avatar = avatar;
|
this.avatar = avatar;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setAvatarFrame(ImageGlyph avatarFrame) {
|
public Builder setAvatarFrame(GlyphImage avatarFrame) {
|
||||||
this.avatarFrame = avatarFrame;
|
this.avatarFrame = avatarFrame;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setScrollTextUp(ImageGlyph scrollTextUp) {
|
public Builder setScrollTextUp(GlyphImage scrollTextUp) {
|
||||||
this.scrollTextUp = scrollTextUp;
|
this.scrollTextUp = scrollTextUp;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setScrollTextDown(ImageGlyph scrollTextDown) {
|
public Builder setScrollTextDown(GlyphImage scrollTextDown) {
|
||||||
this.scrollTextDown = scrollTextDown;
|
this.scrollTextDown = scrollTextDown;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setFont(LanguageGlyphCollection font) {
|
|
||||||
this.font = font;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setActiveTextField(ButtonNumber number, TextField field) {
|
public Builder setActiveTextField(ButtonNumber number, TextField field) {
|
||||||
switch (number) {
|
switch (number) {
|
||||||
case BUTTON_1 -> activeTextField1 = field.get(number);
|
case BUTTON_1 -> activeTextField1 = field.get(number);
|
||||||
|
|||||||
@ -4,9 +4,9 @@ import net.kyori.adventure.text.Component;
|
|||||||
import net.kyori.adventure.text.format.Style;
|
import net.kyori.adventure.text.format.Style;
|
||||||
import net.kyori.adventure.text.format.TextDecoration;
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
import ru.dragonestia.msb3.api.resource.MonologueResources;
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.GlyphComponentBuilder;
|
|
||||||
import ru.dragonestia.msb3.api.util.StringUtil;
|
import ru.dragonestia.msb3.api.util.StringUtil;
|
||||||
|
import ru.dragonestia.msb3.resource.glyph.GlyphComponentBuilder;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -37,8 +37,7 @@ public final class Monologue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Component toComponent(MonologueTheme theme) {
|
private Component toComponent(MonologueTheme theme) {
|
||||||
var spaces = ServerBootstrap.getInstance().getResourcePackManager().getGlyphResourcePack().spaces();
|
var speech = MonologueResources.getSpeechIndicator();
|
||||||
var speech = ServerBootstrap.getInstance().getResourcePackManager().getMonologueResources().getSpeechIndicator();
|
|
||||||
|
|
||||||
Component text = Component.text(message);
|
Component text = Component.text(message);
|
||||||
Component[] parts = StringUtil.splitIntoParts(text, 180, string -> string.length() * 4);
|
Component[] parts = StringUtil.splitIntoParts(text, 180, string -> string.length() * 4);
|
||||||
@ -46,13 +45,13 @@ public final class Monologue {
|
|||||||
int avatarLineStart = Math.max(parts.length - 4, 0) / 2;
|
int avatarLineStart = Math.max(parts.length - 4, 0) / 2;
|
||||||
if (parts.length > 3) ++avatarLineStart;
|
if (parts.length > 3) ++avatarLineStart;
|
||||||
|
|
||||||
var avatarComponent = GlyphComponentBuilder.universal(spaces)
|
var avatarComponent = new GlyphComponentBuilder()
|
||||||
.append(Objects.requireNonNull(theme.getFrame()))
|
.append(Objects.requireNonNull(theme.getFrame()))
|
||||||
.append(4, Objects.requireNonNull(theme.getAvatar()))
|
.append(4, Objects.requireNonNull(theme.getAvatar()))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
var titleComponent = Component.empty()
|
var titleComponent = Component.empty()
|
||||||
.append(speech.toAdventure())
|
.append(speech.component())
|
||||||
.append(Component.space()).append(Component.text(title, theme.getTitleColor(), TextDecoration.BOLD));
|
.append(Component.space()).append(Component.text(title, theme.getTitleColor(), TextDecoration.BOLD));
|
||||||
|
|
||||||
var monolog = Component.text();
|
var monolog = Component.text();
|
||||||
|
|||||||
@ -6,10 +6,8 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.resource.MonologueResources;
|
import ru.dragonestia.msb3.api.resource.MonologueResources;
|
||||||
import ru.dragonestia.msb3.api.resource.ResourcePackManager;
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -18,14 +16,13 @@ import java.util.Objects;
|
|||||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class MonologueTheme {
|
public class MonologueTheme {
|
||||||
|
|
||||||
private final ResourcePackManager resourcePackManager = ServerBootstrap.getInstance().getResourcePackManager();
|
private final GlyphImage avatar;
|
||||||
private final ImageGlyph avatar;
|
private final GlyphImage frame;
|
||||||
private final ImageGlyph frame;
|
|
||||||
private final TextColor titleColor;
|
private final TextColor titleColor;
|
||||||
private final TextColor textColor;
|
private final TextColor textColor;
|
||||||
|
|
||||||
public MonologueTheme withAvatar(String identifier) {
|
public MonologueTheme withAvatar(String identifier) {
|
||||||
var opt = resourcePackManager.getMonologueResources().getAvatar(identifier);
|
var opt = MonologueResources.getAvatar(identifier);
|
||||||
if (opt.isPresent()) {
|
if (opt.isPresent()) {
|
||||||
return withAvatar(opt.get());
|
return withAvatar(opt.get());
|
||||||
}
|
}
|
||||||
@ -35,7 +32,7 @@ public class MonologueTheme {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MonologueTheme withAvatar(ImageGlyph avatar) {
|
public MonologueTheme withAvatar(GlyphImage avatar) {
|
||||||
return new MonologueTheme(avatar, frame, titleColor, textColor);
|
return new MonologueTheme(avatar, frame, titleColor, textColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,16 +42,12 @@ public class MonologueTheme {
|
|||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private final ResourcePackManager resourcePackManager;
|
private GlyphImage avatar = null;
|
||||||
|
private GlyphImage frame = null;
|
||||||
private ImageGlyph avatar = null;
|
|
||||||
private ImageGlyph frame = null;
|
|
||||||
private TextColor titleColor = null;
|
private TextColor titleColor = null;
|
||||||
private TextColor textColor = null;
|
private TextColor textColor = null;
|
||||||
|
|
||||||
private Builder() {
|
private Builder() {}
|
||||||
resourcePackManager = ServerBootstrap.getInstance().getResourcePackManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MonologueTheme build() {
|
public MonologueTheme build() {
|
||||||
if (avatar == null) {
|
if (avatar == null) {
|
||||||
@ -80,18 +73,18 @@ public class MonologueTheme {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setAvatar(ImageGlyph avatar) {
|
public Builder setAvatar(GlyphImage avatar) {
|
||||||
this.avatar = avatar;
|
this.avatar = avatar;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setFrame(ImageGlyph frame) {
|
public Builder setFrame(GlyphImage frame) {
|
||||||
this.frame = frame;
|
this.frame = frame;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setAvatar(String identifier) {
|
public Builder setAvatar(String identifier) {
|
||||||
var opt = resourcePackManager.getMonologueResources().getAvatar(identifier);
|
var opt = MonologueResources.getAvatar(identifier);
|
||||||
if (opt.isPresent()) {
|
if (opt.isPresent()) {
|
||||||
avatar = Objects.requireNonNull(opt.get());
|
avatar = Objects.requireNonNull(opt.get());
|
||||||
return this;
|
return this;
|
||||||
@ -102,7 +95,7 @@ public class MonologueTheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Builder setFrame(String identifier) {
|
public Builder setFrame(String identifier) {
|
||||||
var opt = resourcePackManager.getMonologueResources().getFrame(identifier);
|
var opt = MonologueResources.getFrame(identifier);
|
||||||
if (opt.isPresent()) {
|
if (opt.isPresent()) {
|
||||||
frame = Objects.requireNonNull(opt.get());
|
frame = Objects.requireNonNull(opt.get());
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@ -1,35 +1,28 @@
|
|||||||
package ru.dragonestia.msb3.api.title;
|
package ru.dragonestia.msb3.api.title;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.title.Title;
|
import net.kyori.adventure.title.Title;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
|
||||||
import ru.dragonestia.msb3.api.glyph.glyph.image.TextureProperties;
|
|
||||||
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
||||||
import team.unnamed.creative.base.Writable;
|
import ru.dragonestia.msb3.resource.Resources;
|
||||||
import team.unnamed.creative.texture.Texture;
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class BlackScreen {
|
public class BlackScreen {
|
||||||
|
|
||||||
private static final Writable BACKGROUND_WRITABLE = ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/defaults/fullscreen_background.png");
|
public final GlyphImage glyph = Resources.createGlyph(
|
||||||
private static final Key FULLSCREEN_BACKGROUND_KEY = Key.key(Glyph.DEFAULT_NAMESPACE, "fullscreen_background.png");
|
Key.key("msb3", "black_screen"),
|
||||||
public static final ImageGlyph GLYPH = fullscreenBackgroundGlyph();
|
ResourceFromJar.of("glyphs/defaults/fullscreen_background.png"),
|
||||||
|
2500,
|
||||||
private BlackScreen() {}
|
256
|
||||||
|
);
|
||||||
|
|
||||||
public static void show(Player player) {
|
public static void show(Player player) {
|
||||||
player.showTitle(Title.title(
|
player.showTitle(Title.title(
|
||||||
GLYPH.toAdventure(),
|
glyph.component(),
|
||||||
Component.empty()
|
Component.empty()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ImageGlyph fullscreenBackgroundGlyph() {
|
|
||||||
return ImageGlyph.of(FULLSCREEN_BACKGROUND_KEY,
|
|
||||||
Texture.texture(FULLSCREEN_BACKGROUND_KEY, BACKGROUND_WRITABLE),
|
|
||||||
new TextureProperties(2500, 256));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
package ru.dragonestia.msb3.api.util;
|
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import team.unnamed.creative.base.Writable;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class ImageUtil {
|
|
||||||
|
|
||||||
public Writable imageToWritable(BufferedImage image) {
|
|
||||||
try {
|
|
||||||
return imageToWritable0(image);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Writable imageToWritable0(BufferedImage image) throws Exception {
|
|
||||||
try (var stream = new ByteArrayOutputStream()) {
|
|
||||||
ImageIO.write(image, "png", stream);
|
|
||||||
return Writable.bytes(stream.toByteArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package ru.dragonestia.msb3.api.util;
|
package ru.dragonestia.msb3.api.util;
|
||||||
|
|
||||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
import ru.dragonestia.msb3.api.boot.ServerBootstrap;
|
||||||
import team.unnamed.creative.base.Writable;
|
import team.unnamed.creative.base.Writable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package ru.dragonestia.msb3.resource;
|
package ru.dragonestia.msb3.resource;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||||
@ -18,8 +19,8 @@ import java.util.HashMap;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public final class Resources {
|
public final class Resources {
|
||||||
|
|
||||||
private final ResourcePack resourcePack = init();
|
@Getter private final ResourcePack resourcePack = init();
|
||||||
private final Font.Builder defaultFont = Font.font();
|
@Getter private final Font.Builder defaultFont = Font.font();
|
||||||
private final GlyphRegistry glyphs = new GlyphRegistry(resourcePack, defaultFont);
|
private final GlyphRegistry glyphs = new GlyphRegistry(resourcePack, defaultFont);
|
||||||
|
|
||||||
private boolean compiled = false;
|
private boolean compiled = false;
|
||||||
@ -69,14 +70,15 @@ public final class Resources {
|
|||||||
* @param writableTexture Объект с текстурой, предоставляемый ресурс-паку
|
* @param writableTexture Объект с текстурой, предоставляемый ресурс-паку
|
||||||
* @param height Высота глифа
|
* @param height Высота глифа
|
||||||
* @param ascent Смещение глифа по высоте
|
* @param ascent Смещение глифа по высоте
|
||||||
|
* @return Объект глифа
|
||||||
* @throws IllegalStateException Глиф был создан после компиляции ресурс-пака
|
* @throws IllegalStateException Глиф был создан после компиляции ресурс-пака
|
||||||
*/
|
*/
|
||||||
public void createGlyph(Key key, Writable writableTexture, int height, int ascent) throws IllegalStateException {
|
public GlyphImage createGlyph(Key key, Writable writableTexture, int height, int ascent) throws IllegalStateException {
|
||||||
if (compiled) {
|
if (compiled) {
|
||||||
throw new IllegalStateException("Resources already compiled");
|
throw new IllegalStateException("Resources already compiled");
|
||||||
}
|
}
|
||||||
|
|
||||||
glyphs.register(key, writableTexture, height, ascent);
|
return glyphs.register(key, writableTexture, height, ascent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package ru.dragonestia.msb3.resource.glyph;
|
package ru.dragonestia.msb3.resource.glyph;
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.Style;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -74,35 +77,57 @@ public class GlyphComponentBuilder {
|
|||||||
* @return Текстовый компонент
|
* @return Текстовый компонент
|
||||||
*/
|
*/
|
||||||
public Component build(boolean resetPosition) {
|
public Component build(boolean resetPosition) {
|
||||||
var builder = Component.text();
|
var sb = new StringBuilder();
|
||||||
|
var text = buildAsGlyphComponent();
|
||||||
|
|
||||||
|
sb.append(text.content());
|
||||||
|
if (resetPosition) {
|
||||||
|
sb.append(Spacing.getAsString(-text.width()));
|
||||||
|
}
|
||||||
|
|
||||||
|
var style = Style.style()
|
||||||
|
.color(NamedTextColor.WHITE)
|
||||||
|
.decoration(TextDecoration.ITALIC, false)
|
||||||
|
.decoration(TextDecoration.BOLD, false)
|
||||||
|
.decoration(TextDecoration.UNDERLINED, false)
|
||||||
|
.decoration(TextDecoration.STRIKETHROUGH, false)
|
||||||
|
.decoration(TextDecoration.OBFUSCATED, false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return Component.text(sb.toString(), style);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Собрать все компоненты глифов в один компонент глифа
|
||||||
|
* @return Компонент глифа
|
||||||
|
*/
|
||||||
|
public GlyphComponent buildAsGlyphComponent() {
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
for (var entry: entries) {
|
for (var entry: entries) {
|
||||||
Component component = entry.glyphComponent().component();
|
var component = entry.glyphComponent;
|
||||||
var val = entry.offset();
|
var val = entry.offset;
|
||||||
switch (entry.position()) {
|
switch (entry.position) {
|
||||||
case ABSOLUTE -> {
|
case ABSOLUTE -> {
|
||||||
builder.append(Spacing.get(val - offset));
|
builder.append(Spacing.getAsString(val - offset));
|
||||||
offset = val;
|
offset = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RELATIVE -> {
|
case RELATIVE -> {
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
builder.append(Spacing.get(val));
|
builder.append(Spacing.getAsString(val));
|
||||||
}
|
}
|
||||||
offset += val;
|
offset += val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offset += entry.glyphComponent().width();
|
|
||||||
builder.append(component);
|
offset += entry.glyphComponent.width() + 1;
|
||||||
|
builder.append(component.content());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resetPosition) {
|
return new Text(builder.toString(), offset);
|
||||||
builder.append(Spacing.get(-offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private record Entry(Position position, int offset, GlyphComponent glyphComponent) {}
|
private record Entry(Position position, int offset, GlyphComponent glyphComponent) {}
|
||||||
|
|||||||
@ -10,9 +10,7 @@ import team.unnamed.creative.font.Font;
|
|||||||
import team.unnamed.creative.font.FontProvider;
|
import team.unnamed.creative.font.FontProvider;
|
||||||
import team.unnamed.creative.texture.Texture;
|
import team.unnamed.creative.texture.Texture;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class GlyphRegistry {
|
public class GlyphRegistry {
|
||||||
|
|
||||||
@ -25,13 +23,16 @@ public class GlyphRegistry {
|
|||||||
public GlyphRegistry(ResourcePack resourcePack, Font.Builder defaultFont) {
|
public GlyphRegistry(ResourcePack resourcePack, Font.Builder defaultFont) {
|
||||||
this.resourcePack = resourcePack;
|
this.resourcePack = resourcePack;
|
||||||
this.defaultFont = defaultFont;
|
this.defaultFont = defaultFont;
|
||||||
|
|
||||||
|
precompileSpacing();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void precompileSpacing() {
|
||||||
|
defaultFont.key(Font.MINECRAFT_DEFAULT);
|
||||||
|
defaultFont.addProvider(FontProvider.reference(Spacing.compile(resourcePack)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void compile() {
|
public void compile() {
|
||||||
defaultFont.key(Font.MINECRAFT_DEFAULT);
|
|
||||||
|
|
||||||
defaultFont.addProvider(FontProvider.reference(Spacing.compile(resourcePack)));
|
|
||||||
|
|
||||||
for (var fontBuilder: glyphFonts.values()) {
|
for (var fontBuilder: glyphFonts.values()) {
|
||||||
var font = fontBuilder.build();
|
var font = fontBuilder.build();
|
||||||
|
|
||||||
@ -44,7 +45,8 @@ public class GlyphRegistry {
|
|||||||
|
|
||||||
public void compileAtlases(Map<String, Atlas.Builder> atlases) {
|
public void compileAtlases(Map<String, Atlas.Builder> atlases) {
|
||||||
for (var holder: glyphs.values()) {
|
for (var holder: glyphs.values()) {
|
||||||
var key = holder.texture().key();
|
for (var texture: holder.textures()) {
|
||||||
|
var key = texture.key();
|
||||||
|
|
||||||
var atlas = atlases.computeIfAbsent(key.namespace(), identifier -> {
|
var atlas = atlases.computeIfAbsent(key.namespace(), identifier -> {
|
||||||
var obj = Atlas.atlas();
|
var obj = Atlas.atlas();
|
||||||
@ -55,8 +57,9 @@ public class GlyphRegistry {
|
|||||||
atlas.addSource(AtlasSource.single(Key.key(key.namespace(), key.value().replace(".png", ""))));
|
atlas.addSource(AtlasSource.single(Key.key(key.namespace(), key.value().replace(".png", ""))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void register(Key key, Writable writableTexture, int height, int ascent) {
|
public GlyphImage register(Key key, Writable writableTexture, int height, int ascent) {
|
||||||
var font = glyphFonts.computeIfAbsent(key.namespace(), namespace -> {
|
var font = glyphFonts.computeIfAbsent(key.namespace(), namespace -> {
|
||||||
var obj = Font.font();
|
var obj = Font.font();
|
||||||
obj.key(Key.key(namespace, "glyphs_font"));
|
obj.key(Key.key(namespace, "glyphs_font"));
|
||||||
@ -65,7 +68,6 @@ public class GlyphRegistry {
|
|||||||
|
|
||||||
var character = GlyphCharacterFactory.takeFreeCharacter();
|
var character = GlyphCharacterFactory.takeFreeCharacter();
|
||||||
var image = ImageUtils.imageFromWritable(writableTexture);
|
var image = ImageUtils.imageFromWritable(writableTexture);
|
||||||
// TODO: split image when resolution biggest than 256x256 on any axis
|
|
||||||
|
|
||||||
var texture = Texture.texture()
|
var texture = Texture.texture()
|
||||||
.key(Key.key(key.namespace(), "glyphs/" + key.value() + ".png"))
|
.key(Key.key(key.namespace(), "glyphs/" + key.value() + ".png"))
|
||||||
@ -89,9 +91,10 @@ public class GlyphRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var glyph = new GlyphImage(Character.toString(character), height, wight, ascent);
|
var glyph = new GlyphImage(Character.toString(character), height, wight, ascent);
|
||||||
var holder = new GlyphResourceHolder(key, glyph, texture);
|
var holder = new GlyphResourceHolder(key, glyph, List.of(texture));
|
||||||
|
|
||||||
glyphs.put(key, holder);
|
glyphs.put(key, holder);
|
||||||
|
return holder.glyph();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlyphImage getGlyph(Key key) {
|
public GlyphImage getGlyph(Key key) {
|
||||||
|
|||||||
@ -3,4 +3,6 @@ package ru.dragonestia.msb3.resource.glyph;
|
|||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import team.unnamed.creative.texture.Texture;
|
import team.unnamed.creative.texture.Texture;
|
||||||
|
|
||||||
public record GlyphResourceHolder(Key key, GlyphImage glyph, Texture texture) {}
|
import java.util.List;
|
||||||
|
|
||||||
|
public record GlyphResourceHolder(Key key, GlyphImage glyph, List<Texture> textures) {}
|
||||||
|
|||||||
@ -199,7 +199,7 @@ public final class MinecraftFont {
|
|||||||
|
|
||||||
private Text(String content, int length) {
|
private Text(String content, int length) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.length = length;
|
this.length = length -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -61,7 +61,7 @@ public class Spacing {
|
|||||||
var spacingChar = map.get(index);
|
var spacingChar = map.get(index);
|
||||||
|
|
||||||
if (spacingChar == null) {
|
if (spacingChar == null) {
|
||||||
throw new IllegalArgumentException("Unsupported spacing depth: %s".formatted(currentDepth));
|
throw new IllegalArgumentException("Unsupported spacing depth: %s (index=%s)".formatted(currentDepth, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(spacingChar);
|
sb.append(spacingChar);
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
package ru.dragonestia.msb3.resource.utils;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class ClassPreLoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Предварительная загрузка класса. Сделано для того, чтобы инициализировать статические поля классов.
|
||||||
|
*
|
||||||
|
* <p>Реализация решения проблемы, когда регистрация глифа происходит в статическом финальном поле класса.
|
||||||
|
* Java не загружает все статические поля при старте программы, а только в тот момент, когда идет первое
|
||||||
|
* обращение к классу.
|
||||||
|
*
|
||||||
|
* <p> Пример:
|
||||||
|
* <blockquote><pre>
|
||||||
|
* class BlackScreen {
|
||||||
|
* public static final GlyphImage GLYPH = Resources.createGlyph(
|
||||||
|
* Key.key("msb3", "black_screen"),
|
||||||
|
* ResourceFromJar.of("glyphs/defaults/fullscreen_background.png"),
|
||||||
|
* 2500,
|
||||||
|
* 256
|
||||||
|
* );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Место, где инициализируются глифы
|
||||||
|
* void initializeGlyphs() {
|
||||||
|
* ClassPreLoader.preload(BlackScreen.class);
|
||||||
|
* }
|
||||||
|
* </pre></blockquote>
|
||||||
|
* @param clazz Предварительно загружаемый класс
|
||||||
|
*/
|
||||||
|
public void preload(Class<?> clazz) {
|
||||||
|
try {
|
||||||
|
Class.forName(clazz.getName());
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import team.unnamed.creative.base.Writable;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
@ -18,4 +19,19 @@ public class ImageUtils {
|
|||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Writable imageToWritable(BufferedImage image) {
|
||||||
|
try {
|
||||||
|
return imageToWritable0(image);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Writable imageToWritable0(BufferedImage image) throws Exception {
|
||||||
|
try (var stream = new ByteArrayOutputStream()) {
|
||||||
|
ImageIO.write(image, "png", stream);
|
||||||
|
return Writable.bytes(stream.toByteArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user