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.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
||||
import ru.dragonestia.msb3.api.glyph.glyph.Glyph;
|
||||
import ru.dragonestia.msb3.api.boot.ServerBootstrap;
|
||||
import ru.dragonestia.msb3.api.util.ResourceFromJar;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.model.*;
|
||||
@ -32,7 +31,7 @@ public class BlankSlotItem {
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
Model blankSlotModel = Model.model()
|
||||
@ -52,7 +51,7 @@ public class BlankSlotItem {
|
||||
.overrides(ItemOverride.of(modelKey, ItemPredicate.customModelData(1)))
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
package ru.dragonestia.msb3.api.item;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
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 java.util.HashMap;
|
||||
@ -9,12 +10,11 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Log4j2
|
||||
@UtilityClass
|
||||
public final class ItemPrefabManager {
|
||||
|
||||
private final Map<String, ItemPrefab> prefabs = new HashMap<>();
|
||||
|
||||
public ItemPrefabManager() {}
|
||||
|
||||
public synchronized void register(ItemPrefab prefab) {
|
||||
if (ServerBootstrap.isStarted()) {
|
||||
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.minestom.server.item.ItemStack;
|
||||
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.function.Supplier;
|
||||
@ -22,12 +22,12 @@ public class ItemPrefab {
|
||||
}
|
||||
|
||||
public static Optional<ItemPrefab> of(String identifier) {
|
||||
return ServerBootstrap.getInstance().getItemPrefabManager().getPrefab(identifier);
|
||||
return ItemPrefabManager.getPrefab(identifier);
|
||||
}
|
||||
|
||||
public static Optional<ItemPrefab> of(ItemStack item) {
|
||||
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() {
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package ru.dragonestia.msb3.api.module;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.kyori.adventure.resource.ResourcePackCallback;
|
||||
import net.kyori.adventure.resource.ResourcePackInfo;
|
||||
import net.kyori.adventure.resource.ResourcePackRequest;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.event.player.PlayerSpawnEvent;
|
||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
||||
import team.unnamed.creative.BuiltResourcePack;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.server.ResourcePackServer;
|
||||
@ -22,19 +22,16 @@ import java.util.UUID;
|
||||
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
|
||||
@UtilityClass
|
||||
public class ResourcePackRepositoryModule {
|
||||
|
||||
private static boolean used = false;
|
||||
|
||||
private ResourcePackRepositoryModule() {}
|
||||
private boolean used = false;
|
||||
|
||||
@SneakyThrows
|
||||
public static synchronized void init(ServerBootstrap bootstrap, String address, int port) {
|
||||
public synchronized void init(String address, int port) {
|
||||
if (used) return;
|
||||
used = true;
|
||||
|
||||
bootstrap.getResourcePackManager().compile();
|
||||
|
||||
var file = new File("./resource-pack.zip");
|
||||
var hash = calculateHash(file);
|
||||
var uuid = UUID.randomUUID();
|
||||
@ -59,7 +56,7 @@ public class ResourcePackRepositoryModule {
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private static String calculateHash(File file) {
|
||||
private String calculateHash(File file) {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||
|
||||
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();
|
||||
for (byte b: hash) formatter.format("%02x", b);
|
||||
return formatter.toString();
|
||||
|
||||
@ -1,21 +1,12 @@
|
||||
package ru.dragonestia.msb3.api.resource;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import ru.dragonestia.msb3.api.glyph.font.GlyphFont;
|
||||
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
|
||||
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.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 ru.dragonestia.msb3.api.resource.dialog.*;
|
||||
import ru.dragonestia.msb3.resource.Resources;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||
import ru.dragonestia.msb3.resource.utils.ImageUtils;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
@ -24,95 +15,59 @@ import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@UtilityClass
|
||||
public class DialogueResources {
|
||||
|
||||
private static final Key DIALOGUE_FONT_KEY = Key.key("msb3", "dialog");
|
||||
public static final String DEFAULT = "default";
|
||||
|
||||
private final GlyphResourcePack glyphResourcePack;
|
||||
private final Map<String, GlyphEntry> avatars = new HashMap<>();
|
||||
private final Map<String, GlyphEntry> avatarFrames = new HashMap<>();
|
||||
private final Map<String, GlyphEntry> scrollUp = new HashMap<>();
|
||||
private final Map<String, GlyphEntry> scrollDown = new HashMap<>();
|
||||
private final Map<String, GlyphImage> avatars = new HashMap<>();
|
||||
private final Map<String, GlyphImage> avatarFrames = new HashMap<>();
|
||||
private final Map<String, GlyphImage> scrollUp = new HashMap<>();
|
||||
private final Map<String, GlyphImage> scrollDown = new HashMap<>();
|
||||
private final Map<String, Background> backgrounds = 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, TextField> activeFields = 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) {
|
||||
registerAvatar(identifier, writable, DialogGlyphPositions.DEFAULT);
|
||||
}
|
||||
|
||||
public void registerAvatar(String identifier, Writable writable, DialogGlyphPositions positions) {
|
||||
var glyph = createGlyph(identifier, writable, "avatar", positions.avatar().height(), positions.avatar().y());
|
||||
var glyphIdentifier = StringIdentifier.image("dialog_avatar__" + identifier);
|
||||
avatars.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
||||
avatars.put(identifier, Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/avatar/" + identifier),
|
||||
writable,
|
||||
GlyphPositions.avatar.height(),
|
||||
GlyphPositions.avatar.y()
|
||||
));
|
||||
}
|
||||
|
||||
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) {
|
||||
var glyph = createGlyph(identifier, writable, "avatar_frame", positions.avatar().frameHeight(), positions.avatar().y() + positions.avatar().frameBorderSize());
|
||||
var glyphIdentifier = StringIdentifier.image("dialog_avatar_frame__" + identifier);
|
||||
avatarFrames.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
||||
public void registerScrollUp(String identifier, Writable writable) {
|
||||
scrollUp.put(identifier, Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/scroll_up/" + identifier),
|
||||
writable,
|
||||
GlyphPositions.scrollPhraseButton.height(),
|
||||
GlyphPositions.scrollPhraseButton.buttonY()
|
||||
));
|
||||
}
|
||||
|
||||
public void registerScrollTextUp(String identifier, Writable writable) {
|
||||
registerScrollTextUp(identifier, writable, DialogGlyphPositions.DEFAULT);
|
||||
}
|
||||
|
||||
public void registerScrollTextUp(String identifier, Writable writable, DialogGlyphPositions positions) {
|
||||
var glyph = createGlyph(identifier, writable, "scroll_up", positions.scrollPhraseButton().height(), positions.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 registerScrollDown(String identifier, Writable writable) {
|
||||
scrollDown.put(identifier, Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/scroll_down/" + identifier),
|
||||
writable,
|
||||
GlyphPositions.scrollPhraseButton.height(),
|
||||
GlyphPositions.scrollPhraseButton.buttonY()
|
||||
));
|
||||
}
|
||||
|
||||
public void registerBackground(String identifier, Writable writable) {
|
||||
registerBackground(identifier, writable, DialogGlyphPositions.DEFAULT);
|
||||
}
|
||||
|
||||
public void registerBackground(String identifier, Writable writable, DialogGlyphPositions positions) {
|
||||
BufferedImage image;
|
||||
Writable part1;
|
||||
Writable part2;
|
||||
@ -124,43 +79,43 @@ public class DialogueResources {
|
||||
var w = image.getWidth();
|
||||
var h = image.getHeight();
|
||||
|
||||
part1 = ImageUtil.imageToWritable(image.getSubimage(0, 0, w / 2, h / 2));
|
||||
part2 = ImageUtil.imageToWritable(image.getSubimage(w / 2, 0, w / 2, h / 2));
|
||||
part3 = ImageUtil.imageToWritable(image.getSubimage(0, h / 2, w / 2, h / 2));
|
||||
part4 = ImageUtil.imageToWritable(image.getSubimage(w / 2, h / 2, w / 2, h / 2));
|
||||
part1 = ImageUtils.imageToWritable(image.getSubimage(0, 0, w / 2, h / 2));
|
||||
part2 = ImageUtils.imageToWritable(image.getSubimage(w / 2, 0, w / 2, h / 2));
|
||||
part3 = ImageUtils.imageToWritable(image.getSubimage(0, h / 2, w / 2, h / 2));
|
||||
part4 = ImageUtils.imageToWritable(image.getSubimage(w / 2, h / 2, w / 2, h / 2));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
var glyph1 = new GlyphEntry(
|
||||
StringIdentifier.image("dialog_background1__" + identifier),
|
||||
createGlyph(identifier, part1, "background1", positions.guiBackground().height() / 2, positions.guiBackground().topPartsY())
|
||||
var glyph1 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/background/" + identifier + "__1"),
|
||||
part1,
|
||||
GlyphPositions.guiBackground.height() / 2,
|
||||
GlyphPositions.guiBackground.topPartsY()
|
||||
);
|
||||
var glyph2 = new GlyphEntry(
|
||||
StringIdentifier.image("dialog_background2__" + identifier),
|
||||
createGlyph(identifier, part2, "background2", positions.guiBackground().height() / 2, positions.guiBackground().topPartsY())
|
||||
var glyph2 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/background/" + identifier + "__2"),
|
||||
part2,
|
||||
GlyphPositions.guiBackground.height() / 2,
|
||||
GlyphPositions.guiBackground.topPartsY()
|
||||
);
|
||||
var glyph3 = new GlyphEntry(
|
||||
StringIdentifier.image("dialog_background3__" + identifier),
|
||||
createGlyph(identifier, part3, "background3", positions.guiBackground().height() / 2, positions.guiBackground().bottomPartsY())
|
||||
var glyph3 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/background/" + identifier + "__3"),
|
||||
part3,
|
||||
GlyphPositions.guiBackground.height() / 2,
|
||||
GlyphPositions.guiBackground.bottomPartsY()
|
||||
);
|
||||
var glyph4 = new GlyphEntry(
|
||||
StringIdentifier.image("dialog_background4__" + identifier),
|
||||
createGlyph(identifier, part4, "background4", positions.guiBackground().height() / 2, positions.guiBackground().bottomPartsY())
|
||||
var glyph4 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/background/" + identifier + "__4"),
|
||||
part4,
|
||||
GlyphPositions.guiBackground.height() / 2,
|
||||
GlyphPositions.guiBackground.bottomPartsY()
|
||||
);
|
||||
|
||||
backgrounds.put(identifier, new Background(glyph1.glyph(), glyph2.glyph(), glyph3.glyph(), glyph4.glyph()));
|
||||
glyphResourcePack.with(glyph1.identifier(), glyph1.glyph());
|
||||
glyphResourcePack.with(glyph2.identifier(), glyph2.glyph());
|
||||
glyphResourcePack.with(glyph3.identifier(), glyph3.glyph());
|
||||
glyphResourcePack.with(glyph4.identifier(), glyph4.glyph());
|
||||
backgrounds.put(identifier, new Background(glyph1, glyph2, glyph3, glyph4));
|
||||
}
|
||||
|
||||
public void registerSubstrate(String identifier, Writable writable) {
|
||||
registerSubstrate(identifier, writable, DialogGlyphPositions.DEFAULT);
|
||||
}
|
||||
|
||||
public void registerSubstrate(String identifier, Writable writable, DialogGlyphPositions positions) {
|
||||
BufferedImage image;
|
||||
Writable part1;
|
||||
Writable part2;
|
||||
@ -170,168 +125,129 @@ public class DialogueResources {
|
||||
var w = image.getWidth();
|
||||
var h = image.getHeight();
|
||||
|
||||
part1 = ImageUtil.imageToWritable(image.getSubimage(0, 0, w / 2, h));
|
||||
part2 = ImageUtil.imageToWritable(image.getSubimage(w / 2, 0, w / 2, h));
|
||||
part1 = ImageUtils.imageToWritable(image.getSubimage(0, 0, w / 2, h));
|
||||
part2 = ImageUtils.imageToWritable(image.getSubimage(w / 2, 0, w / 2, h));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
var glyph1 = new GlyphEntry(
|
||||
StringIdentifier.image("dialog_substrate1__" + identifier),
|
||||
createGlyph(identifier, part1, "substrate1", positions.phraseSubstrate().height(), positions.phraseSubstrate().y())
|
||||
var glyph1 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/substrate/" + identifier + "__1"),
|
||||
part1,
|
||||
GlyphPositions.phraseSubstrate.height(),
|
||||
GlyphPositions.phraseSubstrate.y()
|
||||
);
|
||||
var glyph2 = new GlyphEntry(
|
||||
StringIdentifier.image("dialog_substrate2__" + identifier),
|
||||
createGlyph(identifier, part2, "substrate2", positions.phraseSubstrate().height(), positions.phraseSubstrate().y())
|
||||
var glyph2 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/substrate/" + identifier + "__2"),
|
||||
part2,
|
||||
GlyphPositions.phraseSubstrate.height(),
|
||||
GlyphPositions.phraseSubstrate.y()
|
||||
);
|
||||
|
||||
substrates.put(identifier, new Substrate(glyph1.glyph(), glyph2.glyph()));
|
||||
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);
|
||||
substrates.put(identifier, new Substrate(glyph1, glyph2));
|
||||
}
|
||||
|
||||
public void registerButton(String identifier, Writable writable) {
|
||||
registerButton(identifier, writable, DialogGlyphPositions.DEFAULT);
|
||||
}
|
||||
|
||||
public void registerButton(String identifier, Writable writable, DialogGlyphPositions positions) {
|
||||
var glyph1 = createGlyph(identifier,
|
||||
var glyph1 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/button/" + identifier),
|
||||
writable,
|
||||
"button1",
|
||||
positions.answerButton().height(),
|
||||
positions.answerButton().topButtonY());
|
||||
var glyph2 = createGlyph(identifier,
|
||||
GlyphPositions.answerButton.height(),
|
||||
GlyphPositions.answerButton.topButtonY()
|
||||
);
|
||||
var glyph2 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/button/" + identifier),
|
||||
writable,
|
||||
"button2",
|
||||
positions.answerButton().height(),
|
||||
positions.answerButton().topButtonY());
|
||||
var glyph3 = createGlyph(identifier,
|
||||
GlyphPositions.answerButton.height(),
|
||||
GlyphPositions.answerButton.topButtonY()
|
||||
);
|
||||
var glyph3 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/button/" + identifier),
|
||||
writable,
|
||||
"button3",
|
||||
positions.answerButton().height(),
|
||||
positions.answerButton().bottomButtonY());
|
||||
var glyph4 = createGlyph(identifier,
|
||||
GlyphPositions.answerButton.height(),
|
||||
GlyphPositions.answerButton.bottomButtonY()
|
||||
);
|
||||
var glyph4 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/button/" + identifier),
|
||||
writable,
|
||||
"button4",
|
||||
positions.answerButton().height(),
|
||||
positions.answerButton().bottomButtonY());
|
||||
GlyphPositions.answerButton.height(),
|
||||
GlyphPositions.answerButton.bottomButtonY()
|
||||
);
|
||||
|
||||
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) {
|
||||
registerActiveTextField(identifier, writable, DialogGlyphPositions.DEFAULT);
|
||||
}
|
||||
|
||||
public void registerActiveTextField(String identifier, Writable writable, DialogGlyphPositions positions) {
|
||||
var glyph1 = createGlyph(identifier,
|
||||
var glyph1 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/text_field/" + identifier),
|
||||
writable,
|
||||
"active_field1",
|
||||
positions.answerField().height(),
|
||||
positions.answerField().topFieldY());
|
||||
var glyph2 = createGlyph(identifier,
|
||||
GlyphPositions.answerField.height(),
|
||||
GlyphPositions.answerField.topFieldY()
|
||||
);
|
||||
var glyph2 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/text_field/" + identifier),
|
||||
writable,
|
||||
"active_field2",
|
||||
positions.answerField().height(),
|
||||
positions.answerField().topFieldY());
|
||||
var glyph3 = createGlyph(identifier,
|
||||
GlyphPositions.answerField.height(),
|
||||
GlyphPositions.answerField.topFieldY()
|
||||
);
|
||||
var glyph3 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/text_field/" + identifier),
|
||||
writable,
|
||||
"active_field3",
|
||||
positions.answerField().height(),
|
||||
positions.answerField().bottomFieldY());
|
||||
var glyph4 = createGlyph(identifier,
|
||||
GlyphPositions.answerField.height(),
|
||||
GlyphPositions.answerField.bottomFieldY()
|
||||
);
|
||||
var glyph4 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/text_field/" + identifier),
|
||||
writable,
|
||||
"active_field4",
|
||||
positions.answerField().height(),
|
||||
positions.answerField().bottomFieldY());
|
||||
GlyphPositions.answerField.height(),
|
||||
GlyphPositions.answerField.bottomFieldY()
|
||||
);
|
||||
|
||||
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) {
|
||||
registerNotActiveTextField(identifier, writable, DialogGlyphPositions.DEFAULT);
|
||||
}
|
||||
|
||||
public void registerNotActiveTextField(String identifier, Writable writable, DialogGlyphPositions positions) {
|
||||
var glyph1 = createGlyph(identifier,
|
||||
var glyph1 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/inactive_text_field/" + identifier),
|
||||
writable,
|
||||
"not_active_field1",
|
||||
positions.answerField().height(),
|
||||
positions.answerField().topFieldY());
|
||||
var glyph2 = createGlyph(identifier,
|
||||
GlyphPositions.answerField.height(),
|
||||
GlyphPositions.answerField.topFieldY()
|
||||
);
|
||||
var glyph2 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/inactive_text_field/" + identifier),
|
||||
writable,
|
||||
"not_active_field2",
|
||||
positions.answerField().height(),
|
||||
positions.answerField().topFieldY());
|
||||
var glyph3 = createGlyph(identifier,
|
||||
GlyphPositions.answerField.height(),
|
||||
GlyphPositions.answerField.topFieldY()
|
||||
);
|
||||
var glyph3 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/inactive_text_field/" + identifier),
|
||||
writable,
|
||||
"not_active_field3",
|
||||
positions.answerField().height(),
|
||||
positions.answerField().bottomFieldY());
|
||||
var glyph4 = createGlyph(identifier,
|
||||
GlyphPositions.answerField.height(),
|
||||
GlyphPositions.answerField.bottomFieldY()
|
||||
);
|
||||
var glyph4 = Resources.createGlyph(
|
||||
Key.key("msb3", "dialogue/inactive_text_field/" + identifier),
|
||||
writable,
|
||||
"not_active_field4",
|
||||
positions.answerField().height(),
|
||||
positions.answerField().bottomFieldY());
|
||||
GlyphPositions.answerField.height(),
|
||||
GlyphPositions.answerField.bottomFieldY()
|
||||
);
|
||||
|
||||
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) {
|
||||
return getGlyphFromMap(identifier, avatars);
|
||||
public Optional<GlyphImage> getAvatar(String identifier) {
|
||||
return Optional.ofNullable(avatars.get(identifier));
|
||||
}
|
||||
|
||||
public Optional<ImageGlyph> getAvatarFrame(String identifier) {
|
||||
return getGlyphFromMap(identifier, avatarFrames);
|
||||
public Optional<GlyphImage> getAvatarFrame(String identifier) {
|
||||
return Optional.ofNullable(avatarFrames.get(identifier));
|
||||
}
|
||||
|
||||
public Optional<ImageGlyph> getScrollUp(String identifier) {
|
||||
return getGlyphFromMap(identifier, scrollUp);
|
||||
public Optional<GlyphImage> getScrollUp(String identifier) {
|
||||
return Optional.ofNullable(scrollUp.get(identifier));
|
||||
}
|
||||
|
||||
public Optional<ImageGlyph> getScrollDown(String identifier) {
|
||||
return getGlyphFromMap(identifier, scrollDown);
|
||||
public Optional<GlyphImage> getScrollDown(String identifier) {
|
||||
return Optional.ofNullable(scrollDown.get(identifier));
|
||||
}
|
||||
|
||||
public Optional<Background> getBackground(String identifier) {
|
||||
@ -342,10 +258,6 @@ public class DialogueResources {
|
||||
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) {
|
||||
return Optional.ofNullable(buttons.get(identifier));
|
||||
}
|
||||
@ -357,21 +269,4 @@ public class DialogueResources {
|
||||
public Optional<TextField> getNotActiveTextField(String 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;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.UtilityClass;
|
||||
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.resource.Resources;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@UtilityClass
|
||||
public class MonologueResources {
|
||||
|
||||
private static final Key MONOLOG_FONT_KEY = Key.key("msb3", "monolog");
|
||||
public static final String DEFAULT = "default";
|
||||
|
||||
private final GlyphResourcePack glyphResourcePack;
|
||||
private final Map<String, GlyphEntry> avatars = new HashMap<>();
|
||||
private final Map<String, GlyphEntry> frames = new HashMap<>();
|
||||
private final GlyphEntry speechIndicator = initSpeechIndicator();
|
||||
|
||||
public MonologueResources(GlyphResourcePack glyphResourcePack) {
|
||||
this.glyphResourcePack = glyphResourcePack;
|
||||
|
||||
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);
|
||||
}
|
||||
private final Map<String, GlyphImage> avatars = new HashMap<>();
|
||||
private final Map<String, GlyphImage> frames = new HashMap<>();
|
||||
@Getter private static final GlyphImage speechIndicator = Resources.createGlyph(
|
||||
Key.key("msb3", "monologue/speech_indicator"),
|
||||
ResourceFromJar.of("glyphs/monologue/speech_indicator.png"),
|
||||
8,
|
||||
6
|
||||
);
|
||||
|
||||
public void registerAvatar(String identifier, Writable writable) {
|
||||
var glyph = ImageGlyph.of(MONOLOG_FONT_KEY,
|
||||
Texture.texture().key(Key.key("msb3", "monolog/avatar_" + identifier + ".png")).data(writable).build(),
|
||||
new TextureProperties(42, 2));
|
||||
var glyph = Resources.createGlyph(
|
||||
Key.key("msb3", "monologue/avatar/" + identifier),
|
||||
writable,
|
||||
42,
|
||||
2
|
||||
);
|
||||
|
||||
var glyphIdentifier = StringIdentifier.image("monolog_avatar_" + identifier);
|
||||
|
||||
avatars.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
||||
|
||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
||||
avatars.put(identifier, glyph);
|
||||
}
|
||||
|
||||
public void registerFrame(String identifier, Writable writable) {
|
||||
var glyph = ImageGlyph.of(MONOLOG_FONT_KEY,
|
||||
Texture.texture().key(Key.key("msb3", "monolog/frame_" + identifier + ".png")).data(writable).build(),
|
||||
new TextureProperties(50, 6));
|
||||
var glyph = Resources.createGlyph(
|
||||
Key.key("msb3", "monologue/frame/" + identifier),
|
||||
writable,
|
||||
50,
|
||||
6
|
||||
);
|
||||
|
||||
var glyphIdentifier = StringIdentifier.image("monolog_frame_" + identifier);
|
||||
|
||||
frames.put(identifier, new GlyphEntry(glyphIdentifier, glyph));
|
||||
|
||||
glyphResourcePack.with(glyphIdentifier, glyph);
|
||||
frames.put(identifier, glyph);
|
||||
}
|
||||
|
||||
public Optional<ImageGlyph> getAvatar(String identifier) {
|
||||
return Optional.ofNullable(avatars.get(identifier))
|
||||
.map(entry -> {
|
||||
try {
|
||||
return glyphResourcePack.get(entry.identifier());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
public Optional<GlyphImage> getAvatar(String identifier) {
|
||||
return Optional.ofNullable(avatars.get(identifier));
|
||||
}
|
||||
|
||||
public Optional<ImageGlyph> getFrame(String 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());
|
||||
public Optional<GlyphImage> getFrame(String identifier) {
|
||||
return Optional.ofNullable(frames.get(identifier));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
case BUTTON_1 -> button1;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
case BUTTON_1 -> field1;
|
||||
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) {}
|
||||
@ -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 org.apache.commons.text.WordUtils;
|
||||
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.ItemUtil;
|
||||
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.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.EnumMap;
|
||||
@ -42,7 +43,6 @@ public class DialogueRenderer extends Inventory {
|
||||
public static final int CHEST_GUI_WIDTH = 176;
|
||||
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;
|
||||
@Getter @Setter private DialogueTheme theme;
|
||||
@Getter private String text = "";
|
||||
@ -74,15 +74,15 @@ public class DialogueRenderer extends Inventory {
|
||||
}
|
||||
|
||||
public void scrollDown() {
|
||||
if (maxLines > shifted + theme.getPositions().phraseText().maxLines()) {
|
||||
shifted = Math.min(maxLines - theme.getPositions().phraseText().maxLines(), shifted + 3);
|
||||
if (maxLines > shifted + GlyphPositions.phraseText.maxLines()) {
|
||||
shifted = Math.min(maxLines - GlyphPositions.phraseText.maxLines(), shifted + 3);
|
||||
}
|
||||
}
|
||||
|
||||
public void rerender() {
|
||||
setTitle(render());
|
||||
|
||||
var slots = getTheme().getPositions().chestSlotsButtons();
|
||||
var slots = GlyphPositions.chestSlotsButtons;
|
||||
|
||||
for (var slot: slots.scrollUp()) {
|
||||
if (shifted != 0) {
|
||||
@ -93,7 +93,7 @@ public class DialogueRenderer extends Inventory {
|
||||
}
|
||||
|
||||
for (var slot: slots.scrollDown()) {
|
||||
if (maxLines > shifted + theme.getPositions().phraseText().maxLines()) {
|
||||
if (maxLines > shifted + GlyphPositions.phraseText.maxLines()) {
|
||||
setSlotClickable(slot, null, ClickType.SCROLL_DOWN);
|
||||
} else {
|
||||
resetClickableSlot(slot);
|
||||
@ -267,7 +267,7 @@ public class DialogueRenderer extends Inventory {
|
||||
}
|
||||
|
||||
private Component render() {
|
||||
var builder = GlyphComponentBuilder.gui(glyphResourcePack.spaces());
|
||||
var builder = new GlyphComponentBuilder();
|
||||
|
||||
// GUI background
|
||||
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());
|
||||
|
||||
// Phrase substrate
|
||||
builder.append(theme.getPositions().phraseSubstrate().x(), theme.getSubstrate().part1());
|
||||
builder.append(theme.getPositions().phraseSubstrate().x() + theme.getPositions().phraseSubstrate().width() / 2, theme.getSubstrate().part2());
|
||||
builder.append(GlyphPositions.phraseSubstrate.x(), theme.getSubstrate().part1());
|
||||
builder.append(GlyphPositions.phraseSubstrate.x() + GlyphPositions.phraseSubstrate.width() / 2, theme.getSubstrate().part2());
|
||||
|
||||
// Frame and avatar
|
||||
builder.append(theme.getPositions().avatar().x() - 8, theme.getAvatarFrame());
|
||||
builder.append(theme.getPositions().avatar().x(), theme.getAvatar());
|
||||
builder.append(GlyphPositions.avatar.x() - 8, theme.getAvatarFrame());
|
||||
builder.append(GlyphPositions.avatar.x(), theme.getAvatar());
|
||||
|
||||
// Phrase text
|
||||
renderText(builder, shifted);
|
||||
@ -289,22 +289,24 @@ public class DialogueRenderer extends Inventory {
|
||||
// Scroll phrase buttons (optional)
|
||||
if (shifted != 0) {
|
||||
builder.append(
|
||||
theme.getPositions().scrollPhraseButton().scrollUpButtonX(),
|
||||
theme.getScrollTextUp());
|
||||
GlyphPositions.scrollPhraseButton.scrollUpButtonX(),
|
||||
theme.getScrollTextUp()
|
||||
);
|
||||
}
|
||||
|
||||
if (maxLines > shifted + theme.getPositions().phraseText().maxLines()) {
|
||||
if (maxLines > shifted + GlyphPositions.phraseText.maxLines()) {
|
||||
builder.append(
|
||||
theme.getPositions().scrollPhraseButton().scrollDownButtonX(),
|
||||
theme.getScrollTextDown());
|
||||
GlyphPositions.scrollPhraseButton.scrollDownButtonX(),
|
||||
theme.getScrollTextDown()
|
||||
);
|
||||
}
|
||||
|
||||
// Answers
|
||||
for (var number: ButtonNumber.values()) {
|
||||
if (buttonsText.containsKey(number)) {
|
||||
builder.append(number.getIndex() % 2 == 0
|
||||
? theme.getPositions().answerField().leftFieldX()
|
||||
: theme.getPositions().answerField().rightFieldX(),
|
||||
? GlyphPositions.answerField.leftFieldX()
|
||||
: GlyphPositions.answerField.rightFieldX(),
|
||||
switch (number) {
|
||||
case BUTTON_1 -> theme.getActiveTextField1();
|
||||
case BUTTON_2 -> theme.getActiveTextField2();
|
||||
@ -313,8 +315,8 @@ public class DialogueRenderer extends Inventory {
|
||||
});
|
||||
|
||||
builder.append(number.getIndex() % 2 == 0
|
||||
? theme.getPositions().answerButton().leftButtonX()
|
||||
: theme.getPositions().answerButton().rightButtonX(),
|
||||
? GlyphPositions.answerButton.leftButtonX()
|
||||
: GlyphPositions.answerButton.rightButtonX(),
|
||||
switch (number) {
|
||||
case BUTTON_1 -> theme.getButton1();
|
||||
case BUTTON_2 -> theme.getButton2();
|
||||
@ -325,19 +327,20 @@ public class DialogueRenderer extends Inventory {
|
||||
var lines = breakIntoLines(
|
||||
buttonsText.get(number),
|
||||
number.getIndex() < 2
|
||||
? new TextureProperties(theme.getPositions().answerText().fontHeight(), theme.getPositions().answerText().topFirstLineAscent())
|
||||
: new TextureProperties(theme.getPositions().answerText().fontHeight(), theme.getPositions().answerText().bottomFirstLineAscent()),
|
||||
theme.getPositions().answerText().fontHeight(),
|
||||
theme.getPositions().answerText().lineWidth());
|
||||
? new TextureProperties(GlyphPositions.answerText.fontHeight(), GlyphPositions.answerText.topFirstLineAscent())
|
||||
: new TextureProperties(GlyphPositions.answerText.fontHeight(), GlyphPositions.answerText.bottomFirstLineAscent()),
|
||||
GlyphPositions.answerText.fontHeight(),
|
||||
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);
|
||||
|
||||
builder.append(
|
||||
number.getIndex() % 2 == 0
|
||||
? theme.getPositions().answerText().leftLineX()
|
||||
: theme.getPositions().answerText().rightLineX(),
|
||||
? GlyphPositions.answerText.leftLineX()
|
||||
: GlyphPositions.answerText.rightLineX(),
|
||||
line.toGlyphList(line.textureProperties(), 0, endWithDots, switch (number) {
|
||||
case BUTTON_1 -> theme.getColorAnswerText1();
|
||||
case BUTTON_2 -> theme.getColorAnswerText2();
|
||||
@ -346,10 +349,12 @@ public class DialogueRenderer extends Inventory {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
builder.append(number.getIndex() % 2 == 0
|
||||
? theme.getPositions().answerField().leftFieldX()
|
||||
: theme.getPositions().answerField().rightFieldX(),
|
||||
? GlyphPositions.answerField.leftFieldX()
|
||||
: GlyphPositions.answerField.rightFieldX(),
|
||||
switch (number) {
|
||||
case BUTTON_1 -> theme.getNotActiveTextField1();
|
||||
case BUTTON_2 -> theme.getNotActiveTextField2();
|
||||
@ -362,13 +367,12 @@ public class DialogueRenderer extends Inventory {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
private List<TextLine> breakIntoLines(String input, TextureProperties firstLineProperties, int fontHeight, int maxWidth) throws IllegalStateException {
|
||||
var resolvedText = MiniMessage.miniMessage().deserialize(input);
|
||||
var lines = StringUtil.splitIntoParts(resolvedText, maxWidth, line -> {
|
||||
int width = 0;
|
||||
for (var glyph: theme.getFont().translate(firstLineProperties.height(), firstLineProperties.ascent(), line)) {
|
||||
width += glyph.width();
|
||||
}
|
||||
width += MinecraftFont.translate(firstLineProperties.height(), firstLineProperties.ascent(), line).width();
|
||||
return width;
|
||||
});
|
||||
|
||||
@ -381,27 +385,25 @@ public class DialogueRenderer extends Inventory {
|
||||
var text = lines[lineIdx];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private void renderText(GlyphComponentBuilder builder, int shift) {
|
||||
var positions = DialogGlyphPositions.DEFAULT;
|
||||
|
||||
var textLines = breakIntoLines(
|
||||
text,
|
||||
positions.phraseText().firstLineProperties(),
|
||||
positions.phraseText().fontHeight(),
|
||||
positions.phraseText().lineWidth());
|
||||
GlyphPositions.phraseText.firstLineProperties(),
|
||||
GlyphPositions.phraseText.fontHeight(),
|
||||
GlyphPositions.phraseText.lineWidth());
|
||||
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);
|
||||
builder.append(positions.phraseText().lineX(), line.toGlyphList(
|
||||
builder.append(GlyphPositions.phraseText.lineX(), line.toGlyphList(
|
||||
line.textureProperties(),
|
||||
shift,
|
||||
textLines.size() - lineIdx > 0 && lineIdx - shift == positions.phraseText().maxLines() - 1,
|
||||
textLines.size() - lineIdx > 0 && lineIdx - shift == GlyphPositions.phraseText.maxLines() - 1,
|
||||
getTheme().getColorText()
|
||||
));
|
||||
}
|
||||
@ -436,23 +438,22 @@ public class DialogueRenderer extends Inventory {
|
||||
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(
|
||||
parentProperties.height(),
|
||||
parentProperties.ascent() + lineShift * (textureProperties().height() + 1)
|
||||
);
|
||||
|
||||
Component text = this.text;
|
||||
Component text = Component.text(this.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) {
|
||||
return theme.getFont().translate(properties.height(), properties.ascent(), text);
|
||||
private MinecraftFont.Text toList(String text, TextureProperties properties) {
|
||||
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.minestom.server.entity.Player;
|
||||
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.dialog.*;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -24,28 +22,24 @@ import java.util.function.Consumer;
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class DialogueTheme {
|
||||
|
||||
private final DialogueResources resources = ServerBootstrap.getInstance().getResourcePackManager().getDialogueResources();
|
||||
|
||||
private final DialogGlyphPositions positions;
|
||||
private final Background background;
|
||||
private final Substrate substrate;
|
||||
private final ImageGlyph avatar;
|
||||
private final ImageGlyph avatarFrame;
|
||||
private final ImageGlyph scrollTextUp;
|
||||
private final ImageGlyph scrollTextDown;
|
||||
private final ImageGlyph activeTextField1;
|
||||
private final ImageGlyph activeTextField2;
|
||||
private final ImageGlyph activeTextField3;
|
||||
private final ImageGlyph activeTextField4;
|
||||
private final ImageGlyph notActiveTextField1;
|
||||
private final ImageGlyph notActiveTextField2;
|
||||
private final ImageGlyph notActiveTextField3;
|
||||
private final ImageGlyph notActiveTextField4;
|
||||
private final ImageGlyph button1;
|
||||
private final ImageGlyph button2;
|
||||
private final ImageGlyph button3;
|
||||
private final ImageGlyph button4;
|
||||
private final LanguageGlyphCollection font;
|
||||
private final GlyphImage avatar;
|
||||
private final GlyphImage avatarFrame;
|
||||
private final GlyphImage scrollTextUp;
|
||||
private final GlyphImage scrollTextDown;
|
||||
private final GlyphImage activeTextField1;
|
||||
private final GlyphImage activeTextField2;
|
||||
private final GlyphImage activeTextField3;
|
||||
private final GlyphImage activeTextField4;
|
||||
private final GlyphImage notActiveTextField1;
|
||||
private final GlyphImage notActiveTextField2;
|
||||
private final GlyphImage notActiveTextField3;
|
||||
private final GlyphImage notActiveTextField4;
|
||||
private final GlyphImage button1;
|
||||
private final GlyphImage button2;
|
||||
private final GlyphImage button3;
|
||||
private final GlyphImage button4;
|
||||
private final Component textScrollUp;
|
||||
private final Component textScrollDown;
|
||||
private final Component textPrefixAnswer;
|
||||
@ -59,8 +53,6 @@ public class DialogueTheme {
|
||||
|
||||
public Builder toBuilder() {
|
||||
return new Builder(
|
||||
resources,
|
||||
positions,
|
||||
background,
|
||||
substrate,
|
||||
avatar,
|
||||
@ -79,7 +71,6 @@ public class DialogueTheme {
|
||||
button2,
|
||||
button3,
|
||||
button4,
|
||||
font,
|
||||
textScrollUp,
|
||||
textScrollDown,
|
||||
textPrefixAnswer,
|
||||
@ -94,38 +85,30 @@ public class DialogueTheme {
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return builder(DialogGlyphPositions.DEFAULT);
|
||||
}
|
||||
|
||||
public static Builder builder(DialogGlyphPositions positions) {
|
||||
return new Builder(positions);
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class Builder {
|
||||
|
||||
@Getter private final DialogueResources resources;
|
||||
private final DialogGlyphPositions positions;
|
||||
|
||||
private Background background;
|
||||
private Substrate substrate;
|
||||
private ImageGlyph avatar;
|
||||
private ImageGlyph avatarFrame;
|
||||
private ImageGlyph scrollTextUp;
|
||||
private ImageGlyph scrollTextDown;
|
||||
private ImageGlyph activeTextField1;
|
||||
private ImageGlyph activeTextField2;
|
||||
private ImageGlyph activeTextField3;
|
||||
private ImageGlyph activeTextField4;
|
||||
private ImageGlyph notActiveTextField1;
|
||||
private ImageGlyph notActiveTextField2;
|
||||
private ImageGlyph notActiveTextField3;
|
||||
private ImageGlyph notActiveTextField4;
|
||||
private ImageGlyph button1;
|
||||
private ImageGlyph button2;
|
||||
private ImageGlyph button3;
|
||||
private ImageGlyph button4;
|
||||
private LanguageGlyphCollection font;
|
||||
private GlyphImage avatar;
|
||||
private GlyphImage avatarFrame;
|
||||
private GlyphImage scrollTextUp;
|
||||
private GlyphImage scrollTextDown;
|
||||
private GlyphImage activeTextField1;
|
||||
private GlyphImage activeTextField2;
|
||||
private GlyphImage activeTextField3;
|
||||
private GlyphImage activeTextField4;
|
||||
private GlyphImage notActiveTextField1;
|
||||
private GlyphImage notActiveTextField2;
|
||||
private GlyphImage notActiveTextField3;
|
||||
private GlyphImage notActiveTextField4;
|
||||
private GlyphImage button1;
|
||||
private GlyphImage button2;
|
||||
private GlyphImage button3;
|
||||
private GlyphImage button4;
|
||||
private Component textScrollUp;
|
||||
private Component textScrollDown;
|
||||
private Component textPrefixAnswer;
|
||||
@ -137,31 +120,27 @@ public class DialogueTheme {
|
||||
private TextColor colorAnswerText4;
|
||||
private Consumer<Player> onScrollText;
|
||||
|
||||
private Builder(DialogGlyphPositions positions) {
|
||||
resources = ServerBootstrap.getInstance().getResourcePackManager().getDialogueResources();
|
||||
this.positions = positions;
|
||||
}
|
||||
private Builder() {}
|
||||
|
||||
public DialogueTheme build() {
|
||||
if (background == null) setBackground(resources.getBackground(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (substrate == null) setSubstrate(resources.getSubstrate(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (avatar == null) setAvatar(resources.getAvatar(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (avatarFrame == null) setAvatarFrame(resources.getAvatarFrame(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (scrollTextUp == null) setScrollTextUp(resources.getScrollUp(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (scrollTextDown == null) setScrollTextDown(resources.getScrollDown(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (font == null) setFont(resources.getFont(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (activeTextField1 == null) setActiveTextField(ButtonNumber.BUTTON_1, resources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (activeTextField2 == null) setActiveTextField(ButtonNumber.BUTTON_2, resources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (activeTextField3 == null) setActiveTextField(ButtonNumber.BUTTON_3, resources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (activeTextField4 == null) setActiveTextField(ButtonNumber.BUTTON_4, resources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (notActiveTextField1 == null) setNotActiveTextField(ButtonNumber.BUTTON_1, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (notActiveTextField2 == null) setNotActiveTextField(ButtonNumber.BUTTON_2, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (notActiveTextField3 == null) setNotActiveTextField(ButtonNumber.BUTTON_3, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (notActiveTextField4 == null) setNotActiveTextField(ButtonNumber.BUTTON_4, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (button1 == null) setButton(ButtonNumber.BUTTON_1, resources.getButton(DialogueResources.DEFAULT + 1).orElseThrow());
|
||||
if (button2 == null) setButton(ButtonNumber.BUTTON_2, resources.getButton(DialogueResources.DEFAULT + 2).orElseThrow());
|
||||
if (button3 == null) setButton(ButtonNumber.BUTTON_3, resources.getButton(DialogueResources.DEFAULT + 3).orElseThrow());
|
||||
if (button4 == null) setButton(ButtonNumber.BUTTON_4, resources.getButton(DialogueResources.DEFAULT + 4).orElseThrow());
|
||||
if (background == null) setBackground(DialogueResources.getBackground(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (substrate == null) setSubstrate(DialogueResources.getSubstrate(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (avatar == null) setAvatar(DialogueResources.getAvatar(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (avatarFrame == null) setAvatarFrame(DialogueResources.getAvatarFrame(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (scrollTextUp == null) setScrollTextUp(DialogueResources.getScrollUp(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (scrollTextDown == null) setScrollTextDown(DialogueResources.getScrollDown(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (activeTextField1 == null) setActiveTextField(ButtonNumber.BUTTON_1, DialogueResources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (activeTextField2 == null) setActiveTextField(ButtonNumber.BUTTON_2, DialogueResources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (activeTextField3 == null) setActiveTextField(ButtonNumber.BUTTON_3, DialogueResources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (activeTextField4 == null) setActiveTextField(ButtonNumber.BUTTON_4, DialogueResources.getActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (notActiveTextField1 == null) setNotActiveTextField(ButtonNumber.BUTTON_1, DialogueResources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (notActiveTextField2 == null) setNotActiveTextField(ButtonNumber.BUTTON_2, DialogueResources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (notActiveTextField3 == null) setNotActiveTextField(ButtonNumber.BUTTON_3, DialogueResources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (notActiveTextField4 == null) setNotActiveTextField(ButtonNumber.BUTTON_4, DialogueResources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
|
||||
if (button1 == null) setButton(ButtonNumber.BUTTON_1, DialogueResources.getButton(DialogueResources.DEFAULT + 1).orElseThrow());
|
||||
if (button2 == null) setButton(ButtonNumber.BUTTON_2, DialogueResources.getButton(DialogueResources.DEFAULT + 2).orElseThrow());
|
||||
if (button3 == null) setButton(ButtonNumber.BUTTON_3, DialogueResources.getButton(DialogueResources.DEFAULT + 3).orElseThrow());
|
||||
if (button4 == null) setButton(ButtonNumber.BUTTON_4, DialogueResources.getButton(DialogueResources.DEFAULT + 4).orElseThrow());
|
||||
if (textScrollUp == null) setTextScrollUp(
|
||||
Component.text()
|
||||
.append(Component.text("Нажмите сюда чтобы пролистать", NamedTextColor.YELLOW))
|
||||
@ -195,7 +174,6 @@ public class DialogueTheme {
|
||||
}
|
||||
|
||||
return new DialogueTheme(
|
||||
positions,
|
||||
background,
|
||||
substrate,
|
||||
avatar,
|
||||
@ -214,7 +192,6 @@ public class DialogueTheme {
|
||||
button2,
|
||||
button3,
|
||||
button4,
|
||||
font,
|
||||
textScrollUp,
|
||||
textScrollDown,
|
||||
textPrefixAnswer,
|
||||
@ -238,31 +215,26 @@ public class DialogueTheme {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAvatar(ImageGlyph avatar) {
|
||||
public Builder setAvatar(GlyphImage avatar) {
|
||||
this.avatar = avatar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAvatarFrame(ImageGlyph avatarFrame) {
|
||||
public Builder setAvatarFrame(GlyphImage avatarFrame) {
|
||||
this.avatarFrame = avatarFrame;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setScrollTextUp(ImageGlyph scrollTextUp) {
|
||||
public Builder setScrollTextUp(GlyphImage scrollTextUp) {
|
||||
this.scrollTextUp = scrollTextUp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setScrollTextDown(ImageGlyph scrollTextDown) {
|
||||
public Builder setScrollTextDown(GlyphImage scrollTextDown) {
|
||||
this.scrollTextDown = scrollTextDown;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFont(LanguageGlyphCollection font) {
|
||||
this.font = font;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setActiveTextField(ButtonNumber number, TextField field) {
|
||||
switch (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.TextDecoration;
|
||||
import net.minestom.server.entity.Player;
|
||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
||||
import ru.dragonestia.msb3.api.glyph.glyph.GlyphComponentBuilder;
|
||||
import ru.dragonestia.msb3.api.resource.MonologueResources;
|
||||
import ru.dragonestia.msb3.api.util.StringUtil;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphComponentBuilder;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -37,8 +37,7 @@ public final class Monologue {
|
||||
}
|
||||
|
||||
private Component toComponent(MonologueTheme theme) {
|
||||
var spaces = ServerBootstrap.getInstance().getResourcePackManager().getGlyphResourcePack().spaces();
|
||||
var speech = ServerBootstrap.getInstance().getResourcePackManager().getMonologueResources().getSpeechIndicator();
|
||||
var speech = MonologueResources.getSpeechIndicator();
|
||||
|
||||
Component text = Component.text(message);
|
||||
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;
|
||||
if (parts.length > 3) ++avatarLineStart;
|
||||
|
||||
var avatarComponent = GlyphComponentBuilder.universal(spaces)
|
||||
var avatarComponent = new GlyphComponentBuilder()
|
||||
.append(Objects.requireNonNull(theme.getFrame()))
|
||||
.append(4, Objects.requireNonNull(theme.getAvatar()))
|
||||
.build();
|
||||
|
||||
var titleComponent = Component.empty()
|
||||
.append(speech.toAdventure())
|
||||
.append(speech.component())
|
||||
.append(Component.space()).append(Component.text(title, theme.getTitleColor(), TextDecoration.BOLD));
|
||||
|
||||
var monolog = Component.text();
|
||||
|
||||
@ -6,10 +6,8 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
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.ResourcePackManager;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -18,14 +16,13 @@ import java.util.Objects;
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class MonologueTheme {
|
||||
|
||||
private final ResourcePackManager resourcePackManager = ServerBootstrap.getInstance().getResourcePackManager();
|
||||
private final ImageGlyph avatar;
|
||||
private final ImageGlyph frame;
|
||||
private final GlyphImage avatar;
|
||||
private final GlyphImage frame;
|
||||
private final TextColor titleColor;
|
||||
private final TextColor textColor;
|
||||
|
||||
public MonologueTheme withAvatar(String identifier) {
|
||||
var opt = resourcePackManager.getMonologueResources().getAvatar(identifier);
|
||||
var opt = MonologueResources.getAvatar(identifier);
|
||||
if (opt.isPresent()) {
|
||||
return withAvatar(opt.get());
|
||||
}
|
||||
@ -35,7 +32,7 @@ public class MonologueTheme {
|
||||
return this;
|
||||
}
|
||||
|
||||
public MonologueTheme withAvatar(ImageGlyph avatar) {
|
||||
public MonologueTheme withAvatar(GlyphImage avatar) {
|
||||
return new MonologueTheme(avatar, frame, titleColor, textColor);
|
||||
}
|
||||
|
||||
@ -45,16 +42,12 @@ public class MonologueTheme {
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final ResourcePackManager resourcePackManager;
|
||||
|
||||
private ImageGlyph avatar = null;
|
||||
private ImageGlyph frame = null;
|
||||
private GlyphImage avatar = null;
|
||||
private GlyphImage frame = null;
|
||||
private TextColor titleColor = null;
|
||||
private TextColor textColor = null;
|
||||
|
||||
private Builder() {
|
||||
resourcePackManager = ServerBootstrap.getInstance().getResourcePackManager();
|
||||
}
|
||||
private Builder() {}
|
||||
|
||||
public MonologueTheme build() {
|
||||
if (avatar == null) {
|
||||
@ -80,18 +73,18 @@ public class MonologueTheme {
|
||||
);
|
||||
}
|
||||
|
||||
public Builder setAvatar(ImageGlyph avatar) {
|
||||
public Builder setAvatar(GlyphImage avatar) {
|
||||
this.avatar = avatar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFrame(ImageGlyph frame) {
|
||||
public Builder setFrame(GlyphImage frame) {
|
||||
this.frame = frame;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAvatar(String identifier) {
|
||||
var opt = resourcePackManager.getMonologueResources().getAvatar(identifier);
|
||||
var opt = MonologueResources.getAvatar(identifier);
|
||||
if (opt.isPresent()) {
|
||||
avatar = Objects.requireNonNull(opt.get());
|
||||
return this;
|
||||
@ -102,7 +95,7 @@ public class MonologueTheme {
|
||||
}
|
||||
|
||||
public Builder setFrame(String identifier) {
|
||||
var opt = resourcePackManager.getMonologueResources().getFrame(identifier);
|
||||
var opt = MonologueResources.getFrame(identifier);
|
||||
if (opt.isPresent()) {
|
||||
frame = Objects.requireNonNull(opt.get());
|
||||
return this;
|
||||
|
||||
@ -1,35 +1,28 @@
|
||||
package ru.dragonestia.msb3.api.title;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.title.Title;
|
||||
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 team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
import ru.dragonestia.msb3.resource.Resources;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||
|
||||
@UtilityClass
|
||||
public class BlackScreen {
|
||||
|
||||
private static final Writable BACKGROUND_WRITABLE = ResourceFromJar.of(ServerBootstrap.CLASS_LOADER, "glyphs/defaults/fullscreen_background.png");
|
||||
private static final Key FULLSCREEN_BACKGROUND_KEY = Key.key(Glyph.DEFAULT_NAMESPACE, "fullscreen_background.png");
|
||||
public static final ImageGlyph GLYPH = fullscreenBackgroundGlyph();
|
||||
|
||||
private BlackScreen() {}
|
||||
public final GlyphImage glyph = Resources.createGlyph(
|
||||
Key.key("msb3", "black_screen"),
|
||||
ResourceFromJar.of("glyphs/defaults/fullscreen_background.png"),
|
||||
2500,
|
||||
256
|
||||
);
|
||||
|
||||
public static void show(Player player) {
|
||||
player.showTitle(Title.title(
|
||||
GLYPH.toAdventure(),
|
||||
glyph.component(),
|
||||
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;
|
||||
|
||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
||||
import ru.dragonestia.msb3.api.boot.ServerBootstrap;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package ru.dragonestia.msb3.resource;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import ru.dragonestia.msb3.resource.glyph.GlyphImage;
|
||||
@ -18,8 +19,8 @@ import java.util.HashMap;
|
||||
@UtilityClass
|
||||
public final class Resources {
|
||||
|
||||
private final ResourcePack resourcePack = init();
|
||||
private final Font.Builder defaultFont = Font.font();
|
||||
@Getter private final ResourcePack resourcePack = init();
|
||||
@Getter private final Font.Builder defaultFont = Font.font();
|
||||
private final GlyphRegistry glyphs = new GlyphRegistry(resourcePack, defaultFont);
|
||||
|
||||
private boolean compiled = false;
|
||||
@ -69,14 +70,15 @@ public final class Resources {
|
||||
* @param writableTexture Объект с текстурой, предоставляемый ресурс-паку
|
||||
* @param height Высота глифа
|
||||
* @param ascent Смещение глифа по высоте
|
||||
* @return Объект глифа
|
||||
* @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) {
|
||||
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;
|
||||
|
||||
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.List;
|
||||
@ -74,35 +77,57 @@ public class GlyphComponentBuilder {
|
||||
* @return Текстовый компонент
|
||||
*/
|
||||
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;
|
||||
|
||||
for (var entry: entries) {
|
||||
Component component = entry.glyphComponent().component();
|
||||
var val = entry.offset();
|
||||
switch (entry.position()) {
|
||||
var component = entry.glyphComponent;
|
||||
var val = entry.offset;
|
||||
switch (entry.position) {
|
||||
case ABSOLUTE -> {
|
||||
builder.append(Spacing.get(val - offset));
|
||||
builder.append(Spacing.getAsString(val - offset));
|
||||
offset = val;
|
||||
}
|
||||
|
||||
case RELATIVE -> {
|
||||
if (val == 0) {
|
||||
builder.append(Spacing.get(val));
|
||||
builder.append(Spacing.getAsString(val));
|
||||
}
|
||||
offset += val;
|
||||
}
|
||||
}
|
||||
offset += entry.glyphComponent().width();
|
||||
builder.append(component);
|
||||
|
||||
offset += entry.glyphComponent.width() + 1;
|
||||
builder.append(component.content());
|
||||
}
|
||||
|
||||
if (resetPosition) {
|
||||
builder.append(Spacing.get(-offset));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
return new Text(builder.toString(), offset);
|
||||
}
|
||||
|
||||
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.texture.Texture;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
public class GlyphRegistry {
|
||||
|
||||
@ -25,13 +23,16 @@ public class GlyphRegistry {
|
||||
public GlyphRegistry(ResourcePack resourcePack, Font.Builder defaultFont) {
|
||||
this.resourcePack = resourcePack;
|
||||
this.defaultFont = defaultFont;
|
||||
|
||||
precompileSpacing();
|
||||
}
|
||||
|
||||
private void precompileSpacing() {
|
||||
defaultFont.key(Font.MINECRAFT_DEFAULT);
|
||||
defaultFont.addProvider(FontProvider.reference(Spacing.compile(resourcePack)));
|
||||
}
|
||||
|
||||
public void compile() {
|
||||
defaultFont.key(Font.MINECRAFT_DEFAULT);
|
||||
|
||||
defaultFont.addProvider(FontProvider.reference(Spacing.compile(resourcePack)));
|
||||
|
||||
for (var fontBuilder: glyphFonts.values()) {
|
||||
var font = fontBuilder.build();
|
||||
|
||||
@ -44,7 +45,8 @@ public class GlyphRegistry {
|
||||
|
||||
public void compileAtlases(Map<String, Atlas.Builder> atlases) {
|
||||
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 obj = Atlas.atlas();
|
||||
@ -55,8 +57,9 @@ public class GlyphRegistry {
|
||||
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 obj = Font.font();
|
||||
obj.key(Key.key(namespace, "glyphs_font"));
|
||||
@ -65,7 +68,6 @@ public class GlyphRegistry {
|
||||
|
||||
var character = GlyphCharacterFactory.takeFreeCharacter();
|
||||
var image = ImageUtils.imageFromWritable(writableTexture);
|
||||
// TODO: split image when resolution biggest than 256x256 on any axis
|
||||
|
||||
var texture = Texture.texture()
|
||||
.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 holder = new GlyphResourceHolder(key, glyph, texture);
|
||||
var holder = new GlyphResourceHolder(key, glyph, List.of(texture));
|
||||
|
||||
glyphs.put(key, holder);
|
||||
return holder.glyph();
|
||||
}
|
||||
|
||||
public GlyphImage getGlyph(Key key) {
|
||||
|
||||
@ -3,4 +3,6 @@ package ru.dragonestia.msb3.resource.glyph;
|
||||
import net.kyori.adventure.key.Key;
|
||||
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) {
|
||||
this.content = content;
|
||||
this.length = length;
|
||||
this.length = length -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -61,7 +61,7 @@ public class Spacing {
|
||||
var spacingChar = map.get(index);
|
||||
|
||||
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);
|
||||
|
||||
@ -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 java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@UtilityClass
|
||||
@ -18,4 +19,19 @@ public class ImageUtils {
|
||||
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