feat: implemented dialogue themes

This commit is contained in:
Andrey Terentev 2024-12-10 00:24:31 +07:00
parent aa3e3a32ba
commit bd29931a60
12 changed files with 683 additions and 302 deletions

View File

@ -0,0 +1,377 @@
package ru.dragonestia.msb3.api.resource;
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 team.unnamed.creative.base.Writable;
import team.unnamed.creative.texture.Texture;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
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;
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, 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);
}
public void registerAvatarFrame(String identifier, Writable writable) {
registerAvatarFrame(identifier, writable, DialogGlyphPositions.DEFAULT);
}
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 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 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;
Writable part3;
Writable part4;
try (var steam = new ByteArrayInputStream(writable.toByteArray())) {
image = ImageIO.read(steam);
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));
} 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 glyph2 = new GlyphEntry(
StringIdentifier.image("dialog_background2__" + identifier),
createGlyph(identifier, part2, "background2", positions.guiBackground().height() / 2, positions.guiBackground().topPartsY())
);
var glyph3 = new GlyphEntry(
StringIdentifier.image("dialog_background3__" + identifier),
createGlyph(identifier, part3, "background3", positions.guiBackground().height() / 2, positions.guiBackground().bottomPartsY())
);
var glyph4 = new GlyphEntry(
StringIdentifier.image("dialog_background4__" + identifier),
createGlyph(identifier, part4, "background4", positions.guiBackground().height() / 2, positions.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());
}
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;
try (var steam = new ByteArrayInputStream(writable.toByteArray())) {
image = ImageIO.read(steam);
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));
} 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 glyph2 = new GlyphEntry(
StringIdentifier.image("dialog_substrate2__" + identifier),
createGlyph(identifier, part2, "substrate2", positions.phraseSubstrate().height(), positions.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);
}
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,
writable,
"button1",
positions.answerButton().height(),
positions.answerButton().topButtonY());
var glyph2 = createGlyph(identifier,
writable,
"button2",
positions.answerButton().height(),
positions.answerButton().topButtonY());
var glyph3 = createGlyph(identifier,
writable,
"button3",
positions.answerButton().height(),
positions.answerButton().bottomButtonY());
var glyph4 = createGlyph(identifier,
writable,
"button4",
positions.answerButton().height(),
positions.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,
writable,
"active_field1",
positions.answerField().height(),
positions.answerField().topFieldY());
var glyph2 = createGlyph(identifier,
writable,
"active_field2",
positions.answerField().height(),
positions.answerField().topFieldY());
var glyph3 = createGlyph(identifier,
writable,
"active_field3",
positions.answerField().height(),
positions.answerField().bottomFieldY());
var glyph4 = createGlyph(identifier,
writable,
"active_field4",
positions.answerField().height(),
positions.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,
writable,
"not_active_field1",
positions.answerField().height(),
positions.answerField().topFieldY());
var glyph2 = createGlyph(identifier,
writable,
"not_active_field2",
positions.answerField().height(),
positions.answerField().topFieldY());
var glyph3 = createGlyph(identifier,
writable,
"not_active_field3",
positions.answerField().height(),
positions.answerField().bottomFieldY());
var glyph4 = createGlyph(identifier,
writable,
"not_active_field4",
positions.answerField().height(),
positions.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<ImageGlyph> getAvatarFrame(String identifier) {
return getGlyphFromMap(identifier, avatarFrames);
}
public Optional<ImageGlyph> getScrollUp(String identifier) {
return getGlyphFromMap(identifier, scrollUp);
}
public Optional<ImageGlyph> getScrollDown(String identifier) {
return getGlyphFromMap(identifier, scrollDown);
}
public Optional<Background> getBackground(String identifier) {
return Optional.ofNullable(backgrounds.get(identifier));
}
public Optional<Substrate> getSubstrate(String identifier) {
return Optional.ofNullable(substrates.get(identifier));
}
public Optional<LanguageGlyphCollection> getFont(String identifier) {
return Optional.ofNullable(fonts.get(identifier)).map(FontGlyphEntry::glyph);
}
public Optional<Button> getButton(String identifier) {
return Optional.ofNullable(buttons.get(identifier));
}
public Optional<TextField> getActiveTextField(String identifier) {
return Optional.ofNullable(activeFields.get(identifier));
}
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;
}
});
}
}

View File

@ -0,0 +1,7 @@
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) {}

View File

@ -0,0 +1,7 @@
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) {}

View File

@ -1,12 +1,10 @@
package ru.dragonestia.msb3.api.resource;
import net.kyori.adventure.key.Key;
import org.jetbrains.annotations.NotNull;
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.ResourceIdentifier;
import ru.dragonestia.msb3.api.glyph.pack.StringIdentifier;
import ru.dragonestia.msb3.api.util.ResourceFromJar;
import team.unnamed.creative.base.Writable;
@ -96,6 +94,4 @@ public class MonologueResources {
public void compile(GlyphResourcePack resourcePack) {
resourcePack.with(speechIndicator.identifier(), speechIndicator.glyph());
}
private record GlyphEntry(ResourceIdentifier<@NotNull ImageGlyph> identifier, ImageGlyph glyph) {}
}

View File

@ -27,6 +27,7 @@ public class ResourcePackManager {
private final ResourcePack resourcePack;
private final GlyphResourcePack glyphResourcePack;
private final MonologueResources monologueResources;
private final DialogueResources dialogueResources;
public ResourcePackManager() {
resourcePack = ResourcePack.resourcePack();
@ -36,7 +37,7 @@ public class ResourcePackManager {
glyphResourcePack = GlyphResourcePack.create();
monologueResources = new MonologueResources(glyphResourcePack);
DialogueRenderer.compile(glyphResourcePack);
dialogueResources = new DialogueResources(glyphResourcePack);
initDefaultGlyphs();
initLocales();
}
@ -47,6 +48,7 @@ public class ResourcePackManager {
glyphResourcePack.with(GlyphCompiler.instance().compile(BlackScreen.GLYPH));
glyphResourcePack.with(GlyphFont.compile());
monologueResources.compile(glyphResourcePack);
dialogueResources.compile(glyphResourcePack);
}
private void initLocales() {

View File

@ -0,0 +1,5 @@
package ru.dragonestia.msb3.api.resource.dialog;
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
public record Background(ImageGlyph part1, ImageGlyph part2, ImageGlyph part3, ImageGlyph part4) {}

View File

@ -0,0 +1,15 @@
package ru.dragonestia.msb3.api.resource.dialog;
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
public record Button(ImageGlyph button1, ImageGlyph button2, ImageGlyph button3, ImageGlyph button4) {
public ImageGlyph get(ButtonNumber number) {
return switch (number) {
case BUTTON_1 -> button1;
case BUTTON_2 -> button2;
case BUTTON_3 -> button3;
case BUTTON_4 -> button4;
};
}
}

View File

@ -0,0 +1,15 @@
package ru.dragonestia.msb3.api.resource.dialog;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum ButtonNumber {
BUTTON_1(1),
BUTTON_2(2),
BUTTON_3(3),
BUTTON_4(4);
private final int index;
}

View File

@ -0,0 +1,5 @@
package ru.dragonestia.msb3.api.resource.dialog;
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
public record Substrate(ImageGlyph part1, ImageGlyph part2) {}

View File

@ -0,0 +1,15 @@
package ru.dragonestia.msb3.api.resource.dialog;
import ru.dragonestia.msb3.api.glyph.glyph.image.ImageGlyph;
public record TextField(ImageGlyph field1, ImageGlyph field2, ImageGlyph field3, ImageGlyph field4) {
public ImageGlyph get(ButtonNumber number) {
return switch (number) {
case BUTTON_1 -> field1;
case BUTTON_2 -> field2;
case BUTTON_3 -> field3;
case BUTTON_4 -> field4;
};
}
}

View File

@ -1,6 +1,5 @@
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;
@ -11,227 +10,20 @@ 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.ImageUtil;
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 javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
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 DEFAULT_AVATAR = ResourceFromJar.of("glyphs/dialogue/default_avatar.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;
private static final ImageGlyph GLYPH_BACKGROUND_2;
private static final ImageGlyph GLYPH_BACKGROUND_3;
private static final ImageGlyph GLYPH_BACKGROUND_4;
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;
private static final ImageGlyph GLYPH_PHRASE_SUBSTRATE_2;
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 {
BufferedImage backgroundImage;
Writable b1;
Writable b2;
Writable b3;
Writable b4;
try (var steam = ResourceFromJar.streamOf("glyphs/dialogue/background.png")) {
backgroundImage = ImageIO.read(steam);
var w = backgroundImage.getWidth();
var h = backgroundImage.getHeight();
b1 = ImageUtil.imageToWritable(backgroundImage.getSubimage(0, 0, w / 2, h / 2));
b2 = ImageUtil.imageToWritable(backgroundImage.getSubimage(w / 2, 0, w / 2, h / 2));
b3 = ImageUtil.imageToWritable(backgroundImage.getSubimage(0, h / 2, w / 2, h / 2));
b4 = ImageUtil.imageToWritable(backgroundImage.getSubimage(w / 2, h / 2, w / 2, h / 2));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
GLYPH_BACKGROUND_1 = createGlyph("dialog/background_1.png",
b1,
DialogGlyphPositions.DEFAULT.guiBackground().height() / 2,
DialogGlyphPositions.DEFAULT.guiBackground().topPartsY());
GLYPH_BACKGROUND_2 = createGlyph("dialog/background_2.png",
b2,
DialogGlyphPositions.DEFAULT.guiBackground().height() / 2,
DialogGlyphPositions.DEFAULT.guiBackground().topPartsY());
GLYPH_BACKGROUND_3 = createGlyph("dialog/background_3.png",
b3,
DialogGlyphPositions.DEFAULT.guiBackground().height() / 2,
DialogGlyphPositions.DEFAULT.guiBackground().bottomPartsY());
GLYPH_BACKGROUND_4 = createGlyph("dialog/background_4.png",
b4,
DialogGlyphPositions.DEFAULT.guiBackground().height() / 2,
DialogGlyphPositions.DEFAULT.guiBackground().bottomPartsY());
BufferedImage substrateImage;
Writable s1;
Writable s2;
try (var stream = ResourceFromJar.streamOf("glyphs/dialogue/phrase_substrate.png")) {
substrateImage = ImageIO.read(stream);
var w = substrateImage.getWidth();
var h = substrateImage.getHeight();
s1 = ImageUtil.imageToWritable(substrateImage.getSubimage(0, 0, w / 2, h));
s2 = ImageUtil.imageToWritable(substrateImage.getSubimage(w / 2, 0, w / 2, h));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
GLYPH_PHRASE_SUBSTRATE_1 = createGlyph("dialog/phrase_substrate_1.png",
s1,
DialogGlyphPositions.DEFAULT.phraseSubstrate().height(),
DialogGlyphPositions.DEFAULT.phraseSubstrate().y());
GLYPH_PHRASE_SUBSTRATE_2 = createGlyph("dialog/phrase_substrate_2.png",
s2,
DialogGlyphPositions.DEFAULT.phraseSubstrate().height(),
DialogGlyphPositions.DEFAULT.phraseSubstrate().y());
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 DialogueTheme theme = DialogueTheme.builder().build();
private final Player player;
private final String text = """
Абсолютно точно.
@ -280,44 +72,33 @@ public class DialogueRenderer {
}
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);
builder.append(CHEST_GUI_WIDTH / 2 + 2 - theme.getBackground().part1().width(), theme.getBackground().part1());
builder.append(CHEST_GUI_WIDTH / 2 + 1, theme.getBackground().part2());
builder.append(CHEST_GUI_WIDTH / 2 + 2 - theme.getBackground().part3().width(), theme.getBackground().part3());
builder.append(CHEST_GUI_WIDTH / 2 + 1, theme.getBackground().part4());
// Phrase substrate
builder.append(positions.phraseSubstrate().x(), phraseSubstrate1);
builder.append(positions.phraseSubstrate().x() + positions.phraseSubstrate().width() / 2, phraseSubstrate2);
builder.append(theme.getPositions().phraseSubstrate().x(), theme.getSubstrate().part1());
builder.append(theme.getPositions().phraseSubstrate().x() + theme.getPositions().phraseSubstrate().width() / 2, theme.getSubstrate().part2());
// Frame and avatar
builder.append(positions.avatar().x() - 8, avatarFrame);
builder.append(positions.avatar().x(), avatar);
builder.append(theme.getPositions().avatar().x() - 8, theme.getAvatarFrame());
builder.append(theme.getPositions().avatar().x(), theme.getAvatar());
// Phrase text
renderText(builder, 0);
// Scroll phrase buttons (optional)
builder.append(
positions.scrollPhraseButton().scrollUpButtonX(),
resourcePack.get(ID_SCROLL_PHRASE_UP_BUTTON));
theme.getPositions().scrollPhraseButton().scrollUpButtonX(),
theme.getScrollTextUp());
builder.append(
positions.scrollPhraseButton().scrollDownButtonX(),
resourcePack.get(ID_SCROLL_PHRASE_DOWN_BUTTON));
theme.getPositions().scrollPhraseButton().scrollDownButtonX(),
theme.getScrollTextDown());
// Answers
@ -325,57 +106,57 @@ public class DialogueRenderer {
for (int i = 0; i < 4; i++) {
if (true) { //TODO: checking answer exists
builder.append(i % 2 == 0
? positions.answerField().leftFieldX()
: positions.answerField().rightFieldX(),
? theme.getPositions().answerField().leftFieldX()
: theme.getPositions().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);
case 0 -> theme.getActiveTextField1();
case 1 -> theme.getActiveTextField2();
case 2 -> theme.getActiveTextField3();
case 3 -> theme.getActiveTextField4();
default -> throw new IllegalStateException("Unexpected value: " + i);
});
builder.append(i % 2 == 0
? positions.answerButton().leftButtonX()
: positions.answerButton().rightButtonX(),
? theme.getPositions().answerButton().leftButtonX()
: theme.getPositions().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);
case 0 -> theme.getButton1();
case 1 -> theme.getButton2();
case 2 -> theme.getButton3();
case 3 -> theme.getButton4();
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());
? 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());
for (int lineIdx = 0; lineIdx < Math.min(lines.size(), positions.answerText().maxLines()); lineIdx++) {
boolean endWithDots = lineIdx + 1 == positions.answerText().maxLines()
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();
var line = lines.get(lineIdx);
builder.append(
i % 2 == 0
? positions.answerText().leftLineX()
: positions.answerText().rightLineX(),
line.toGlyphList(line.textureProperties(), 0, endWithDots, positions.answerText().textColor())
? theme.getPositions().answerText().leftLineX()
: theme.getPositions().answerText().rightLineX(),
line.toGlyphList(line.textureProperties(), 0, endWithDots, theme.getPositions().answerText().textColor())
);
}
} else {
builder.append(i % 2 == 0
? positions.answerField().leftFieldX()
: positions.answerField().rightFieldX(),
? theme.getPositions().answerField().leftFieldX()
: theme.getPositions().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);
case 0 -> theme.getNotActiveTextField1();
case 1 -> theme.getNotActiveTextField2();
case 2 -> theme.getNotActiveTextField3();
case 3 -> theme.getNotActiveTextField4();
default -> throw new IllegalStateException("Unexpected value: " + i);
});
}
@ -388,7 +169,7 @@ public class DialogueRenderer {
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)) {
for (var glyph: theme.getFont().translate(firstLineProperties.height(), firstLineProperties.ascent(), line)) {
width += glyph.width();
}
return width;
@ -403,7 +184,7 @@ public class DialogueRenderer {
var text = lines[lineIdx];
var properties = new TextureProperties(firstLineProperties.height(), firstLineProperties.ascent() - lineIdx * (fontHeight + 1));
textLines.add(new TextLine(text, properties));
textLines.add(new TextLine(theme, text, properties));
}
return textLines;
}
@ -428,43 +209,9 @@ public class DialogueRenderer {
}
}
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) {
private record TextLine(DialogueTheme theme, Component text, TextureProperties textureProperties) {
public List<@NotNull AppendableGlyph> toGlyphList(TextureProperties parentProperties, int lineShift, boolean cutEnding, TextColor color) {
var positions = DialogGlyphPositions.DEFAULT;
var properties = new TextureProperties(
parentProperties.height(),
parentProperties.ascent() + lineShift * (textureProperties().height() + 1)
@ -478,7 +225,7 @@ public class DialogueRenderer {
}
private List<AppendableGlyph> toList(TextComponent text, TextureProperties properties) {
return GLYPH_FONT.translate(properties.height(), properties.ascent(), text);
return theme.getFont().translate(properties.height(), properties.ascent(), text);
}
}
}

View File

@ -0,0 +1,190 @@
package ru.dragonestia.msb3.api.talk.dialogue;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
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.ResourcePackManager;
import ru.dragonestia.msb3.api.resource.dialog.*;
@Log4j2
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class DialogueTheme {
private final ResourcePackManager resourcePackManager = ServerBootstrap.getInstance().getResourcePackManager();
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;
public static Builder builder() {
return builder(DialogGlyphPositions.DEFAULT);
}
public static Builder builder(DialogGlyphPositions positions) {
return new Builder(positions);
}
public static class Builder {
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 Builder(DialogGlyphPositions positions) {
resources = ServerBootstrap.getInstance().getResourcePackManager().getDialogueResources();
this.positions = positions;
}
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) setActiveTextField(ButtonNumber.BUTTON_1, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
if (notActiveTextField2 == null) setActiveTextField(ButtonNumber.BUTTON_2, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
if (notActiveTextField3 == null) setActiveTextField(ButtonNumber.BUTTON_3, resources.getNotActiveTextField(DialogueResources.DEFAULT).orElseThrow());
if (notActiveTextField4 == null) setActiveTextField(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());
return new DialogueTheme(
positions,
background,
substrate,
avatar,
avatarFrame,
scrollTextUp,
scrollTextDown,
activeTextField1,
activeTextField2,
activeTextField3,
activeTextField4,
notActiveTextField1,
notActiveTextField2,
notActiveTextField3,
notActiveTextField4,
button1,
button2,
button3,
button4,
font
);
}
public Builder setBackground(Background background) {
this.background = background;
return this;
}
public Builder setSubstrate(Substrate substrate) {
this.substrate = substrate;
return this;
}
public Builder setAvatar(ImageGlyph avatar) {
this.avatar = avatar;
return this;
}
public Builder setAvatarFrame(ImageGlyph avatarFrame) {
this.avatarFrame = avatarFrame;
return this;
}
public Builder setScrollTextUp(ImageGlyph scrollTextUp) {
this.scrollTextUp = scrollTextUp;
return this;
}
public Builder setScrollTextDown(ImageGlyph 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);
case BUTTON_2 -> activeTextField2 = field.get(number);
case BUTTON_3 -> activeTextField3 = field.get(number);
case BUTTON_4 -> activeTextField4 = field.get(number);
}
return this;
}
public Builder setNotActiveTextField(ButtonNumber number, TextField field) {
switch (number) {
case BUTTON_1 -> notActiveTextField1 = field.get(number);
case BUTTON_2 -> notActiveTextField2 = field.get(number);
case BUTTON_3 -> notActiveTextField3 = field.get(number);
case BUTTON_4 -> notActiveTextField4 = field.get(number);
}
return this;
}
public Builder setButton(ButtonNumber number, Button button) {
switch (number) {
case BUTTON_1 -> button1 = button.get(number);
case BUTTON_2 -> button2 = button.get(number);
case BUTTON_3 -> button3 = button.get(number);
case BUTTON_4 -> button4 = button.get(number);
}
return this;
}
}
}