feat: base of implementation of dialogue renderer
@ -25,8 +25,10 @@ public class GlyphFont {
|
||||
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() {}
|
||||
@ -35,9 +37,18 @@ public class GlyphFont {
|
||||
return GlyphCompiler.instance().compile(SPACES, LANGUAGE_GLYPH);
|
||||
}
|
||||
|
||||
private static @NotNull LanguageGlyphCollection minecraftFontGlyphCollection(@NotNull Key fontKey, @NotNull Key textureKey, @NotNull List<@NotNull TextureProperties> propertiesList) {
|
||||
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, MINECRAFT_FONT_IMAGE_WRITABLE),
|
||||
Texture.texture(textureKey, writable),
|
||||
propertiesList,
|
||||
List.of(" АБВГДЕЖЗИК",
|
||||
"ЛМНОПРСТУФХЦЧШЩЪ",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
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;
|
||||
@ -32,6 +33,8 @@ public interface LanguageGlyphCollection extends ResourceProducer {
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
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;
|
||||
@ -9,6 +10,7 @@ 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;
|
||||
|
||||
@ -85,8 +87,22 @@ public class LanguageGlyphCollectionImpl implements LanguageGlyphCollection {
|
||||
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();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
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) {}
|
||||
}
|
||||
}
|
||||
@ -7,17 +7,18 @@ 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.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
@Getter
|
||||
@Log4j2
|
||||
@ -35,7 +36,9 @@ public class ResourcePackManager {
|
||||
|
||||
glyphResourcePack = GlyphResourcePack.create();
|
||||
monologueResources = new MonologueResources(glyphResourcePack);
|
||||
DialogueRenderer.compile(glyphResourcePack);
|
||||
initDefaultGlyphs();
|
||||
initLocales();
|
||||
}
|
||||
|
||||
private void initDefaultGlyphs() {
|
||||
@ -46,6 +49,15 @@ public class ResourcePackManager {
|
||||
monologueResources.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();
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
package ru.dragonestia.msb3.api.talk.dialogue;
|
||||
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
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) {
|
||||
|
||||
public static final DialogGlyphPositions DEFAULT = new DialogGlyphPositions(
|
||||
new GuiBackground(35, -96, 262),
|
||||
new PhraseText(11, -11, 340, 8, 8, "#000000"),
|
||||
new PhraseSubstrate(-24, 19, 356, 116),
|
||||
new Avatar(-144, 11, 100, 116),
|
||||
new AnswerText(175, 4, 8, -145, 149, -122, -170, "#000000"),
|
||||
new AnswerField(-117, -165, -153, 141, 44),
|
||||
new AnswerButton(-124, -182, 41, 97, 20, "#a18262", "#ffd8a8"),
|
||||
new ScrollPhraseButton(0, 126, -100, 10, "#a18262")
|
||||
);
|
||||
|
||||
public record GuiBackground(int topPartsY, int bottomPartsY, int height) {}
|
||||
|
||||
public record PhraseText(int maxLines, int lineX, int lineWidth, int fontHeight, int firstLineAscent, String textColorHex) {
|
||||
|
||||
public TextColor textColor() {
|
||||
return TextColor.fromHexString(textColorHex);
|
||||
}
|
||||
|
||||
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,
|
||||
String textColorHex) {
|
||||
|
||||
public TextColor textColor() {
|
||||
return TextColor.fromHexString(textColorHex);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
String loreHeadingTextColorHex,
|
||||
String loreFallbackTextColorHex) {
|
||||
|
||||
public Style loreHeadingTextStyle() {
|
||||
return Style.style(TextColor.fromHexString(loreHeadingTextColorHex), TextDecoration.ITALIC.withState(false));
|
||||
}
|
||||
|
||||
public Style loreFallbackTextStyle() {
|
||||
return Style.style(TextColor.fromHexString(loreFallbackTextColorHex), TextDecoration.ITALIC.withState(false));
|
||||
}
|
||||
}
|
||||
|
||||
public record ScrollPhraseButton(int scrollUpButtonX, int scrollDownButtonX, int buttonY, int height, String textColorHex) {
|
||||
|
||||
public Style textStyle() {
|
||||
return Style.style(TextColor.fromHexString(textColorHex),
|
||||
TextDecoration.ITALIC.withState(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,440 @@
|
||||
package ru.dragonestia.msb3.api.talk.dialogue;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.inventory.Inventory;
|
||||
import net.minestom.server.inventory.InventoryType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import ru.dragonestia.msb3.api.ServerBootstrap;
|
||||
import ru.dragonestia.msb3.api.glyph.font.GlyphFont;
|
||||
import ru.dragonestia.msb3.api.glyph.glyph.AppendableGlyph;
|
||||
import ru.dragonestia.msb3.api.glyph.glyph.GlyphComponentBuilder;
|
||||
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.util.ResourceFromJar;
|
||||
import ru.dragonestia.msb3.api.util.StringUtil;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class DialogueRenderer {
|
||||
|
||||
public static final int CHEST_GUI_WIDTH = 176;
|
||||
|
||||
private static final Key DIALOGUE_FONT_KEY = Key.key("msb3", "dialog");
|
||||
|
||||
private static final Writable ANSWER_ACTIVE_TEXT_FIELD = ResourceFromJar.of("glyphs/dialogue/answer_active_text_field.png");
|
||||
private static final Writable ANSWER_BUTTON_ACTIVE_1 = ResourceFromJar.of("glyphs/dialogue/answer_button_active_1.png");
|
||||
private static final Writable ANSWER_BUTTON_ACTIVE_2 = ResourceFromJar.of("glyphs/dialogue/answer_button_active_2.png");
|
||||
private static final Writable ANSWER_BUTTON_ACTIVE_3 = ResourceFromJar.of("glyphs/dialogue/answer_button_active_3.png");
|
||||
private static final Writable ANSWER_BUTTON_ACTIVE_4 = ResourceFromJar.of("glyphs/dialogue/answer_button_active_4.png");
|
||||
private static final Writable ANSWER_NOT_ACTIVE_TEXT_FIELD = ResourceFromJar.of("glyphs/dialogue/answer_not_active_text_field.png");
|
||||
private static final Writable AVATAR_FRAME = ResourceFromJar.of("glyphs/dialogue/avatar_frame.png");
|
||||
private static final Writable BACKGROUND_1 = ResourceFromJar.of("glyphs/dialogue/background_1.png");
|
||||
private static final Writable BACKGROUND_2 = ResourceFromJar.of("glyphs/dialogue/background_2.png");
|
||||
private static final Writable BACKGROUND_3 = ResourceFromJar.of("glyphs/dialogue/background_3.png");
|
||||
private static final Writable BACKGROUND_4 = ResourceFromJar.of("glyphs/dialogue/background_4.png");
|
||||
private static final Writable DEFAULT_AVATAR = ResourceFromJar.of("glyphs/dialogue/default_avatar.png");
|
||||
private static final Writable PHRASE_SUBSTRATE_1 = ResourceFromJar.of("glyphs/dialogue/phrase_substrate_1.png");
|
||||
private static final Writable PHRASE_SUBSTRATE_2 = ResourceFromJar.of("glyphs/dialogue/phrase_substrate_2.png");
|
||||
private static final Writable SCROLL_PHRASE_DOWN_BUTTON = ResourceFromJar.of("glyphs/dialogue/scroll_phrase_down_button.png");
|
||||
private static final Writable SCROLL_PHRASE_UP_BUTTON = ResourceFromJar.of("glyphs/dialogue/scroll_phrase_up_button.png");
|
||||
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_ACTIVE_TEXT_FIELD_1 = StringIdentifier.image("dialog_answer_active_text_field_1");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_ACTIVE_TEXT_FIELD_2 = StringIdentifier.image("dialog_answer_active_text_field_2");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_ACTIVE_TEXT_FIELD_3 = StringIdentifier.image("dialog_answer_active_text_field_3");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_ACTIVE_TEXT_FIELD_4 = StringIdentifier.image("dialog_answer_active_text_field_4");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_BUTTON_ACTIVE_1 = StringIdentifier.image("dialog_answer_button_active_1");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_BUTTON_ACTIVE_2 = StringIdentifier.image("dialog_answer_button_active_2");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_BUTTON_ACTIVE_3 = StringIdentifier.image("dialog_answer_button_active_3");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_BUTTON_ACTIVE_4 = StringIdentifier.image("dialog_answer_button_active_4");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_1 = StringIdentifier.image("dialog_answer_not_active_text_field_1");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_2 = StringIdentifier.image("dialog_answer_not_active_text_field_2");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_3 = StringIdentifier.image("dialog_answer_not_active_text_field_3");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_4 = StringIdentifier.image("dialog_answer_not_active_text_field_4");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_AVATAR_FRAME = StringIdentifier.image("dialog_avatar_frame");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_BACKGROUND_1 = StringIdentifier.image("dialog_background_1");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_BACKGROUND_2 = StringIdentifier.image("dialog_background_2");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_BACKGROUND_3 = StringIdentifier.image("dialog_background_3");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_BACKGROUND_4 = StringIdentifier.image("dialog_background_4");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_DEFAULT_AVATAR = StringIdentifier.image("dialog_default_avatar");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_PHRASE_SUBSTRATE_1 = StringIdentifier.image("dialog_phrase_substrate_1");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_PHRASE_SUBSTRATE_2 = StringIdentifier.image("dialog_phrase_substrate_2");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_SCROLL_PHRASE_DOWN_BUTTON = StringIdentifier.image("dialog_scroll_phrase_down_button");
|
||||
private static final StringIdentifier<@NotNull ImageGlyph> ID_SCROLL_PHRASE_UP_BUTTON = StringIdentifier.image("dialog_scroll_phrase_up_button");
|
||||
|
||||
private static final ImageGlyph GLYPH_ANSWER_ACTIVE_TEXT_FIELD_1 = createGlyph("dialog/answer_active_text_field.png",
|
||||
ANSWER_ACTIVE_TEXT_FIELD,
|
||||
DialogGlyphPositions.DEFAULT.answerField().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerField().topFieldY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_ACTIVE_TEXT_FIELD_2 = createGlyph("dialog/answer_active_text_field.png",
|
||||
ANSWER_ACTIVE_TEXT_FIELD,
|
||||
DialogGlyphPositions.DEFAULT.answerField().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerField().topFieldY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_ACTIVE_TEXT_FIELD_3 = createGlyph("dialog/answer_active_text_field.png",
|
||||
ANSWER_ACTIVE_TEXT_FIELD,
|
||||
DialogGlyphPositions.DEFAULT.answerField().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerField().bottomFieldY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_ACTIVE_TEXT_FIELD_4 = createGlyph("dialog/answer_active_text_field.png",
|
||||
ANSWER_ACTIVE_TEXT_FIELD,
|
||||
DialogGlyphPositions.DEFAULT.answerField().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerField().bottomFieldY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_BUTTON_ACTIVE_1 = createGlyph("dialog/answer_button_active_1.png",
|
||||
ANSWER_BUTTON_ACTIVE_1,
|
||||
DialogGlyphPositions.DEFAULT.answerButton().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerButton().topButtonY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_BUTTON_ACTIVE_2 = createGlyph("dialog/answer_button_active_2.png",
|
||||
ANSWER_BUTTON_ACTIVE_2,
|
||||
DialogGlyphPositions.DEFAULT.answerButton().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerButton().topButtonY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_BUTTON_ACTIVE_3 = createGlyph("dialog/answer_button_active_3.png",
|
||||
ANSWER_BUTTON_ACTIVE_3,
|
||||
DialogGlyphPositions.DEFAULT.answerButton().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerButton().bottomButtonY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_BUTTON_ACTIVE_4 = createGlyph("dialog/answer_button_active_4.png",
|
||||
ANSWER_BUTTON_ACTIVE_4,
|
||||
DialogGlyphPositions.DEFAULT.answerButton().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerButton().bottomButtonY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_NOT_ACTIVE_TEXT_FIELD_1 = createGlyph("dialog/answer_not_active_text_field.png",
|
||||
ANSWER_NOT_ACTIVE_TEXT_FIELD,
|
||||
DialogGlyphPositions.DEFAULT.answerField().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerField().topFieldY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_NOT_ACTIVE_TEXT_FIELD_2 = createGlyph("dialog/answer_not_active_text_field.png",
|
||||
ANSWER_NOT_ACTIVE_TEXT_FIELD,
|
||||
DialogGlyphPositions.DEFAULT.answerField().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerField().topFieldY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_NOT_ACTIVE_TEXT_FIELD_3 = createGlyph("dialog/answer_not_active_text_field.png",
|
||||
ANSWER_NOT_ACTIVE_TEXT_FIELD,
|
||||
DialogGlyphPositions.DEFAULT.answerField().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerField().bottomFieldY());
|
||||
private static final ImageGlyph GLYPH_ANSWER_NOT_ACTIVE_TEXT_FIELD_4 = createGlyph("dialog/answer_not_active_text_field.png",
|
||||
ANSWER_NOT_ACTIVE_TEXT_FIELD,
|
||||
DialogGlyphPositions.DEFAULT.answerField().height(),
|
||||
DialogGlyphPositions.DEFAULT.answerField().bottomFieldY());
|
||||
private static final ImageGlyph GLYPH_AVATAR_FRAME = createGlyph("dialog/avatar_frame.png",
|
||||
AVATAR_FRAME,
|
||||
DialogGlyphPositions.DEFAULT.avatar().frameHeight(),
|
||||
DialogGlyphPositions.DEFAULT.avatar().y() + DialogGlyphPositions.DEFAULT.avatar().frameBorderSize());
|
||||
private static final ImageGlyph GLYPH_BACKGROUND_1 = createGlyph("dialog/background_1.png",
|
||||
BACKGROUND_1,
|
||||
DialogGlyphPositions.DEFAULT.guiBackground().height() / 2,
|
||||
DialogGlyphPositions.DEFAULT.guiBackground().topPartsY());
|
||||
private static final ImageGlyph GLYPH_BACKGROUND_2 = createGlyph("dialog/background_2.png",
|
||||
BACKGROUND_2,
|
||||
DialogGlyphPositions.DEFAULT.guiBackground().height() / 2,
|
||||
DialogGlyphPositions.DEFAULT.guiBackground().topPartsY());
|
||||
private static final ImageGlyph GLYPH_BACKGROUND_3 = createGlyph("dialog/background_3.png",
|
||||
BACKGROUND_3,
|
||||
DialogGlyphPositions.DEFAULT.guiBackground().height() / 2,
|
||||
DialogGlyphPositions.DEFAULT.guiBackground().bottomPartsY());
|
||||
private static final ImageGlyph GLYPH_BACKGROUND_4 = createGlyph("dialog/background_4.png",
|
||||
BACKGROUND_4,
|
||||
DialogGlyphPositions.DEFAULT.guiBackground().height() / 2,
|
||||
DialogGlyphPositions.DEFAULT.guiBackground().bottomPartsY());
|
||||
private static final ImageGlyph GLYPH_DEFAULT_AVATAR = createGlyph("dialog/default_avatar.png",
|
||||
DEFAULT_AVATAR,
|
||||
DialogGlyphPositions.DEFAULT.avatar().height(),
|
||||
DialogGlyphPositions.DEFAULT.avatar().y());
|
||||
private static final ImageGlyph GLYPH_PHRASE_SUBSTRATE_1 = createGlyph("dialog/phrase_substrate_1.png",
|
||||
PHRASE_SUBSTRATE_1,
|
||||
DialogGlyphPositions.DEFAULT.phraseSubstrate().height(),
|
||||
DialogGlyphPositions.DEFAULT.phraseSubstrate().y());
|
||||
private static final ImageGlyph GLYPH_PHRASE_SUBSTRATE_2 = createGlyph("dialog/phrase_substrate_2.png",
|
||||
PHRASE_SUBSTRATE_2,
|
||||
DialogGlyphPositions.DEFAULT.phraseSubstrate().height(),
|
||||
DialogGlyphPositions.DEFAULT.phraseSubstrate().y());
|
||||
private static final ImageGlyph GLYPH_SCROLL_PHRASE_DOWN_BUTTON = createGlyph("dialog/scroll_phrase_down_button.png",
|
||||
SCROLL_PHRASE_DOWN_BUTTON,
|
||||
DialogGlyphPositions.DEFAULT.scrollPhraseButton().height(),
|
||||
DialogGlyphPositions.DEFAULT.scrollPhraseButton().buttonY());
|
||||
private static final ImageGlyph GLYPH_SCROLL_PHRASE_UP_BUTTON = createGlyph("dialog/scroll_phrase_up_button.png",
|
||||
SCROLL_PHRASE_UP_BUTTON,
|
||||
DialogGlyphPositions.DEFAULT.scrollPhraseButton().height(),
|
||||
DialogGlyphPositions.DEFAULT.scrollPhraseButton().buttonY());
|
||||
|
||||
private static final LanguageGlyphCollection GLYPH_FONT;
|
||||
private static final StringIdentifier<@NotNull LanguageGlyphCollection> ID_FONT = StringIdentifier.of("dialog_font", LanguageGlyphCollection.class);
|
||||
|
||||
static {
|
||||
var positions = DialogGlyphPositions.DEFAULT;
|
||||
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();
|
||||
|
||||
GLYPH_FONT = GlyphFont.minecraftFontGlyphCollection(DIALOGUE_FONT_KEY, Key.key("dialog/font.png"), propertiesList);
|
||||
}
|
||||
|
||||
private final Player player;
|
||||
private final String text = """
|
||||
Абсолютно точно.
|
||||
Я знаю точнo - невозможное возможно
|
||||
Сойти с ума, влюбиться так неосторoжно
|
||||
Найти тебя, не отпускать ни днём, ни ночью
|
||||
Всё невозможное - возможно, знаю точно!
|
||||
А где тебя искать, прошу ты мне ответь
|
||||
В какие города мне за тобой лететь
|
||||
Я готов на край Земли, я всё должен объяснить
|
||||
Пойми, что без тебя я не умею жить
|
||||
Я знаю точно - невозможное возможно
|
||||
Сойти с ума, влюбиться так неосторожно
|
||||
Найти тебя, не отпускать ни днём, ни ночью
|
||||
Всё невозможное - возможно, знаю точно!
|
||||
На-на-на-на (на-на-на-на), а-а, а-а
|
||||
На-на-на-на (на-на-на-на), а-а, а-а
|
||||
Всё готов делить, с тобой я пополам
|
||||
Ты только мне поверь, я сделал выбор сам
|
||||
Дай же мне последний шанс, я всё должен объяснить
|
||||
Пойми, что без тебя я не умею жить
|
||||
Я знаю точно - невозможное возможно
|
||||
Сойти с ума, влюбиться так неосторожно
|
||||
Найти тебя, не отпускать ни днём, ни ночью
|
||||
Всё невозможное - возможно, знаю точно!
|
||||
На-на-на-на (на-на-на-на), а-а, а-а
|
||||
На-на-на-на (на-на-на-на), а-а, а-а
|
||||
Я знаю точно - невозможное возможно
|
||||
Сойти с ума, влюбиться так неосторожно
|
||||
Найти тебя, не отпускать ни днём, ни ночью
|
||||
Всё невозможное - возможно, знаю точно!
|
||||
На-на-на-на (на-на-на-на), а-а, а-а
|
||||
На-на-на-на (на-на-на-на), а-а, а-а""";
|
||||
|
||||
private DialogueRenderer(Player player) {
|
||||
this.player = player;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static DialogueRenderer create(Player player) {
|
||||
return new DialogueRenderer(player);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
var inv = new Inventory(InventoryType.CHEST_6_ROW, render(ServerBootstrap.getInstance().getResourcePackManager().getGlyphResourcePack()));
|
||||
player.openInventory(inv);
|
||||
}
|
||||
|
||||
private Component render(GlyphResourcePack resourcePack) {
|
||||
var positions = DialogGlyphPositions.DEFAULT;
|
||||
|
||||
var avatar = resourcePack.get(ID_DEFAULT_AVATAR);
|
||||
var avatarFrame = resourcePack.get(ID_AVATAR_FRAME);
|
||||
var guiBackground1 = resourcePack.get(ID_BACKGROUND_1);
|
||||
var guiBackground2 = resourcePack.get(ID_BACKGROUND_2);
|
||||
var guiBackground3 = resourcePack.get(ID_BACKGROUND_3);
|
||||
var guiBackground4 = resourcePack.get(ID_BACKGROUND_4);
|
||||
var phraseSubstrate1 = resourcePack.get(ID_PHRASE_SUBSTRATE_1);
|
||||
var phraseSubstrate2 = resourcePack.get(ID_PHRASE_SUBSTRATE_2);
|
||||
|
||||
var builder = GlyphComponentBuilder.gui(resourcePack.spaces());
|
||||
|
||||
// GUI background
|
||||
builder.append(CHEST_GUI_WIDTH / 2 + 2 - guiBackground1.width(), guiBackground1);
|
||||
builder.append(CHEST_GUI_WIDTH / 2 + 1, guiBackground2);
|
||||
builder.append(CHEST_GUI_WIDTH / 2 + 2 - guiBackground3.width(), guiBackground3);
|
||||
builder.append(CHEST_GUI_WIDTH / 2 + 1, guiBackground4);
|
||||
|
||||
// Phrase substrate
|
||||
builder.append(positions.phraseSubstrate().x(), phraseSubstrate1);
|
||||
builder.append(positions.phraseSubstrate().x() + positions.phraseSubstrate().width() / 2, phraseSubstrate2);
|
||||
|
||||
// Frame and avatar
|
||||
builder.append(positions.avatar().x() - 8, avatarFrame);
|
||||
builder.append(positions.avatar().x(), avatar);
|
||||
|
||||
// Phrase text
|
||||
renderText(builder, 0);
|
||||
|
||||
// Scroll phrase buttons (optional)
|
||||
builder.append(
|
||||
positions.scrollPhraseButton().scrollUpButtonX(),
|
||||
resourcePack.get(ID_SCROLL_PHRASE_UP_BUTTON));
|
||||
|
||||
builder.append(
|
||||
positions.scrollPhraseButton().scrollDownButtonX(),
|
||||
resourcePack.get(ID_SCROLL_PHRASE_DOWN_BUTTON));
|
||||
|
||||
// Answers
|
||||
|
||||
var answers = List.of("Hello world!", "I am a teapot", "I love pizza", "msb3 is top!");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (true) { //TODO: checking answer exists
|
||||
builder.append(i % 2 == 0
|
||||
? positions.answerField().leftFieldX()
|
||||
: positions.answerField().rightFieldX(),
|
||||
switch (i) {
|
||||
case 0 -> resourcePack.get(ID_ANSWER_ACTIVE_TEXT_FIELD_1);
|
||||
case 1 -> resourcePack.get(ID_ANSWER_ACTIVE_TEXT_FIELD_2);
|
||||
case 2 -> resourcePack.get(ID_ANSWER_ACTIVE_TEXT_FIELD_3);
|
||||
case 3 -> resourcePack.get(ID_ANSWER_ACTIVE_TEXT_FIELD_4);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + i);
|
||||
});
|
||||
|
||||
builder.append(i % 2 == 0
|
||||
? positions.answerButton().leftButtonX()
|
||||
: positions.answerButton().rightButtonX(),
|
||||
switch (i) {
|
||||
case 0 -> resourcePack.get(ID_ANSWER_BUTTON_ACTIVE_1);
|
||||
case 1 -> resourcePack.get(ID_ANSWER_BUTTON_ACTIVE_2);
|
||||
case 2 -> resourcePack.get(ID_ANSWER_BUTTON_ACTIVE_3);
|
||||
case 3 -> resourcePack.get(ID_ANSWER_BUTTON_ACTIVE_4);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + i);
|
||||
});
|
||||
|
||||
var lines = breakIntoLines(
|
||||
answers.get(i),
|
||||
i < 2
|
||||
? new TextureProperties(positions.answerText().fontHeight(),
|
||||
positions.answerText().topFirstLineAscent())
|
||||
: new TextureProperties(
|
||||
positions.answerText().fontHeight(),
|
||||
positions.answerText().bottomFirstLineAscent()),
|
||||
positions.answerText().fontHeight(),
|
||||
positions.answerText().lineWidth());
|
||||
|
||||
for (int lineIdx = 0;
|
||||
lineIdx < Math.min(lines.size(), positions.answerText().maxLines());
|
||||
lineIdx++) {
|
||||
|
||||
boolean endWithDots = lineIdx + 1 == positions.answerText().maxLines()
|
||||
&& lineIdx + 1 != lines.size();
|
||||
|
||||
var line = lines.get(lineIdx);
|
||||
builder.append(i % 2 == 0
|
||||
? positions.answerText().leftLineX()
|
||||
: positions.answerText().rightLineX(), line.toGlyphList(0, endWithDots, positions.answerText().textColor()));
|
||||
}
|
||||
} else {
|
||||
builder.append(i % 2 == 0
|
||||
? positions.answerField().leftFieldX()
|
||||
: positions.answerField().rightFieldX(),
|
||||
switch (i) {
|
||||
case 0 -> resourcePack.get(ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_1);
|
||||
case 1 -> resourcePack.get(ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_2);
|
||||
case 2 -> resourcePack.get(ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_3);
|
||||
case 3 -> resourcePack.get(ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_4);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + i);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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: GLYPH_FONT.translate(firstLineProperties.height(), firstLineProperties.ascent(), line)) {
|
||||
width += glyph.width();
|
||||
}
|
||||
return width;
|
||||
});
|
||||
|
||||
if (lines == null) {
|
||||
throw new IllegalStateException("Cannot fit text into dialog");
|
||||
}
|
||||
|
||||
var textLines = new ArrayList<TextLine>();
|
||||
for (int lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
||||
var text = lines[lineIdx];
|
||||
|
||||
textLines.add(new TextLine(text, new TextureProperties(firstLineProperties.height(), firstLineProperties.ascent() - lineIdx * (fontHeight + 1))));
|
||||
}
|
||||
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());
|
||||
|
||||
for (int lineIdx = shift; (lineIdx - shift) < Math.min(textLines.size() - shift, positions.phraseText().maxLines()); lineIdx++) {
|
||||
var line = textLines.get(lineIdx);
|
||||
builder.append(positions.phraseText().lineX(), line.toGlyphList(
|
||||
-lineIdx + shift,
|
||||
textLines.size() - lineIdx > 0 && lineIdx - shift == positions.phraseText().maxLines() - 1,
|
||||
positions.phraseText().textColor()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public static void compile(GlyphResourcePack resourcePack) {
|
||||
resourcePack.with(ID_ANSWER_ACTIVE_TEXT_FIELD_1, GLYPH_ANSWER_ACTIVE_TEXT_FIELD_1)
|
||||
.with(ID_ANSWER_ACTIVE_TEXT_FIELD_2, GLYPH_ANSWER_ACTIVE_TEXT_FIELD_2)
|
||||
.with(ID_ANSWER_ACTIVE_TEXT_FIELD_3, GLYPH_ANSWER_ACTIVE_TEXT_FIELD_3)
|
||||
.with(ID_ANSWER_ACTIVE_TEXT_FIELD_4, GLYPH_ANSWER_ACTIVE_TEXT_FIELD_4)
|
||||
.with(ID_ANSWER_BUTTON_ACTIVE_1, GLYPH_ANSWER_BUTTON_ACTIVE_1)
|
||||
.with(ID_ANSWER_BUTTON_ACTIVE_2, GLYPH_ANSWER_BUTTON_ACTIVE_2)
|
||||
.with(ID_ANSWER_BUTTON_ACTIVE_3, GLYPH_ANSWER_BUTTON_ACTIVE_3)
|
||||
.with(ID_ANSWER_BUTTON_ACTIVE_4, GLYPH_ANSWER_BUTTON_ACTIVE_4)
|
||||
.with(ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_1, GLYPH_ANSWER_NOT_ACTIVE_TEXT_FIELD_1)
|
||||
.with(ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_2, GLYPH_ANSWER_NOT_ACTIVE_TEXT_FIELD_2)
|
||||
.with(ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_3, GLYPH_ANSWER_NOT_ACTIVE_TEXT_FIELD_3)
|
||||
.with(ID_ANSWER_NOT_ACTIVE_TEXT_FIELD_4, GLYPH_ANSWER_NOT_ACTIVE_TEXT_FIELD_4)
|
||||
.with(ID_AVATAR_FRAME, GLYPH_AVATAR_FRAME)
|
||||
.with(ID_BACKGROUND_1, GLYPH_BACKGROUND_1)
|
||||
.with(ID_BACKGROUND_2, GLYPH_BACKGROUND_2)
|
||||
.with(ID_BACKGROUND_3, GLYPH_BACKGROUND_3)
|
||||
.with(ID_BACKGROUND_4, GLYPH_BACKGROUND_4)
|
||||
.with(ID_DEFAULT_AVATAR, GLYPH_DEFAULT_AVATAR)
|
||||
.with(ID_PHRASE_SUBSTRATE_1, GLYPH_PHRASE_SUBSTRATE_1)
|
||||
.with(ID_PHRASE_SUBSTRATE_2, GLYPH_PHRASE_SUBSTRATE_2)
|
||||
.with(ID_SCROLL_PHRASE_DOWN_BUTTON, GLYPH_SCROLL_PHRASE_DOWN_BUTTON)
|
||||
.with(ID_SCROLL_PHRASE_UP_BUTTON, GLYPH_SCROLL_PHRASE_UP_BUTTON)
|
||||
.with(ID_FONT, GLYPH_FONT);
|
||||
}
|
||||
|
||||
private static ImageGlyph createGlyph(String texturePath, Writable writable, int height, int ascent) {
|
||||
return ImageGlyph.of(DIALOGUE_FONT_KEY,
|
||||
Texture.texture().key(Key.key("msb3", texturePath)).data(writable).build(),
|
||||
new TextureProperties(height, ascent));
|
||||
}
|
||||
|
||||
private record TextLine(Component text, TextureProperties textureProperties) {
|
||||
|
||||
public List<@NotNull AppendableGlyph> toGlyphList(int lineShift, boolean cutEnding, TextColor color) {
|
||||
var positions = DialogGlyphPositions.DEFAULT;
|
||||
|
||||
var properties = new TextureProperties(
|
||||
positions.phraseText().firstLineProperties().height(),
|
||||
positions.phraseText().firstLineProperties().ascent() + lineShift * (textureProperties().height() + 1)
|
||||
);
|
||||
|
||||
Component text = this.text;
|
||||
if (cutEnding) text = StringUtil.cutEnding(text, " <...>");
|
||||
text = text.applyFallbackStyle(Style.style(color));
|
||||
|
||||
return toList((TextComponent) text, properties);
|
||||
}
|
||||
|
||||
private List<AppendableGlyph> toList(TextComponent text, TextureProperties properties) {
|
||||
return GLYPH_FONT.translate(properties.height(), properties.ascent(), text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 445 B |
|
After Width: | Height: | Size: 281 B |
|
After Width: | Height: | Size: 305 B |
|
After Width: | Height: | Size: 284 B |
|
After Width: | Height: | Size: 301 B |
|
After Width: | Height: | Size: 442 B |
BIN
api/src/main/resources/glyphs/dialogue/avatar_frame.png
Normal file
|
After Width: | Height: | Size: 648 B |
BIN
api/src/main/resources/glyphs/dialogue/background_1.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
api/src/main/resources/glyphs/dialogue/background_2.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
api/src/main/resources/glyphs/dialogue/background_3.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
api/src/main/resources/glyphs/dialogue/background_4.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
api/src/main/resources/glyphs/dialogue/default_avatar.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
api/src/main/resources/glyphs/dialogue/phrase_substrate_1.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
api/src/main/resources/glyphs/dialogue/phrase_substrate_2.png
Normal file
|
After Width: | Height: | Size: 796 B |
|
After Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 234 B |