diff --git a/api/src/main/java/ru/dragonestia/msb3/api/resource/DialogueResources.java b/api/src/main/java/ru/dragonestia/msb3/api/resource/DialogueResources.java new file mode 100644 index 0000000..3033a7d --- /dev/null +++ b/api/src/main/java/ru/dragonestia/msb3/api/resource/DialogueResources.java @@ -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 avatars = new HashMap<>(); + private final Map avatarFrames = new HashMap<>(); + private final Map scrollUp = new HashMap<>(); + private final Map scrollDown = new HashMap<>(); + private final Map backgrounds = new HashMap<>(); + private final Map substrates = new HashMap<>(); + private final Map fonts = new HashMap<>(); + private final Map buttons = new HashMap<>(); + private final Map activeFields = new HashMap<>(); + private final Map 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 getAvatar(String identifier) { + return getGlyphFromMap(identifier, avatars); + } + + public Optional getAvatarFrame(String identifier) { + return getGlyphFromMap(identifier, avatarFrames); + } + + public Optional getScrollUp(String identifier) { + return getGlyphFromMap(identifier, scrollUp); + } + + public Optional getScrollDown(String identifier) { + return getGlyphFromMap(identifier, scrollDown); + } + + public Optional getBackground(String identifier) { + return Optional.ofNullable(backgrounds.get(identifier)); + } + + public Optional getSubstrate(String identifier) { + return Optional.ofNullable(substrates.get(identifier)); + } + + public Optional getFont(String identifier) { + return Optional.ofNullable(fonts.get(identifier)).map(FontGlyphEntry::glyph); + } + + public Optional