diff --git a/gradle.properties b/gradle.properties index b29b97b..b9ee8c3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ parchment_mappings=1.19.4:2023.06.26 loader_version=0.14.21 # Mod Properties -mod_version=2.8 +mod_version=3.0 maven_group=com.cstav.genshinstrument archives_base_name=genshinstrument diff --git a/src/main/java/com/cstav/genshinstrument/client/config/ModClientConfigs.java b/src/main/java/com/cstav/genshinstrument/client/config/ModClientConfigs.java index 1b9d351..6c9be5c 100644 --- a/src/main/java/com/cstav/genshinstrument/client/config/ModClientConfigs.java +++ b/src/main/java/com/cstav/genshinstrument/client/config/ModClientConfigs.java @@ -22,7 +22,7 @@ public class ModClientConfigs { public static final EnumValue GRID_LABEL_TYPE; public static final EnumValue CHANNEL_TYPE; public static final BooleanValue STOP_MUSIC_ON_PLAY, EMIT_RING_ANIMATION, SHARED_INSTRUMENT, - RENDER_BACKGROUND; + RENDER_BACKGROUND, ACCEPTED_GENSHIN_CONSENT, ACCURATE_ACCIDENTALS; public static final EnumValue ZITHER_SOUND_TYPE; public static final EnumValue DRUM_LABEL_TYPE; @@ -45,6 +45,9 @@ public class ModClientConfigs { SHARED_INSTRUMENT = configBuilder.comment("Defines whether you will see others playing on your instrument's screen") .define("display_other_players", true); RENDER_BACKGROUND = configBuilder.define("render_background", true); + ACCURATE_ACCIDENTALS = configBuilder.define("accurate_accidentals", true); + + ACCEPTED_GENSHIN_CONSENT = configBuilder.define("accepted_genshin_consent", false); ZITHER_SOUND_TYPE = configBuilder.defineEnum("zither_sound_type", ZitherSoundType.NEW); diff --git a/src/main/java/com/cstav/genshinstrument/client/config/enumType/label/NoteGridLabel.java b/src/main/java/com/cstav/genshinstrument/client/config/enumType/label/NoteGridLabel.java index fbffc70..73ee12a 100644 --- a/src/main/java/com/cstav/genshinstrument/client/config/enumType/label/NoteGridLabel.java +++ b/src/main/java/com/cstav/genshinstrument/client/config/enumType/label/NoteGridLabel.java @@ -19,16 +19,25 @@ public enum NoteGridLabel implements INoteLabel { KEYBOARD_LAYOUT((note) -> INoteLabel.upperComponent( KeyMappings.GRID_INSTRUMENT_MAPPINGS[ng(note).column][ng(note).row].getDisplayName() )), - DO_RE_MI((note) -> Component.translatable( - INoteLabel.TRANSLATABLE_PATH + AbsGridLabels.DO_RE_MI[ng(note).row % gs(note).rows()] + NOTE_NAME((note) -> Component.literal( + AbsGridLabels.getCutNoteName(ng(note)) )), - ABC((note) -> Component.literal( + DO_RE_MI((note) -> + Component.translatable( + INoteLabel.TRANSLATABLE_PATH + AbsGridLabels.DO_RE_MI[ng(note).row % gs(note).rows()] + ).append(AbsGridLabels.getCutNoteName(ng(note)).substring(1)) + ), + ABC_1((note) -> Component.literal( + AbsGridLabels.ABC[ng(note).row] + (gs(note).columns() - ng(note).column) + )), + ABC_2((note) -> Component.literal( ( (ng(note).column == 0) ? "A" : (ng(note).column == 1) ? "B" : "C" ) + (ng(note).row + 1) )), + NONE(NoteLabelSupplier.EMPTY); diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/GenshinConsentScreen.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/GenshinConsentScreen.java new file mode 100644 index 0000000..ddc4572 --- /dev/null +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/GenshinConsentScreen.java @@ -0,0 +1,122 @@ +package com.cstav.genshinstrument.client.gui.screens.instrument; + +import java.awt.Color; +import java.util.List; + +import com.cstav.genshinstrument.client.config.ModClientConfigs; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.multiplayer.WarningScreen; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; + +/** + * @implNote

+ * This screen was heavily inspired by Kistu-Lyre+'s Disclaimer screen. + * Please consider supporting them on Ko-fi! + *

+ * On a personal note, I unfortunately lack any budget to be in position of donating any sum of money to any one person ;-; + */ +public class GenshinConsentScreen extends WarningScreen { + + private static final Component TITLE = Component.translatable( + "genshinstrument.genshin_disclaimer.title" + ).withStyle(ChatFormatting.BOLD); + // Can't create object field because of constructor + private static final MutableComponent CONTENT = Component.translatable( + "genshinstrument.genshin_disclaimer.content", boldenAll(2) + ); + private static final Component NARRATION = TITLE.copy().append("\n").append(CONTENT); + + private final Screen previousScreen; + + public GenshinConsentScreen(final Screen previousScreen) { + super(TITLE, CONTENT, null, NARRATION); + this.previousScreen = previousScreen; + } + + + @Override + protected int getLineHeight() { + return 10; + } + + private static boolean hasGreeting = false; + + @Override + protected void init() { + final Button acknowledgeButton = Button.builder(CommonComponents.GUI_ACKNOWLEDGE, (button) -> { + ModClientConfigs.ACCEPTED_GENSHIN_CONSENT.set(true); + minecraft.setScreen(previousScreen); + }).build(); + + + // Make space for if the button is overlayed atop of the greeting + final int perferredButtonY = 100 + 140, annoyingButtonY = height - acknowledgeButton.getHeight() - 10; + + if (annoyingButtonY <= perferredButtonY) { + acknowledgeButton.setPosition( + (width - acknowledgeButton.getWidth()) / 2, + annoyingButtonY + ); + + if (hasGreeting) { + // i have to eradicate brothers alike UmU + final List siblings = CONTENT.getSiblings(); + for (int i = 0; i < 2; i++) + siblings.remove(siblings.size() - 1); + + hasGreeting = false; + } + } else { + acknowledgeButton.setPosition( + (width - acknowledgeButton.getWidth()) / 2, + perferredButtonY + ); + + if (!hasGreeting) { + CONTENT.append("\n\n\n\n") + .append(Component.translatable("genshinstrument.genshin_disclaimer.content.no_legal")); + + hasGreeting = true; + } + } + + this.addRenderableWidget(acknowledgeButton); + + super.init(); + } + + @Override + protected void renderTitle(GuiGraphics gui) { + gui.drawCenteredString(font, title, width/2, 30, Color.WHITE.getRGB()); + } + + + private static Component bolden(final int index) { + return Component.translatable("genshinstrument.genshin_disclaimer.bolden"+index).withStyle(ChatFormatting.BOLD); + } + private static Object[] boldenAll(final int amount) { + final Object[] result = new Object[amount]; + + for (int i = 0; i < amount; i++) + result[i] = bolden(i+1); + + return result; + } + + + @Override + public void onClose() { + super.onClose(); + previousScreen.onClose(); + } + + + @Override + protected void initButtons(int idc) {} +} \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/AratakisGreatAndGloriousDrumScreen.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/AratakisGreatAndGloriousDrumScreen.java index f585be5..6fcb7cf 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/AratakisGreatAndGloriousDrumScreen.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/AratakisGreatAndGloriousDrumScreen.java @@ -68,6 +68,10 @@ protected void init() { layout1.setPosition((width - layout1.getWidth()) / 2, (int)(height * .8f)); layout2.setPosition((width - layout2.getWidth()) / 2, layout1.getY() - layout1.getHeight()); + layout1.arrangeElements(); + layout2.arrangeElements(); + + layout1.visitWidgets(this::addRenderableWidget); layout2.visitWidgets(this::addRenderableWidget); diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/DrumButtonType.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/DrumButtonType.java index a08efb5..aceed97 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/DrumButtonType.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/DrumButtonType.java @@ -9,27 +9,21 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -@Environment(EnvType.CLIENT) public enum DrumButtonType { - DON(0, ModSounds.GLORIOUS_DRUM[0], "glorious_drum.don", KeyMappings.DON), - KA(1, ModSounds.GLORIOUS_DRUM[1], "glorious_drum.ka", KeyMappings.KA); + DON(0, ModSounds.GLORIOUS_DRUM[0], "glorious_drum.don"), + KA(1, ModSounds.GLORIOUS_DRUM[1], "glorious_drum.ka"); - private final DrumKeys keys; private final String transKey; private final NoteSound sound; private final int index; - private DrumButtonType(int index, NoteSound sound, String transKey, DrumKeys keys) { + private DrumButtonType(int index, NoteSound sound, String transKey) { this.sound = sound; this.index = index; - this.keys = keys; this.transKey = INoteLabel.TRANSLATABLE_PATH + transKey; } - public DrumKeys getKeys() { - return keys; - } public NoteSound getSound() { return sound; } @@ -39,4 +33,11 @@ public int getIndex() { public String getTransKey() { return transKey; } + + + // Seperated for server compatibility + @Environment(EnvType.CLIENT) + public DrumKeys getKeys() { + return (this == DON) ? KeyMappings.DON : KeyMappings.KA; + } } \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/DrumNoteButton.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/DrumNoteButton.java index 4fe66d5..041709f 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/DrumNoteButton.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/drum/DrumNoteButton.java @@ -2,6 +2,7 @@ import com.cstav.genshinstrument.client.config.ModClientConfigs; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteButton; +import com.cstav.genshinstrument.networking.buttonidentifier.DrumNoteIdentifier; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -12,7 +13,7 @@ public class DrumNoteButton extends NoteButton { public final DrumButtonType btnType; public final boolean isRight; - public DrumNoteButton(DrumButtonType btnType, boolean isLeft, AratakisGreatAndGloriousDrumScreen drumScreen) { + public DrumNoteButton(DrumButtonType btnType, boolean isRight, AratakisGreatAndGloriousDrumScreen drumScreen) { super( btnType.getSound(), ModClientConfigs.DRUM_LABEL_TYPE.get().getLabelSupplier(), @@ -22,7 +23,13 @@ public DrumNoteButton(DrumButtonType btnType, boolean isLeft, AratakisGreatAndGl ); this.btnType = btnType; - this.isRight = isLeft; + this.isRight = isRight; + } + + + @Override + public DrumNoteIdentifier getIdentifier() { + return new DrumNoteIdentifier(this); } } diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/AbstractGridInstrumentScreen.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/AbstractGridInstrumentScreen.java index c854080..e9b5538 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/AbstractGridInstrumentScreen.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/AbstractGridInstrumentScreen.java @@ -2,6 +2,7 @@ import java.awt.Color; import java.util.Map; +import java.util.NoSuchElementException; import com.cstav.genshinstrument.GInstrumentMod; import com.cstav.genshinstrument.client.ClientUtil; @@ -11,6 +12,8 @@ import com.cstav.genshinstrument.client.gui.screens.options.instrument.AbstractInstrumentOptionsScreen; import com.cstav.genshinstrument.client.gui.screens.options.instrument.GridInstrumentOptionsScreen; import com.cstav.genshinstrument.client.keyMaps.KeyMappings; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteGridButtonIdentifier; import com.mojang.blaze3d.platform.InputConstants.Key; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; @@ -40,6 +43,33 @@ public int columns() { public int rows() { return DEF_ROWS; } + + + /** + *

+ * If the given identifier is of type {@link NoteGridButtonIdentifier}, + * uses the optimal method to obtain the described {@link NoteButton}. + *

+ * Otherwise, uses {@link AbstractInstrumentScreen#getNoteButton the regular linear method}. + * @return The {@link NoteButton} as described by the given identifier + */ + @Override + public NoteButton getNoteButton(final NoteButtonIdentifier noteIdentifier) throws IndexOutOfBoundsException, NoSuchElementException { + if (!(noteIdentifier instanceof NoteGridButtonIdentifier)) + return super.getNoteButton(noteIdentifier); + + return getNoteButton((NoteGridButtonIdentifier)noteIdentifier); + } + /** + * Gets a {@link NoteButton} based on the location of the note as described by the given identifier. + */ + public NoteButton getNoteButton(final NoteGridButtonIdentifier noteIdentifier) throws IndexOutOfBoundsException { + return getNoteButton(noteIdentifier.row, noteIdentifier.column); + } + + public NoteButton getNoteButton(final int row, final int column) throws IndexOutOfBoundsException { + return noteGrid.getNoteButton(row, column); + } // Abstract implementations diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/AbstractInstrumentScreen.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/AbstractInstrumentScreen.java index 95df26a..be0f56e 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/AbstractInstrumentScreen.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/AbstractInstrumentScreen.java @@ -1,11 +1,14 @@ package com.cstav.genshinstrument.client.gui.screens.instrument.partial; import java.util.Map; +import java.util.NoSuchElementException; import com.cstav.genshinstrument.client.config.ModClientConfigs; +import com.cstav.genshinstrument.client.gui.screens.instrument.GenshinConsentScreen; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteButton; import com.cstav.genshinstrument.client.gui.screens.options.instrument.AbstractInstrumentOptionsScreen; import com.cstav.genshinstrument.networking.ModPacketHandler; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; import com.cstav.genshinstrument.networking.packets.instrument.CloseInstrumentPacket; import com.cstav.genshinstrument.sound.NoteSound; import com.cstav.genshinstrument.util.ModEntityData; @@ -25,7 +28,9 @@ @Environment(EnvType.CLIENT) public abstract class AbstractInstrumentScreen extends Screen { + public static final String[] DEFAULT_NOTE_LAYOUT = new String[] {"C", "D", "E", "F", "G", "A", "B"}; + /** * The set pitch of all note buttons in this screen */ @@ -69,6 +74,38 @@ protected static final InstrumentThemeLoader initThemeLoader(String modId, Strin */ public abstract NoteSound[] getSounds(); + /** + * @return The layout of the note names accross the instrument's rows. + * @apiNote All built-in instruments' layouts are derived from + * + * Genshin Music app configs + * + */ + public String[] noteLayout() { + return DEFAULT_NOTE_LAYOUT; + } + + /** + * @return Whether this instrument is derived from Genshin Impact + * @apiNote This value will help the mod determine whether a disclaimer pop-up should appear upon opening this + * instrument. + */ + public boolean isGenshinInstrument() { + return true; + } + + + /** + * @return The first {@link NoteButton} that matches the description of the given identifier + */ + public NoteButton getNoteButton(final NoteButtonIdentifier noteIdentifier) throws NoSuchElementException { + for (NoteButton note : notesIterable()) + if (noteIdentifier.matches(note)) + return note; + + throw new NoSuchElementException("Could not find a note in "+getClass().getSimpleName()+" based on the given identifier"); + } + /** * @return A map holding an integer key as its keycode and a {@link NoteButton} as its value. */ @@ -123,6 +160,9 @@ public AbstractInstrumentScreen(final InteractionHand hand) { @Override protected void init() { optionsScreen.init(minecraft, width, height); + + if (isGenshinInstrument() && !ModClientConfigs.ACCEPTED_GENSHIN_CONSENT.get()) + minecraft.setScreen(new GenshinConsentScreen(this)); } /** * Initializes a new button responsible for popping up the options menu for this instrument. diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/InstrumentThemeLoader.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/InstrumentThemeLoader.java index e221b27..25b914f 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/InstrumentThemeLoader.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/InstrumentThemeLoader.java @@ -89,7 +89,7 @@ public static T tryGetProperty(final J element, Funct try { return getter.apply(element); } catch (Exception e) { - e.printStackTrace(); + GInstrumentMod.LOGGER.error("Error retrieving property from JSON element", e); return def; } } @@ -99,17 +99,19 @@ public static void onResourcesReload(EventArgs.Empty empty) { final ResourceManager rManager = Minecraft.getInstance().getResourceManager(); for (final InstrumentThemeLoader instrumentLoader : LOADERS) { + final ResourceLocation styleLocation = instrumentLoader.getInstrumentStyleLocation(); try { + // Call all load listeners on the current loader for (final Consumer listener : instrumentLoader.listeners) listener.accept(JsonParser.parseReader( - rManager.getResource(instrumentLoader.getInstrumentStyleLocation()).get().openAsReader() + rManager.getResource(styleLocation).get().openAsReader() ).getAsJsonObject()); - GInstrumentMod.LOGGER.info("Loaded instrument style from "+instrumentLoader.InstrumentStyleLocation); + GInstrumentMod.LOGGER.info("Loaded instrument style from "+styleLocation); } catch (IOException e) { - GInstrumentMod.LOGGER.error("Unable to load instrument styler for " + instrumentLoader.InstrumentStyleLocation, e); + GInstrumentMod.LOGGER.error("Unable to load instrument styler for " + styleLocation, e); continue; } } diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteButton.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteButton.java index ede672f..3d97726 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteButton.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteButton.java @@ -1,6 +1,5 @@ package com.cstav.genshinstrument.client.gui.screens.instrument.partial.note; -import java.awt.Color; import java.awt.Point; import java.util.ArrayList; @@ -11,6 +10,8 @@ import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.animation.NoteAnimationController; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.label.NoteLabelSupplier; import com.cstav.genshinstrument.networking.ModPacketHandler; +import com.cstav.genshinstrument.networking.buttonidentifier.DefaultNoteButtonIdentifier; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; import com.cstav.genshinstrument.networking.packets.instrument.InstrumentPacket; import com.cstav.genshinstrument.sound.NoteSound; import com.cstav.genshinstrument.util.CommonUtil; @@ -28,9 +29,17 @@ import net.minecraft.resources.ResourceLocation; @Environment(EnvType.CLIENT) -public class NoteButton extends AbstractButton { +public abstract class NoteButton extends AbstractButton { + public static final String NOTE_BG_FILENAME = "note_bg.png"; + private static final double + FLAT_TEXTURE_HEIGHT_MULTIPLIER = 3.7f/1.3f, + FLAT_TEXTURE_WIDTH_MULTIPLIER = 1.7f/1.3f, + SHARP_MULTIPLIER = .8f, + DOUBLE_SHARP_MULTIPLIER = .9f + ; + @SuppressWarnings("resource") public static int getSize() { @@ -51,13 +60,22 @@ public static int getSize() { protected final NoteAnimationController noteAnimation = new NoteAnimationController(.15f, 9, this); protected final ArrayList rings = new ArrayList<>(); + + /** + *

Returns the identifier of this button.

+ * You may use the {@link DefaultNoteButtonIdentifier default implementation} if you're too lazy. + */ + public NoteButtonIdentifier getIdentifier() { + return new DefaultNoteButtonIdentifier(getSound()); + } + - public NoteSound sound; + private NoteSound sound; public final AbstractInstrumentScreen instrumentScreen; protected final int noteTextureRow, rowsInNoteTexture; protected final ResourceLocation rootLocation, - noteLocation, noteBgLocation; + noteLocation, noteBgLocation, accidentalsLocation; private NoteLabelSupplier labelSupplier; private int noteTextureWidth = 56; @@ -84,6 +102,7 @@ public NoteButton(NoteSound sound, noteLocation = instrumentScreen.getNotesLocation(); noteBgLocation = getResourceFromRoot(NOTE_BG_FILENAME); + accidentalsLocation = getResourceFromRoot("accidentals.png"); } public NoteButton(NoteSound sound, NoteLabelSupplier labelSupplier, int noteTextureRow, int rowsInNoteTexture, @@ -98,13 +117,24 @@ public NoteButton(NoteSound sound, public void setLabelSupplier(final NoteLabelSupplier labelSupplier) { this.labelSupplier = labelSupplier; - setMessage(labelSupplier.get(this)); + updateNoteLabel(); } public NoteLabelSupplier getLabelSupplier() { return labelSupplier; } public void updateNoteLabel() { - setMessage(labelSupplier.get(this)); + setMessage(getLabelSupplier().get(this)); + } + + public NoteSound getSound() { + return sound; + } + public void setSound(NoteSound sound) { + this.sound = sound; + + // Update the sound for the sound (default) identifier + if (getIdentifier() instanceof DefaultNoteButtonIdentifier) + ((DefaultNoteButtonIdentifier)getIdentifier()).setSound(sound); } @@ -146,6 +176,11 @@ public void moveToCenter() { } + public NoteNotation getNotation() { + return NoteNotation.NONE; + } + + public void init() { initPos(); setLabelSupplier(labelSupplier); @@ -156,7 +191,8 @@ public boolean isPlaying() { } - + //#region Rendering + @Override public void renderWidget(PoseStack poseStack, int mouseX, int mouseY, float partialTick) { RenderSystem.enableBlend(); @@ -166,15 +202,19 @@ public void renderWidget(PoseStack poseStack, int mouseX, int mouseY, float part rings.removeIf((ring) -> !ring.isPlaying()); rings.forEach((ring) -> ring.render(poseStack)); - final InstrumentThemeLoader theme = instrumentScreen.getThemeLoader(); - final Color - noteTheme = theme.getNoteTheme(), - pressedNoteTheme = theme.getPressedNoteTheme(), - labelTheme = theme.getLabelTheme() - ; + renderNoteButton(poseStack, instrumentScreen.getThemeLoader()); + noteAnimation.update(); + } + protected void renderNoteButton(PoseStack stack, final InstrumentThemeLoader themeLoader) { + renderNote(stack, themeLoader); + renderSymbol(stack, themeLoader); + renderLabel(stack, themeLoader); - // Button + renderAccidentals(stack); + } + + protected void renderNote(final PoseStack stack, final InstrumentThemeLoader themeLoader) { ClientUtil.displaySprite(noteBgLocation); // width = full color, width * 2 = border, 0 = normal @@ -187,20 +227,25 @@ public void renderWidget(PoseStack poseStack, int mouseX, int mouseY, float part (width * 2) : 0; - GuiComponent.blit(poseStack, + GuiComponent.blit(stack, this.getX(), this.getY(), blitOffset, 0, width, height, width*3, height ); - - // Note + } + // "Symbol" so that I can call the above "Note" + protected void renderSymbol(final PoseStack stack, final InstrumentThemeLoader themeLoader) { ClientUtil.displaySprite(noteLocation); + ClientUtil.setShaderColor((isPlaying() && !foreignPlaying) + ? themeLoader.getPressedNoteTheme() + : themeLoader.getLabelTheme() + ); + final int noteWidth = width/2, noteHeight = height/2; - ClientUtil.setShaderColor((isPlaying() && !foreignPlaying) ? pressedNoteTheme : labelTheme); - GuiComponent.blit(poseStack, + GuiComponent.blit(stack, this.getX() + noteWidth/2, this.getY() + noteHeight/2, //NOTE: I have no clue whatsoever how on earth these 1.025 and .9 multipliers actually work. // Like seriously wtf why fkuaherjgaeorg i hate maths @@ -211,20 +256,67 @@ public void renderWidget(PoseStack poseStack, int mouseX, int mouseY, float part ); ClientUtil.resetShaderColor(); - - // Label + } + protected void renderLabel(final PoseStack stack, final InstrumentThemeLoader themeLoader) { //FIXME: All text rendered this way are making their way to the top of // the render stack, for some reason drawCenteredString( - poseStack, minecraft.font, getMessage(), + stack, minecraft.font, getMessage(), textX, textY, - ((isPlaying() && !foreignPlaying) ? pressedNoteTheme : noteTheme).getRGB() + ((isPlaying() && !foreignPlaying) + ? themeLoader.getPressedNoteTheme() + : themeLoader.getNoteTheme() + ).getRGB() ); + } + protected void renderAccidentals(final PoseStack stack) { + switch (getNotation()) { + case NONE: break; + + case FLAT: + renderAccidental(stack, 0); + break; + case SHARP: + renderAccidental(stack, 1); + break; + case DOUBLE_FLAT: + renderAccidental(stack, 0, -6, -3); + renderAccidental(stack, 0, 5, 2); + break; + case DOUBLE_SHARP: + renderAccidental(stack, 2, -1, 0); + break; + + } + } + + protected void renderAccidental(final PoseStack stack, int index) { + renderAccidental(stack, index, 0, 0); + } + protected void renderAccidental(PoseStack stack, int index, int offsetX, int offsetY) { + final int textureWidth = (int)(width * FLAT_TEXTURE_WIDTH_MULTIPLIER * ( + (index == 1) ? SHARP_MULTIPLIER : (index == 2) ? DOUBLE_SHARP_MULTIPLIER : 1 + )), + textureHeight = (int)(height * FLAT_TEXTURE_HEIGHT_MULTIPLIER * ( + (index == 1) ? SHARP_MULTIPLIER : (index == 2) ? DOUBLE_SHARP_MULTIPLIER : 1 + )); + + final int spritePartHeight = textureHeight/3; - noteAnimation.update(); + ClientUtil.displaySprite(accidentalsLocation); + + blit(stack, + getX() - 9 + offsetX, getY() - 6 + offsetY, + // Handle sharp imperfections + isPlaying() ? textureWidth/2 : 0, (spritePartHeight) * index - index, + textureWidth/2, spritePartHeight + ((index == 1) ? 3 : 0), + textureWidth - (((index != 0) && isPlaying()) ? 1 : 0), textureHeight + ); } + //#endregion + public boolean locked = false; public void play() { @@ -237,7 +329,8 @@ public void play() { ModPacketHandler.sendToServer( new InstrumentPacket( sound, instrumentScreen.getPitch(), - instrumentScreen.interactionHand, instrumentScreen.getInstrumentId() + instrumentScreen.interactionHand, + instrumentScreen.getInstrumentId(), getIdentifier() ) ); @@ -278,6 +371,19 @@ protected void updateWidgetNarration(final NarrationElementOutput neo) { } + /** + *

Check whether an object is equal to this {@link NoteButton}.

+ * + * An object will only be equal to this note if it is of type {@link NoteButton} + * and both their identifiers {@link NoteButtonIdentifier#matches match} + */ + @Override + public boolean equals(Object obj) { + return getIdentifier().matches(obj); + } + + + // Doesn't exist for some reason public void setHeight(final int height) { this.height = height; diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteGrid.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteGrid.java index a418eb3..6d322fe 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteGrid.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteGrid.java @@ -79,7 +79,7 @@ public void setNoteSounds(final NoteSound[] noteSounds) { for (int i = 0; i < columns; i++) for (int j = 0; j < rows; j++) - notes[i][j].sound = getSoundAt(noteSounds, j, i); + notes[i][j].setSound(getSoundAt(noteSounds, j, i)); } @@ -109,8 +109,8 @@ public AbstractLayout initNoteGridLayout(final float vertAlignment, final int sc forEach(rowHelper::addChild); grid.arrangeElements(); - FrameLayout.alignInRectangle(grid, 0, 0, screenWidth, screenHeight, 0.5f, vertAlignment); + grid.arrangeElements(); // Initialize all the notes forEach(NoteButton::init); @@ -119,7 +119,7 @@ public AbstractLayout initNoteGridLayout(final float vertAlignment, final int sc } - public NoteButton getNote(final int row, final int column) { + public NoteButton getNoteButton(final int row, final int column) { return notes[column][row]; } diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteGridButton.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteGridButton.java index 4b93575..bc6e00e 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteGridButton.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteGridButton.java @@ -1,7 +1,10 @@ package com.cstav.genshinstrument.client.gui.screens.instrument.partial.note; +import com.cstav.genshinstrument.client.config.ModClientConfigs; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.AbstractGridInstrumentScreen; +import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.label.AbsGridLabels; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.label.NoteLabelSupplier; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteGridButtonIdentifier; import com.cstav.genshinstrument.sound.NoteSound; import net.fabricmc.api.EnvType; @@ -13,12 +16,23 @@ public class NoteGridButton extends NoteButton { public final int row, column; public NoteGridButton(int row, int column, NoteSound sound, NoteLabelSupplier labelSupplier, - AbstractGridInstrumentScreen instrumentScreen) { + AbstractGridInstrumentScreen instrumentScreen) { super(sound, labelSupplier, row, instrumentScreen.rows(), instrumentScreen); - - + this.row = row; this.column = column; } - -} + + @Override + public NoteGridButtonIdentifier getIdentifier() { + return new NoteGridButtonIdentifier(this); + } + + @Override + public NoteNotation getNotation() { + return ModClientConfigs.ACCURATE_ACCIDENTALS.get() + ? NoteNotation.getNotation(AbsGridLabels.getNoteName(this)) + : NoteNotation.NONE; + } + +} \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteNotation.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteNotation.java new file mode 100644 index 0000000..f5c69b7 --- /dev/null +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/NoteNotation.java @@ -0,0 +1,17 @@ +package com.cstav.genshinstrument.client.gui.screens.instrument.partial.note; + +/** + * Marks the accidental notation of a {@link NoteButton} + */ +public enum NoteNotation { + NONE, FLAT, DOUBLE_FLAT, SHARP, DOUBLE_SHARP; + + public static NoteNotation getNotation(final String noteName) { + if (noteName.endsWith("b")) + return noteName.endsWith("bb") ? DOUBLE_FLAT : FLAT; + if (noteName.endsWith("#")) + return noteName.endsWith("##") ? DOUBLE_SHARP : SHARP; + + return NONE; + } +} \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/label/AbsGridLabels.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/label/AbsGridLabels.java index 6f3fc0f..3d602d1 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/label/AbsGridLabels.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/partial/note/label/AbsGridLabels.java @@ -1,5 +1,14 @@ package com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.label; +import static java.util.Map.entry; + +import java.util.LinkedHashMap; +import java.util.Map.Entry; + +import com.cstav.genshinstrument.client.config.ModClientConfigs; +import com.cstav.genshinstrument.client.gui.screens.instrument.partial.AbstractGridInstrumentScreen; +import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteGridButton; + import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -12,68 +21,120 @@ public abstract class AbsGridLabels { }, PITCHES = { "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" + }, + ABC = { + "C", "D", "E", "F", "G", "A", "B" } ; - // The pitches dont even match, 1/16th is annoying to get - // @Deprecated(forRemoval = true) - // public static String getNoteName(final float pitch, final int noteRow) { - // int index = getNoteIndex(pitch + noteRow * .05f * 2); - - // // // Cb at start - // // final boolean didWrap = index > PITCHES.length; - - // // E and F - // final int startIndex = getNoteIndex(pitch), passed = index - startIndex; - // for (int i = 0; i < steppedOnPoint(startIndex, passed, 6 + (startIndex - 1)); i++) - // index--; - // // B and C - // // for (int i = 0; i < steppedOnPoint(startIndex, passed, 0 + (startIndex - 1)); i++) - // // index--; - - // return PITCHES[doublyPyWrap(index, PITCHES) /*+ (didWrap ? 1 : 0)*/]; - // } - - // private static int steppedOnPoint(final int start, int passed, final int point) { - // int counter = 0; - - // for (int i = start; passed > 0; i = (i + 1) % PITCHES.length) { - // if (i == point) - // counter++; - - // passed--; - // } - - // return counter; - // } - - // //NOTE: Assuming pitch step is always .05 and (0 < pitch < 2) - // private static int getNoteIndex(final float pitch) { - // float result = (pitch * 100 - 100) / 5; - // // Ceil/floor for float imperfections - // result += (result >= 0) ? .001f : -.001f; - - // return pyWrap((int)result, PITCHES); - // } - // /** - // * Provides a similar behaviour to python's indexing, - // * where negatives are counted backwards. - // */ - // private static int pyWrap(int index, final Object[] arr, boolean add1) { - // while (index < 0) - // index += arr.length + (add1 ? 1 : 0); - - // return index; - // } - // private static int doublyPyWrap(int index, final Object[] arr) { - // while (index >= arr.length) - // index -= arr.length; - - // return pyWrap(index, arr); - // } - - // private static int pyWrap(int index, final Object[] arr) { - // return pyWrap(index, arr, false); - // } + // Pitch system implementation + // Literally could not have been done w/o Specy's instrument app, oh my gosh their method is genius + // Either that or I'm just too much of a novice on music theory + + /** + * @implNote Scales map taken from Specy's + * + * Genshin Music app configs + * + */ + public static final LinkedHashMap NOTE_SCALES = ofEntries( + entry("Cb", strArr("Cb", "Dbb", "Db", "Ebb", "Eb", "Fb", "Gbb", "Gb", "Abb", "Ab", "Bbb", "Bb")), + entry("C", strArr("C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B")), + entry("C#", strArr("C#", "D", "D#", "E", "E#", "F#", "G", "G#", "A", "A#", "B", "B#")), + entry("Db", strArr("Db", "Ebb", "Eb", "Fb", "F", "Gb", "Abb", "Ab", "Bbb", "Bb", "Cb", "C")), + entry("D", strArr("D", "Eb", "E", "F", "F#", "G", "Ab", "A", "Bb", "B", "C", "C#")), + entry("D#", strArr("D#", "E", "E#", "F#", "F##", "G#", "A", "A#", "B", "B#", "C#", "C##")), + entry("Eb", strArr("Eb", "Fb", "F", "Gb", "G", "Ab", "Bbb", "Bb", "Cb", "C", "Db", "D")), + entry("E", strArr("E", "F", "F#", "G", "G#", "A", "Bb", "B", "C", "C#", "D", "D#")), + entry("E#", strArr("E#", "F#", "F##", "G#", "G##", "A#", "B", "B#", "C#", "C##", "D#", "D##")), + entry("Fb", strArr("Fb", "Gbb", "Gb", "Abb", "Ab", "Bbb", "Cbb", "Cb", "Dbb", "Db", "Ebb", "Eb")), + entry("F", strArr("F", "Gb", "G", "Ab", "A", "Bb", "Cb", "C", "Db", "D", "Eb", "E")), + entry("F#", strArr("F#", "G", "G#", "A", "A#", "B", "C", "C#", "D", "D#", "E", "E#")), + entry("Gb", strArr("Gb", "Abb", "Ab", "Bbb", "Bb", "Cb", "Dbb", "Db", "Ebb", "Eb", "Fb", "F")), + entry("G", strArr("G", "Ab", "A", "Bb", "B", "C", "Db", "D", "Eb", "E", "F", "F#")), + entry("G#", strArr("G#", "A", "A#", "B", "B#", "C#", "D", "D#", "E", "E#", "F#", "F##")), + entry("Ab", strArr("Ab", "Bbb", "Bb", "Cb", "C", "Db", "Ebb", "Eb", "Fb", "F", "Gb", "G")), + entry("A", strArr("A", "Bb", "B", "C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#")), + entry("A#", strArr("A#", "B", "B#", "C#", "C##", "D#", "E", "E#", "F#", "F##", "G#", "G##")), + entry("Bb", strArr("Bb", "Cb", "C", "Db", "D", "Eb", "Fb", "F", "Gb", "G", "Ab", "A")), + entry("B", strArr("B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#")), + entry("B#", strArr("B#", "C#", "C##", "D#", "D##", "E#", "F#", "F##", "G#", "G##", "A#", "A##")) + ); + private static String[] strArr(final String... arr) { + return arr; + } + @SafeVarargs + public static LinkedHashMap ofEntries(Entry... entries) { + final LinkedHashMap map = new LinkedHashMap<>(); + for (Entry entry : entries) + map.put(entry.getKey(), entry.getValue()); + + return map; + } + + public static String getNoteName(final float pitch, final String[] noteLayout, final int offset) { + final String baseNote = noteLayout[wrapAround(offset, noteLayout.length)]; + //NOTE: Assuming pitch step is always .05 + //TODO: Figure a formula for this 2 + final int pitchStep = perfectConv( + ((2) * 10) * (pitch - 1) + // To account for the fact that a pitch step is 1/16th and we are doing jumps of 1/20th, + // divide by the following amount + / 1.6f + ); + + final String[] scale = NOTE_SCALES.get(baseNote); + return scale[(doublyPyWrap(pitchStep, scale.length))]; + } + public static String getNoteName(final NoteGridButton gridButton) { + final AbstractGridInstrumentScreen screen = (AbstractGridInstrumentScreen) gridButton.instrumentScreen; + return getNoteName( + screen.getPitch(), screen.noteLayout(), + gridButton.row + gridButton.column * screen.rows() + ); + } + + public static String getCutNoteName(final NoteGridButton gridButton) { + String result = AbsGridLabels.getNoteName(gridButton); + + if (ModClientConfigs.ACCURATE_ACCIDENTALS.get()) + result = String.valueOf(result.charAt(0)); + + return result; + } + + + /** + * Perfects {@code num} to its actual int value by an accuricity of 0.001 + */ + private static int perfectConv(final float num) { + return (int)(num + ((num >= 0) ? .001f : -.001f)); + } + + /** + * Provides a similar behaviour to python's indexing, + * where negatives are counted backwards. + */ + private static int pyWrap(int index, final int arrLength) { + while (index < 0) + index += arrLength; + + return index; + } + /** + * Wraps the index around an array + */ + private static int wrapAround(int index, final int arrLength) { + while (index >= arrLength) + index -= arrLength; + + return index; + } + /** + * Performs both {@link AbsGridLabels#pyWrap} and {@link AbsGridLabels#wrapAround} + */ + private static int doublyPyWrap(int index, final int arrLength) { + return wrapAround(pyWrap(index, arrLength), arrLength); + } } \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/vintagelyre/VintageLyreScreen.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/vintagelyre/VintageLyreScreen.java index c1b378a..8721523 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/vintagelyre/VintageLyreScreen.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/vintagelyre/VintageLyreScreen.java @@ -15,6 +15,11 @@ @Environment(EnvType.CLIENT) public class VintageLyreScreen extends AbstractGridInstrumentScreen { public static final String INSTRUMENT_ID = "vintage_lyre"; + public static final String[] VINTAGE_LYRE_LAYOUT = new String[] { + "C", "Db", "Eb", "F", "G", "Ab", "Bb", + "C", "D", "Eb", "F", "G", "A", "Bb", + "C", "D", "Eb", "F", "G", "A", "Bb" + }; public VintageLyreScreen(InteractionHand hand) { super(hand); @@ -29,6 +34,12 @@ public ResourceLocation getInstrumentId() { public NoteSound[] getSounds() { return ModSounds.VINTAGE_LYRE_NOTE_SOUNDS; } + + @Override + public String[] noteLayout() { + return VINTAGE_LYRE_LAYOUT; + } + @Override public NoteGrid initNoteGrid() { diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/vintagelyre/VintageNoteButton.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/vintagelyre/VintageNoteButton.java index 26da795..82fe6be 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/vintagelyre/VintageNoteButton.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/instrument/vintagelyre/VintageNoteButton.java @@ -1,22 +1,17 @@ package com.cstav.genshinstrument.client.gui.screens.instrument.vintagelyre; -import com.cstav.genshinstrument.client.ClientUtil; +import com.cstav.genshinstrument.client.config.ModClientConfigs; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.AbstractGridInstrumentScreen; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteGridButton; +import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteNotation; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.label.NoteLabelSupplier; import com.cstav.genshinstrument.sound.NoteSound; -import com.mojang.blaze3d.vertex.PoseStack; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.gui.GuiComponent; -import net.minecraft.resources.ResourceLocation; @Environment(EnvType.CLIENT) public class VintageNoteButton extends NoteGridButton { - private static final float TEXTURE_MULTIPLIER = 1/1.3f; - - private final ResourceLocation thingyLocation = getResourceFromRoot("thing.png"); public VintageNoteButton(int row, int column, NoteSound sound, NoteLabelSupplier labelSupplier, AbstractGridInstrumentScreen instrumentScreen) { @@ -24,30 +19,16 @@ public VintageNoteButton(int row, int column, } - private boolean shouldRenderThingy() { + private boolean isDefaultFlat() { return (row == 6) || (row == 2) || ((row == 1) && (column == 0)) || ((row == 5) && (column == 0)); } @Override - public void renderWidget(PoseStack poseStack, int pMouseX, int pMouseY, float pPartialTick) { - super.renderWidget(poseStack, pMouseX, pMouseY, pPartialTick); - - if (!shouldRenderThingy()) - return; - - final int textureWidth = (int)(width * TEXTURE_MULTIPLIER), - textureHeight = (int)(height * TEXTURE_MULTIPLIER); - - - ClientUtil.displaySprite(thingyLocation); - - GuiComponent.blit(poseStack, - getX() - 1, getY() - 5, - isPlaying() ? textureWidth/2 : 0, 0, - textureWidth/2, textureHeight, - textureWidth, textureHeight - ); + public NoteNotation getNotation() { + return ModClientConfigs.ACCURATE_ACCIDENTALS.get() + ? super.getNotation() + : isDefaultFlat() ? NoteNotation.FLAT : NoteNotation.NONE; } } diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/AbstractInstrumentOptionsScreen.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/AbstractInstrumentOptionsScreen.java index 6e76814..436af5f 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/AbstractInstrumentOptionsScreen.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/AbstractInstrumentOptionsScreen.java @@ -10,6 +10,7 @@ import com.cstav.genshinstrument.client.config.enumType.label.NoteGridLabel; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.AbstractInstrumentScreen; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteButton; +import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.label.AbsGridLabels; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.label.INoteLabel; import com.cstav.genshinstrument.sound.NoteSound; import com.ibm.icu.text.DecimalFormat; @@ -37,9 +38,12 @@ public abstract class AbstractInstrumentOptionsScreen extends Screen { private static final String SOUND_CHANNEL_KEY = "button.genshinstrument.audioChannels", STOP_MUSIC_KEY = "button.genshinstrument.stop_music_on_play"; - private static final double PITCH_STEP = .05; + + public static final double PITCH_STEP = .05; + protected final HashMap APPLIED_OPTIONS = new HashMap<>(); + /** * Queues the given option to later be saved, * such that when the client closes this screen - the given runnable will run. @@ -101,6 +105,7 @@ public AbstractInstrumentOptionsScreen(@Nullable AbstractInstrumentScreen screen } public AbstractInstrumentOptionsScreen(final Screen lastScreen) { super(Component.translatable("button.genshinstrument.instrumentOptions")); + this.isOverlay = false; this.instrumentScreen = null; @@ -125,29 +130,27 @@ protected void init() { .alignHorizontallyCenter(); final RowHelper rowHelper = grid.createRowHelper(2); + initOptionsGrid(grid, rowHelper); grid.arrangeElements(); FrameLayout.alignInRectangle(grid, 0, 0, width, height, 0.5f, 0); grid.visitWidgets(this::addRenderableWidget); - + + grid.arrangeElements(); grid.setY(40); final Button doneBtn = Button.builder(CommonComponents.GUI_DONE, (btn) -> onClose()) .width(getSmallButtonWidth()) - .pos((width - getSmallButtonWidth())/2, Math.min(grid.getY() + grid.getHeight() + 60, height - getButtonHeight() - 15)) + .pos((width - getSmallButtonWidth())/2, Math.min(grid.getY() + grid.getHeight() + 50, height - getButtonHeight() - 15)) .build(); addRenderableWidget(doneBtn); } - /** - * Fills the settings grid with all the necessary widgets, buttons and such - * @param grid The settings grid to add the widgets to - * @param rowHelper A row helper for the specified {@code grid} - */ - protected void initOptionsGrid(final GridLayout grid, final RowHelper rowHelper) { + + protected void initAudioSection(final GridLayout grid, final RowHelper rowHelper) { final CycleButton instrumentChannel = CycleButton.builder((soundType) -> Component.translatable(SOUND_CHANNEL_KEY +"."+ soundType.toString().toLowerCase()) ) @@ -178,6 +181,7 @@ protected void updateMessage() { this.setMessage( Component.translatable("button.genshinstrument.pitch").append( ": " + format.format(getPitch()) + + " ("+AbsGridLabels.getNoteName(getPitch(), AbstractInstrumentScreen.DEFAULT_NOTE_LAYOUT, 0)+")" ) ); } @@ -205,21 +209,9 @@ private static double divisibleBy5(double number) { Component.translatable(STOP_MUSIC_KEY), this::onMusicStopChanged ); rowHelper.addChild(stopMusic); + } - - rowHelper.addChild(SpacerElement.height(15), 2); - - - if (labels != null) { - final CycleButton labelType = CycleButton.builder((label) -> Component.translatable(label.getKey())) - .withValues(labels) - .withInitialValue(currLabel) - .create(0, 0, - getSmallButtonWidth(), getButtonHeight(), - Component.translatable("button.genshinstrument.label"), this::onLabelChanged - ); - rowHelper.addChild(labelType); - } + protected void initVisualsSection(final GridLayout grid, final RowHelper rowHelper) { final CycleButton emitRing = CycleButton.booleanBuilder(CommonComponents.OPTION_ON, CommonComponents.OPTION_OFF) .withInitialValue(ModClientConfigs.EMIT_RING_ANIMATION.get()) @@ -237,10 +229,45 @@ private static double divisibleBy5(double number) { Component.translatable("button.genshinstrument.shared_instrument"), this::onSharedInstrumentChanged ); rowHelper.addChild(sharedInstrument); + + final CycleButton accurateAccidentals = CycleButton.booleanBuilder(CommonComponents.OPTION_ON, CommonComponents.OPTION_OFF) + .withInitialValue(ModClientConfigs.ACCURATE_ACCIDENTALS.get()) + .withTooltip((value) -> Tooltip.create(Component.translatable("button.genshinstrument.accurate_accidentals.tooltip"))) + .create(0, 0, + getSmallButtonWidth(), getButtonHeight(), + Component.translatable("button.genshinstrument.accurate_accidentals"), this::onAccurateAccidentalsChanged + ); + rowHelper.addChild(accurateAccidentals); + + + if (labels != null) { + final CycleButton labelType = CycleButton.builder((label) -> Component.translatable(label.getKey())) + .withValues(labels) + .withInitialValue(currLabel) + .create(0, 0, + getBigButtonWidth(), getButtonHeight(), + Component.translatable("button.genshinstrument.label"), this::onLabelChanged + ); + rowHelper.addChild(labelType, 2); + } + } + + + /** + * Fills the settings grid with all the necessary widgets, buttons and such + * @param grid The settings grid to add the widgets to + * @param rowHelper A row helper for the specified {@code grid} + */ + protected void initOptionsGrid(final GridLayout grid, final RowHelper rowHelper) { + initAudioSection(grid, rowHelper); + + rowHelper.addChild(SpacerElement.height(15), 2); + + initVisualsSection(grid, rowHelper); } private float getPitch() { - return (instrumentScreen == null) + return (!isOverlay) ? ModClientConfigs.PITCH.get().floatValue() : instrumentScreen.getPitch(); } @@ -248,7 +275,7 @@ private float getPitch() { // Change handlers protected void onLabelChanged(final CycleButton button, final INoteLabel label) { - if (instrumentScreen != null) + if (isOverlay) instrumentScreen.notesIterable().forEach((note) -> note.setLabelSupplier(label.getLabelSupplier())); queueToSave("note_label", () -> saveLabel(label)); @@ -259,7 +286,7 @@ protected void saveLabel(final INoteLabel newLabel) { } protected void onPitchChanged(final AbstractSliderButton slider, final double pitch) { - if (instrumentScreen != null) { + if (isOverlay) { instrumentScreen.setPitch((float)pitch); instrumentScreen.notesIterable().forEach(NoteButton::updateNoteLabel); @@ -285,6 +312,12 @@ protected void onEmitRingChanged(final CycleButton button, final boolea protected void onSharedInstrumentChanged(final CycleButton button, final boolean value) { ModClientConfigs.SHARED_INSTRUMENT.set(value); } + protected void onAccurateAccidentalsChanged(final CycleButton button, final boolean value) { + ModClientConfigs.ACCURATE_ACCIDENTALS.set(value); + + if (isOverlay) + instrumentScreen.notesIterable().forEach(NoteButton::updateNoteLabel); + } @@ -315,6 +348,8 @@ public void onClose() { protected void onSave() { for (final Runnable runnable : APPLIED_OPTIONS.values()) runnable.run(); + + ModClientConfigs.CONFIGS.save(); } diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/FloralZitherOptionsScreen.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/FloralZitherOptionsScreen.java index 00f547a..446a0ca 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/FloralZitherOptionsScreen.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/FloralZitherOptionsScreen.java @@ -57,7 +57,7 @@ public void render(PoseStack poseStack, int pMouseX, int pMouseY, float pPartial super.render(poseStack, pMouseX, pMouseY, pPartialTick); drawCenteredString(poseStack, font, - Component.translatable("button.genshinstrument.zither_options"), + Component.translatable("label.genshinstrument.zither_options"), width/2, heightBefore + SPACE_BEFORE + SPACER_HEIGHT , Color.WHITE.getRGB()); } diff --git a/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/GridInstrumentOptionsScreen.java b/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/GridInstrumentOptionsScreen.java index eb21ad4..639b9c0 100644 --- a/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/GridInstrumentOptionsScreen.java +++ b/src/main/java/com/cstav/genshinstrument/client/gui/screens/options/instrument/GridInstrumentOptionsScreen.java @@ -35,9 +35,7 @@ public NoteGridLabel getCurrentLabel() { @Override - protected void initOptionsGrid(GridLayout grid, RowHelper rowHelper) { - super.initOptionsGrid(grid, rowHelper); - + protected void initVisualsSection(GridLayout grid, RowHelper rowHelper) { final CycleButton renderBackground = CycleButton.booleanBuilder(CommonComponents.OPTION_ON, CommonComponents.OPTION_OFF) .withInitialValue(ModClientConfigs.RENDER_BACKGROUND.get()) .create(0, 0, @@ -45,6 +43,8 @@ protected void initOptionsGrid(GridLayout grid, RowHelper rowHelper) { Component.translatable("button.genshinstrument.render_background"), this::onRenderBackgroundChanged ); rowHelper.addChild(renderBackground); + + super.initVisualsSection(grid, rowHelper); } protected void onRenderBackgroundChanged(final CycleButton button, final boolean value) { diff --git a/src/main/java/com/cstav/genshinstrument/event/ClientEvents.java b/src/main/java/com/cstav/genshinstrument/event/ClientEvents.java index 8bc55c8..34f58f0 100644 --- a/src/main/java/com/cstav/genshinstrument/event/ClientEvents.java +++ b/src/main/java/com/cstav/genshinstrument/event/ClientEvents.java @@ -2,7 +2,6 @@ import com.cstav.genshinstrument.client.config.ModClientConfigs; import com.cstav.genshinstrument.client.gui.screens.instrument.partial.AbstractInstrumentScreen; -import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteButton; import com.cstav.genshinstrument.event.InstrumentPlayedEvent.ByPlayer.ByPlayerArgs; import com.cstav.genshinstrument.event.InstrumentPlayedEvent.InstrumentPlayedEventArgs; import com.cstav.genshinstrument.item.InstrumentItem; @@ -63,11 +62,9 @@ public static void onInstrumentPlayed(final InstrumentPlayedEventArgs args) { return; - for (NoteButton note : screen.notesIterable()) - if (note.sound.equals(args.sound)) { - note.playNoteAnimation(true); - return; - } + try { + screen.getNoteButton(args.noteIdentifier).playNoteAnimation(true); + } catch (Exception e) {} } } diff --git a/src/main/java/com/cstav/genshinstrument/event/InstrumentPlayedEvent.java b/src/main/java/com/cstav/genshinstrument/event/InstrumentPlayedEvent.java index 2716b57..604af85 100644 --- a/src/main/java/com/cstav/genshinstrument/event/InstrumentPlayedEvent.java +++ b/src/main/java/com/cstav/genshinstrument/event/InstrumentPlayedEvent.java @@ -3,6 +3,7 @@ import com.cstav.genshinstrument.event.impl.Cancelable; import com.cstav.genshinstrument.event.impl.EventArgs; import com.cstav.genshinstrument.event.impl.ModEvent; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; import com.cstav.genshinstrument.sound.NoteSound; import net.fabricmc.fabric.api.event.Event; @@ -30,15 +31,19 @@ public static class InstrumentPlayedEventArgs extends EventArgs { public final boolean isClientSide; public final ResourceLocation instrumentId; + public final NoteButtonIdentifier noteIdentifier; public final BlockPos pos; - public InstrumentPlayedEventArgs(NoteSound sound, Level level, BlockPos pos, ResourceLocation instrumentId, boolean isClientSide) { + public InstrumentPlayedEventArgs(NoteSound sound, Level level, BlockPos pos, + ResourceLocation instrumentId, NoteButtonIdentifier noteIdentifier, boolean isClientSide) { + this.sound = sound; this.level = level; this.pos = pos; this.isClientSide = isClientSide; this.instrumentId = instrumentId; + this.noteIdentifier = noteIdentifier; // Handle provided invalid id if (!BuiltInRegistries.ITEM.containsKey(instrumentId)) @@ -66,8 +71,10 @@ public static class ByPlayerArgs extends InstrumentPlayedEventArgs { public final ItemStack instrument; public final InteractionHand hand; - public ByPlayerArgs(NoteSound sound, Player player, InteractionHand hand, ResourceLocation instrumentId, boolean isClientSide) { - super(sound, player.getLevel(), player.blockPosition(), instrumentId, isClientSide); + public ByPlayerArgs(NoteSound sound, Player player, InteractionHand hand, + ResourceLocation instrumentId, NoteButtonIdentifier noteIdentifier, boolean isClientSide) { + + super(sound, player.getLevel(), player.blockPosition(), instrumentId, noteIdentifier, isClientSide); this.player = player; this.hand = hand; diff --git a/src/main/java/com/cstav/genshinstrument/networking/ModPacketHandler.java b/src/main/java/com/cstav/genshinstrument/networking/ModPacketHandler.java index cdeb11b..3b6fa14 100644 --- a/src/main/java/com/cstav/genshinstrument/networking/ModPacketHandler.java +++ b/src/main/java/com/cstav/genshinstrument/networking/ModPacketHandler.java @@ -3,11 +3,15 @@ import java.util.List; import com.cstav.genshinstrument.GInstrumentMod; +import com.cstav.genshinstrument.networking.buttonidentifier.DrumNoteIdentifier; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteGridButtonIdentifier; import com.cstav.genshinstrument.networking.packets.instrument.CloseInstrumentPacket; import com.cstav.genshinstrument.networking.packets.instrument.InstrumentPacket; import com.cstav.genshinstrument.networking.packets.instrument.NotifyInstrumentOpenPacket; import com.cstav.genshinstrument.networking.packets.instrument.OpenInstrumentPacket; import com.cstav.genshinstrument.networking.packets.instrument.PlayNotePacket; +import com.cstav.genshinstrument.util.ServerUtil; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.FabricPacket; @@ -27,6 +31,19 @@ public class ModPacketHandler { }) ; + @SuppressWarnings("unchecked") + private static final List> ACCEPTABLE_IDENTIFIERS = List.of(new Class[] { + NoteButtonIdentifier.class, NoteGridButtonIdentifier.class, DrumNoteIdentifier.class + }); + + /** + * @see ServerUtil#getValidNoteIdentifier + */ + public static Class getValidIdentifier(String classType) + throws ClassNotFoundException { + return ServerUtil.getValidNoteIdentifier(classType, ACCEPTABLE_IDENTIFIERS); + } + public static void registerClientPackets() { for (final Class packetClass : S2C_PACKETS) { diff --git a/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/DefaultNoteButtonIdentifier.java b/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/DefaultNoteButtonIdentifier.java new file mode 100644 index 0000000..e70c26a --- /dev/null +++ b/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/DefaultNoteButtonIdentifier.java @@ -0,0 +1,48 @@ +package com.cstav.genshinstrument.networking.buttonidentifier; + +import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteButton; +import com.cstav.genshinstrument.sound.NoteSound; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.network.FriendlyByteBuf; + +/** + * The default note button identifier. Uses a button's {@link NoteSound} as an identifier. + */ +public class DefaultNoteButtonIdentifier extends NoteButtonIdentifier { + + private NoteSound sound; + + public DefaultNoteButtonIdentifier(final NoteSound sound) { + this.sound = sound; + } + @Environment(EnvType.CLIENT) + public DefaultNoteButtonIdentifier(final NoteButton note) { + this(note.getSound()); + } + + public void setSound(NoteSound sound) { + this.sound = sound; + } + + + public DefaultNoteButtonIdentifier(final FriendlyByteBuf buf) { + sound = NoteSound.readFromNetwork(buf); + } + + @Override + public void writeToNetwork(FriendlyByteBuf buf) { + super.writeToNetwork(buf); + sound.writeToNetwork(buf); + } + + + public boolean matches(NoteButtonIdentifier other) { + return MatchType.forceMatch(other, this::matchSound); + } + private boolean matchSound(final DefaultNoteButtonIdentifier other) { + return other.sound.equals(sound); + } + +} \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/DrumNoteIdentifier.java b/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/DrumNoteIdentifier.java new file mode 100644 index 0000000..60d7e31 --- /dev/null +++ b/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/DrumNoteIdentifier.java @@ -0,0 +1,43 @@ +package com.cstav.genshinstrument.networking.buttonidentifier; + +import com.cstav.genshinstrument.client.gui.screens.instrument.drum.DrumButtonType; +import com.cstav.genshinstrument.client.gui.screens.instrument.drum.DrumNoteButton; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.network.FriendlyByteBuf; + +public class DrumNoteIdentifier extends DefaultNoteButtonIdentifier { + + public final DrumButtonType noteType; + public final boolean isRight; + + @Environment(EnvType.CLIENT) + public DrumNoteIdentifier(final DrumNoteButton note) { + super(note); + noteType = note.btnType; + isRight = note.isRight; + } + + public DrumNoteIdentifier(FriendlyByteBuf buf) { + super(buf); + noteType = buf.readEnum(DrumButtonType.class); + isRight = buf.readBoolean(); + } + @Override + public void writeToNetwork(FriendlyByteBuf buf) { + super.writeToNetwork(buf); + buf.writeEnum(noteType); + buf.writeBoolean(isRight); + } + + @Override + public boolean matches(NoteButtonIdentifier other) { + return MatchType.perferMatch(other, this::drumMatch, super::matches); + } + private boolean drumMatch(final DrumNoteIdentifier other) { + return (noteType == other.noteType) && (isRight == other.isRight); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/NoteButtonIdentifier.java b/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/NoteButtonIdentifier.java new file mode 100644 index 0000000..cf708bb --- /dev/null +++ b/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/NoteButtonIdentifier.java @@ -0,0 +1,128 @@ +package com.cstav.genshinstrument.networking.buttonidentifier; + +import java.util.function.Function; + +import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteButton; +import com.cstav.genshinstrument.networking.ModPacketHandler; +import com.mojang.logging.LogUtils; + +import net.minecraft.network.FriendlyByteBuf; + +/** + *

+ * A class used for identifying {@link NoteButton note button}s' UI placement over network. + *

+ * All implementors must include a constructor that gets a type {@link FriendlyByteBuf}. + */ +public abstract class NoteButtonIdentifier { + + public void writeToNetwork(final FriendlyByteBuf buf) { + buf.writeUtf(getClass().getName()); + } + + + public abstract boolean matches(final NoteButtonIdentifier other); + + public boolean matches(final NoteButton note) { + return matches(note.getIdentifier()); + } + public boolean matches(final Object obj) { + return equals(obj); + } + + + @Override + public boolean equals(Object other) { + if (other instanceof NoteButtonIdentifier) + return matches((NoteButtonIdentifier)other); + if (other instanceof NoteButton) + return matches((NoteButton)other); + + return false; + } + + + public static NoteButtonIdentifier readIdentifier(FriendlyByteBuf buf) { + try { + return ModPacketHandler.getValidIdentifier(buf.readUtf()) + .getDeclaredConstructor(FriendlyByteBuf.class).newInstance(buf); + } catch (Exception e) { + LogUtils.getLogger().error("Error initializing button identifier", e); + return null; + } + } + + + + /** + * A class holding methods to simplify the usage of the {@link NoteButtonIdentifier#matches matches} function + */ + public static abstract class MatchType { + /** + *

Executes the match methods such that if the current {@code matchFunction} returned {@code false}, + * the {@code unmatchFunction} will execute in its stead.

+ * If the type of {@code other} and {@code T} do not match, then {@code unmatchFunction} will be executed. + * @param The type of the identifier to expect + * @param other + * @param matchFunction The function for when the type is as expected + * @param unmatchFunction The function for when the type is unexpected (generic, {@link NoteButtonIdentifier}) + * @return The result of the identification process + */ + @SuppressWarnings("unchecked") + public static boolean hierarchyMatch(NoteButtonIdentifier other, + Function matchFunction, Function unmatchFunction) { + + try { + return matchFunction.apply((T)other) || unmatchFunction.apply(other); + } catch (ClassCastException e) { + return unmatchFunction.apply(other); + } + } + /** + *

Executes the match methods such that only that if {@code other} did not match the type of {@code matchFunction}, + * the {@code unmatchFunction} will execute in its stead.

+ * @param The type of the identifier to expect + * @param other + * @param matchFunction The function for when the type is as expected + * @param unmatchFunction The function for when the type is unexpected (generic, {@link NoteButtonIdentifier}) + * @return The result of the identification process + */ + @SuppressWarnings("unchecked") + public static boolean perferMatch(NoteButtonIdentifier other, + Function matchFunction, Function unmatchFunction) { + + try { + return matchFunction.apply((T)other); + } catch (ClassCastException e) { + return unmatchFunction.apply(other); + } + } + + /** + * Executes the given match method such that if the expected type does not match {@code other}, + * {@code false} will be returned. + * @param The type of the identifier to expect + * @param other + * @param matchFunction The function for when the type is as expected + * @return The result of the identification process, or {@code false} if the expected type does not match + * + * + * @apiNote It is generally recommended not to use this match method, + * because a lower type of identifier may be triggered as a result of 3rd-party initiation of notes. + * + * Implementors should instead consider using any of the other types + * with {@link DefaultNoteButtonIdentifier the default identifier} as their basis. + */ + @SuppressWarnings("unchecked") + public static boolean forceMatch(NoteButtonIdentifier other, + Function matchFunction) { + + try { + return matchFunction.apply((T)other); + } catch (ClassCastException e) { + return false; + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/NoteGridButtonIdentifier.java b/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/NoteGridButtonIdentifier.java new file mode 100644 index 0000000..8dda9d0 --- /dev/null +++ b/src/main/java/com/cstav/genshinstrument/networking/buttonidentifier/NoteGridButtonIdentifier.java @@ -0,0 +1,41 @@ +package com.cstav.genshinstrument.networking.buttonidentifier; + +import com.cstav.genshinstrument.client.gui.screens.instrument.partial.note.NoteGridButton; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.network.FriendlyByteBuf; + +public class NoteGridButtonIdentifier extends DefaultNoteButtonIdentifier { + + public final int row, column; + + @Environment(EnvType.CLIENT) + public NoteGridButtonIdentifier(final NoteGridButton button) { + super(button); + this.row = button.row; + this.column = button.column; + } + + public NoteGridButtonIdentifier(FriendlyByteBuf buf) { + super(buf); + row = buf.readInt(); + column = buf.readInt(); + } + @Override + public void writeToNetwork(FriendlyByteBuf buf) { + super.writeToNetwork(buf); + buf.writeInt(row); + buf.writeInt(column); + } + + + @Override + public boolean matches(NoteButtonIdentifier other) { + return MatchType.perferMatch(other, this::gridMatch, super::matches); + } + private boolean gridMatch(final NoteGridButtonIdentifier other) { + return (row == other.row) && (column == other.column); + } + +} \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/networking/packets/instrument/InstrumentPacket.java b/src/main/java/com/cstav/genshinstrument/networking/packets/instrument/InstrumentPacket.java index 5f33286..7db5813 100644 --- a/src/main/java/com/cstav/genshinstrument/networking/packets/instrument/InstrumentPacket.java +++ b/src/main/java/com/cstav/genshinstrument/networking/packets/instrument/InstrumentPacket.java @@ -1,6 +1,7 @@ package com.cstav.genshinstrument.networking.packets.instrument; import com.cstav.genshinstrument.networking.ModPacket; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; import com.cstav.genshinstrument.sound.NoteSound; import com.cstav.genshinstrument.util.ModEntityData; import com.cstav.genshinstrument.util.ServerUtil; @@ -22,20 +23,24 @@ public class InstrumentPacket implements ModPacket { private final float pitch; private final ResourceLocation instrumentId; + private final NoteButtonIdentifier noteIdentifier; - public InstrumentPacket(NoteSound sound, float pitch, InteractionHand hand, ResourceLocation instrumentId) { + public InstrumentPacket(NoteSound sound, float pitch, InteractionHand hand, + ResourceLocation instrumentId, NoteButtonIdentifier noteIdentifier) { this.sound = sound; this.hand = hand; this.pitch = pitch; - + this.instrumentId = instrumentId; + this.noteIdentifier = noteIdentifier; } public InstrumentPacket(FriendlyByteBuf buf) { sound = NoteSound.readFromNetwork(buf); hand = buf.readEnum(InteractionHand.class); pitch = buf.readFloat(); - + instrumentId = buf.readResourceLocation(); + noteIdentifier = NoteButtonIdentifier.readIdentifier(buf); } @Override @@ -45,6 +50,7 @@ public void write(final FriendlyByteBuf buf) { buf.writeFloat(pitch); buf.writeResourceLocation(instrumentId); + noteIdentifier.writeToNetwork(buf); } @@ -53,7 +59,7 @@ public void handle(Player player, PacketSender responseSender) { if (!ModEntityData.isInstrumentOpen(player)) return; - ServerUtil.sendPlayNotePackets((ServerPlayer)player, hand, sound, instrumentId, pitch); + ServerUtil.sendPlayNotePackets((ServerPlayer)player, hand, sound, instrumentId, noteIdentifier, pitch); } } \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/networking/packets/instrument/PlayNotePacket.java b/src/main/java/com/cstav/genshinstrument/networking/packets/instrument/PlayNotePacket.java index a4ad45a..b185875 100644 --- a/src/main/java/com/cstav/genshinstrument/networking/packets/instrument/PlayNotePacket.java +++ b/src/main/java/com/cstav/genshinstrument/networking/packets/instrument/PlayNotePacket.java @@ -4,6 +4,7 @@ import java.util.UUID; import com.cstav.genshinstrument.networking.ModPacket; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; import com.cstav.genshinstrument.sound.NoteSound; import net.fabricmc.fabric.api.networking.v1.PacketSender; @@ -22,16 +23,19 @@ public class PlayNotePacket implements ModPacket { private final NoteSound sound; private final float pitch; private final ResourceLocation instrumentId; + private final NoteButtonIdentifier noteIdentifier; private final Optional playerUUID; private final Optional hand; public PlayNotePacket(BlockPos pos, NoteSound sound, float pitch, ResourceLocation instrumentId, - Optional playerUUID, Optional hand) { + NoteButtonIdentifier noteIdentifier, Optional playerUUID, Optional hand) { + this.blockPos = pos; this.sound = sound; this.pitch = pitch; this.instrumentId = instrumentId; + this.noteIdentifier = noteIdentifier; this.playerUUID = playerUUID; this.hand = hand; @@ -41,6 +45,7 @@ public PlayNotePacket(FriendlyByteBuf buf) { sound = NoteSound.readFromNetwork(buf); pitch = buf.readFloat(); instrumentId = buf.readResourceLocation(); + noteIdentifier = NoteButtonIdentifier.readIdentifier(buf); playerUUID = buf.readOptional(FriendlyByteBuf::readUUID); hand = buf.readOptional((fbb) -> fbb.readEnum(InteractionHand.class)); @@ -52,6 +57,7 @@ public void write(FriendlyByteBuf buf) { sound.writeToNetwork(buf); buf.writeFloat(pitch); buf.writeResourceLocation(instrumentId); + noteIdentifier.writeToNetwork(buf); buf.writeOptional(playerUUID, FriendlyByteBuf::writeUUID); buf.writeOptional(hand, FriendlyByteBuf::writeEnum); @@ -60,6 +66,9 @@ public void write(FriendlyByteBuf buf) { @Override public void handle(Player player, PacketSender responseSender) { - sound.playAtPos(pitch, playerUUID.orElse(null), hand.orElse(null), instrumentId, blockPos); + sound.playAtPos( + pitch, playerUUID.orElse(null), hand.orElse(null), + instrumentId, noteIdentifier, blockPos + ); } } \ No newline at end of file diff --git a/src/main/java/com/cstav/genshinstrument/sound/ModSounds.java b/src/main/java/com/cstav/genshinstrument/sound/ModSounds.java index 056f66c..602367e 100644 --- a/src/main/java/com/cstav/genshinstrument/sound/ModSounds.java +++ b/src/main/java/com/cstav/genshinstrument/sound/ModSounds.java @@ -18,7 +18,7 @@ public class ModSounds { GLORIOUS_DRUM = new NoteSound[] { registerNote(loc("glorious_drum_don")), - registerNote(loc("glorious_drum_ka")) + registerNote(loc("glorious_drum_ka"), true) } ; diff --git a/src/main/java/com/cstav/genshinstrument/sound/NoteSound.java b/src/main/java/com/cstav/genshinstrument/sound/NoteSound.java index a20cd72..a914db2 100644 --- a/src/main/java/com/cstav/genshinstrument/sound/NoteSound.java +++ b/src/main/java/com/cstav/genshinstrument/sound/NoteSound.java @@ -6,8 +6,9 @@ import com.cstav.genshinstrument.client.config.ModClientConfigs; import com.cstav.genshinstrument.client.config.enumType.InstrumentChannelType; import com.cstav.genshinstrument.event.InstrumentPlayedEvent; -import com.cstav.genshinstrument.event.InstrumentPlayedEvent.InstrumentPlayedEventArgs; import com.cstav.genshinstrument.event.InstrumentPlayedEvent.ByPlayer.ByPlayerArgs; +import com.cstav.genshinstrument.event.InstrumentPlayedEvent.InstrumentPlayedEventArgs; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -125,7 +126,9 @@ private static boolean metInstrumentVolume() { * @param pos The position at which the sound was fired from */ @Environment(EnvType.CLIENT) - public void playAtPos(float pitch, UUID playerUUID, InteractionHand hand, ResourceLocation instrumentId, BlockPos pos) { + public void playAtPos(float pitch, UUID playerUUID, InteractionHand hand, + ResourceLocation instrumentId, NoteButtonIdentifier buttonIdentifier, BlockPos pos) { + final Minecraft minecraft = Minecraft.getInstance(); final Player player = minecraft.player; @@ -139,11 +142,14 @@ public void playAtPos(float pitch, UUID playerUUID, InteractionHand hand, Resour // Send instrument played event if (playerUUID == null) InstrumentPlayedEvent.EVENT.invoker().triggered( - new InstrumentPlayedEventArgs(this, level, pos, instrumentId, true) + new InstrumentPlayedEventArgs(this, level, pos, instrumentId, buttonIdentifier, true) ); else InstrumentPlayedEvent.ByPlayer.EVENT.invoker().triggered( - new ByPlayerArgs(this, level.getPlayerByUUID(playerUUID), hand, instrumentId, true) + new ByPlayerArgs( + this, level.getPlayerByUUID(playerUUID), hand, + instrumentId, buttonIdentifier, true + ) ); diff --git a/src/main/java/com/cstav/genshinstrument/util/ServerUtil.java b/src/main/java/com/cstav/genshinstrument/util/ServerUtil.java index 4d32839..78f83cc 100644 --- a/src/main/java/com/cstav/genshinstrument/util/ServerUtil.java +++ b/src/main/java/com/cstav/genshinstrument/util/ServerUtil.java @@ -4,9 +4,11 @@ import java.util.Optional; import com.cstav.genshinstrument.event.InstrumentPlayedEvent; -import com.cstav.genshinstrument.event.InstrumentPlayedEvent.InstrumentPlayedEventArgs; import com.cstav.genshinstrument.event.InstrumentPlayedEvent.ByPlayer.ByPlayerArgs; +import com.cstav.genshinstrument.event.InstrumentPlayedEvent.InstrumentPlayedEventArgs; import com.cstav.genshinstrument.networking.ModPacketHandler; +import com.cstav.genshinstrument.networking.buttonidentifier.DefaultNoteButtonIdentifier; +import com.cstav.genshinstrument.networking.buttonidentifier.NoteButtonIdentifier; import com.cstav.genshinstrument.networking.packets.instrument.PlayNotePacket; import com.cstav.genshinstrument.sound.NoteSound; @@ -26,6 +28,21 @@ public class ServerUtil { public static final int PLAY_DISTANCE = 16; + /** + * Sends {@link PlayNotePacket}s in the specified {@link ServerUtil#PLAY_DISTANCE}. + * This method treats the sound as it was produced by a player. + * @param player The player producing the sounds + * @param hand The hand of the player producing the sounds + * @param sound The sound tp initiate + * @param sound The sound to initiate + * @param instrumentId The ID of the instrument initiating the sound + * @param pitch The pitch of the sound to initiate + */ + public static void sendPlayNotePackets(ServerPlayer player, InteractionHand hand, + NoteSound sound, ResourceLocation instrumentId, float pitch) { + + sendPlayNotePackets(player, hand, sound, instrumentId, new DefaultNoteButtonIdentifier(sound), pitch); + } /** * Sends {@link PlayNotePacket}s in the specified {@link ServerUtil#PLAY_DISTANCE}. * This method treats the sound as it was produced by a player. @@ -35,11 +52,13 @@ public class ServerUtil { * @param pitch The pitch of the sound to initiate */ public static void sendPlayNotePackets(ServerPlayer player, InteractionHand hand, - NoteSound sound, ResourceLocation instrumentId, float pitch) { + NoteSound sound, ResourceLocation instrumentId, NoteButtonIdentifier noteIdentifier, float pitch) { + for (final Player listener : noteListeners(player.getLevel(), player.blockPosition())) ModPacketHandler.sendToClient( new PlayNotePacket( - player.blockPosition(), sound, pitch, instrumentId, + player.blockPosition(), sound, pitch, + instrumentId, noteIdentifier, Optional.of(player.getUUID()), Optional.of(hand) ), (ServerPlayer)listener @@ -54,7 +73,7 @@ public static void sendPlayNotePackets(ServerPlayer player, InteractionHand hand // Fire a player-specific event InstrumentPlayedEvent.ByPlayer.EVENT.invoker().triggered( - new ByPlayerArgs(sound, player, hand, instrumentId, false) + new ByPlayerArgs(sound, player, hand, instrumentId, noteIdentifier, false) ); } @@ -64,13 +83,30 @@ public static void sendPlayNotePackets(ServerPlayer player, InteractionHand hand * @param level The world that the sound should initiate in * @param pos The position of the sound to initiate * @param sound The sound to initiate + * @param instrumentId The ID of the instrument initiating the sound * @param pitch The pitch of the sound to initiate */ public static void sendPlayNotePackets(Level level, BlockPos pos, NoteSound sound, ResourceLocation instrumentId, float pitch) { + sendPlayNotePackets(level, pos, sound, instrumentId, new DefaultNoteButtonIdentifier(sound), pitch); + } + /** + * Sends {@link PlayNotePacket}s in the specified {@link ServerUtil#PLAY_DISTANCE}. + * This method treats the sound as it was NOT produced by a player. + * @param level The world that the sound should initiate in + * @param pos The position of the sound to initiate + * @param sound The sound to initiate + * @param instrumentId The ID of the instrument initiating the sound + * @param noteIdentifier The identifier of the note + * @param pitch The pitch of the sound to initiate + */ + public static void sendPlayNotePackets(Level level, BlockPos pos, NoteSound sound, + ResourceLocation instrumentId, NoteButtonIdentifier noteIdentifier, float pitch) { + for (final Player listener : noteListeners(level, pos)) ModPacketHandler.sendToClient( new PlayNotePacket( - pos, sound, pitch, instrumentId, + pos, sound, pitch, + instrumentId, noteIdentifier, Optional.empty(), Optional.empty() ), (ServerPlayer)listener @@ -90,7 +126,7 @@ public static void sendPlayNotePackets(Level level, BlockPos pos, NoteSound soun // Fire a generic instrument event InstrumentPlayedEvent.EVENT.invoker().triggered( - new InstrumentPlayedEventArgs(sound, (ServerLevel)level, pos, instrumentId, false) + new InstrumentPlayedEventArgs(sound, (ServerLevel)level, pos, instrumentId, noteIdentifier, false) ); } @@ -101,4 +137,25 @@ private static List noteListeners(Level level, BlockPos pos) { ); } + + /** + * Gets a {@link NoteButtonIdentifier} as described by the {@code classType} destination. + * Will only return a class type if it is valid and included in the {@code acceptableIdentifiers} list. + * @param classType The class name of the requested identifiers + * @param acceptableIdentifiers + * + * @return The class of the requested identifier + * @throws ClassNotFoundException If the requested class was not found in the provided {@code acceptableIdentifiers} list + */ + public static Class getValidNoteIdentifier(String classType, + List> acceptableIdentifiers) throws ClassNotFoundException { + + for (final Class identifier : acceptableIdentifiers) { + if (identifier.getName().equals(classType)) + return identifier; + } + + throw new ClassNotFoundException("Class type "+classType+" could not be evaluated as part of the acceptable identifiers"); + } + } diff --git a/src/main/resources/assets/genshinstrument/lang/ar_sa.json b/src/main/resources/assets/genshinstrument/lang/ar_sa.json new file mode 100644 index 0000000..dc15a07 --- /dev/null +++ b/src/main/resources/assets/genshinstrument/lang/ar_sa.json @@ -0,0 +1,56 @@ +{ + "genshinstrument.itemGroup.instruments": "الات موسيقية", + + "item.genshinstrument.windsong_lyre": "القيثارة", + "item.genshinstrument.floral_zither": "القانون", + "item.genshinstrument.vintage_lyre": "خمر القيثارة", + "item.genshinstrument.glorious_drum": "طبلة اغتكي الرائعة والمجيدة", + + + "soundCategory.record": "الات موسيقية", + + + "button.genshinstrument.instrumentOptions": "خيارات الأداة", + "label.genshinstrument.zither_options": "Zither Options", + + + "button.genshinstrument.audioChannels": "Instrument Audio Channel Type", + "button.genshinstrument.audioChannels.mono": "مونو", + "button.genshinstrument.audioChannels.stereo": "ستيريو", + "button.genshinstrument.audioChannels.mixed.tooltip": + "إذا تم تعيين فئة صوت الآلات على 100٪ ، فسوف تسمع آلات على ستيريو ضمن٪ s كتل من النطاق.\nخلاف ذلك ، سوف تسمع مونو.", + "button.genshinstrument.audioChannels.mixed": "مختلط", + "button.genshinstrument.stop_music_on_play.tooltip": "عندما تعزف أنت أو لاعبون آخرون ضمن٪ s من النطاق على آلة موسيقية ، ستتوقف موسيقى Minecraft في الخلفية.", + "button.genshinstrument.stop_music_on_play": "إيقاف تشغيل الموسيقى", + "button.genshinstrument.emit_ring": "انبعاث الرسوم المتحركة الدائري", + "button.genshinstrument.shared_instrument.tooltip": "تعرف على ما يلعبه لاعبو الملاحظات الآخرون القريبون في شاشة الآلة الموسيقية الخاصة بك", + "button.genshinstrument.shared_instrument": "شاشة الجهاز المشترك", + + "button.genshinstrument.render_background": "إظهار مرئيات الخلفية", + + + + "button.genshinstrument.label": "نوع تسميات الملاحظات", + "button.genshinstrument.pitch": "نغمة", + + "button.genshinstrument.zither.soundType": "نوع الصوت", + "button.genshinstrument.zither.soundType.old": "قديم", + "button.genshinstrument.zither.soundType.new": "جديد", + + + "button.genshinstrument.label.do_re_mi": "دو ري مي", + + "genshinstrument.label.do": "دو", + "genshinstrument.label.re": "ري", + "genshinstrument.label.mi": "مي", + "genshinstrument.label.fa": "فا", + "genshinstrument.label.so": "صو", + "genshinstrument.label.la": "لا ", + "genshinstrument.label.ti": "تي", + + + "button.genshinstrument.label.keyboard_layout": "لوحة المفاتيح", + "button.genshinstrument.label.note_name": "اسم الملاحظة", + "button.genshinstrument.label.none": "لا تسمية" + +} \ No newline at end of file diff --git a/src/main/resources/assets/genshinstrument/lang/en_us.json b/src/main/resources/assets/genshinstrument/lang/en_us.json index f018b3d..bbc2450 100644 --- a/src/main/resources/assets/genshinstrument/lang/en_us.json +++ b/src/main/resources/assets/genshinstrument/lang/en_us.json @@ -11,7 +11,13 @@ "button.genshinstrument.instrumentOptions": "Instrument Options", - "button.genshinstrument.zither_options": "Zither Options", + "label.genshinstrument.zither_options": "Zither Options", + + "genshinstrument.genshin_disclaimer.title": "Disclaimer!", + "genshinstrument.genshin_disclaimer.content": "Genshin Instruments is an %s and %s Minecraft mod that is in no way afiliated with Genshin Impact nor HoYoverse.\n\nThus, all assets used in-game, such as sounds, images, instrumens and more are of complete ownership to HoYoverse.\n\nAs the user, you have the full responsibility over your actions within the game, including (but not limited to!) playing and sharing/publishing any songs that may be protected by copyright laws.", + "genshinstrument.genshin_disclaimer.content.no_legal": "Legal stuff aside; I hope you enjoy playing with this mod!", + "genshinstrument.genshin_disclaimer.bolden1": "unofficial", + "genshinstrument.genshin_disclaimer.bolden2": "fanmade", "button.genshinstrument.audioChannels": "Instrument Audio Channel Type", @@ -29,9 +35,12 @@ "button.genshinstrument.shared_instrument": "Shared Instrument Screen", "button.genshinstrument.render_background": "Show Background Visuals", + "button.genshinstrument.accurate_accidentals": "Accurate Accidentals", + "button.genshinstrument.accurate_accidentals.tooltip": "When on, provides a pitch-accurate representation of the accidentals used by this instrument's layout", + - "button.genshinstrument.label": "Note labels", + "button.genshinstrument.label": "Note Labels Type", "button.genshinstrument.pitch": "Pitch", "button.genshinstrument.zither.soundType": "Sound Type", @@ -54,7 +63,9 @@ "button.genshinstrument.label.keyboard_layout": "Keyboard", - "button.genshinstrument.label.abc": "ABC", + "button.genshinstrument.label.abc_1": "ABC - Type 1", + "button.genshinstrument.label.abc_2": "ABC - Type 2", + "button.genshinstrument.label.note_name": "Note Name", "button.genshinstrument.label.none": "No Label", "button.genshinstrument.label.don_ka": "Don-Ka", diff --git a/src/main/resources/assets/genshinstrument/lang/he_il.json b/src/main/resources/assets/genshinstrument/lang/he_il.json index c0a6cc5..ab1d5ad 100644 --- a/src/main/resources/assets/genshinstrument/lang/he_il.json +++ b/src/main/resources/assets/genshinstrument/lang/he_il.json @@ -5,9 +5,14 @@ "item.genshinstrument.floral_zither": "הציטר הפרחי", "item.genshinstrument.vintage_lyre": "נבל הבציר", "item.genshinstrument.glorious_drum": "התוף הגדול והמפואר של ארטאקי", - + "genshinstrument.genshin_disclaimer.content": "מוד כלי הנגינה של גנשין הינו %s ו%s, כלפי שום קשר עם Genshin Impact או HoYoverse.\n\nלכן, כל נכס הנעשה בו שימוש בתוסף, כגון צלילים, תמונות, כלי נגינה וכו' שייכים במלואן ל- HoYoverse.\n\nכמשתמש, עליך מוטלת האחריות המלאה על מעשיך במשחק זה, הכולל ניגון ושיתוף של כל שיר/פיסת מוזיקה המוגן תחת זכויות יוצרים ועוד.", + "genshinstrument.genshin_disclaimer.content.no_legal": "דברי משפט בצד; מקווה שתהנו מהתוסף!", + "genshinstrument.genshin_disclaimer.bolden1": "תוצר קהילתי", + "genshinstrument.genshin_disclaimer.bolden2": "לא רשמי", + + "soundCategory.record": "כלי נגינה", "button.genshinstrument.audioChannels": "סוג אאודיו לכלי נגינה", @@ -20,16 +25,19 @@ "button.genshinstrument.audioChannels.mixed": "מעורב", "button.genshinstrument.stop_music_on_play.tooltip": "כאשר את.ה או שחקנים אחרים בטווח של %s בלוקים מנגנים בכלי נגינה, מוזיקת הרקע תחדול לנגן.", "button.genshinstrument.stop_music_on_play": "הפסק מוזיקה בזמן נגינה", - "button.genshinstrument.emit_ring": "הצג אנימציות תווים", + "button.genshinstrument.emit_ring": "הצג הנפשות תווים", "button.genshinstrument.shared_instrument.tooltip": "ראה מה שחקנים אחרים מנגנים במסך הנגינה שלך", "button.genshinstrument.shared_instrument": "מסך נגינה משותף", "button.genshinstrument.render_background": "הצג תפאורות רקע", + "button.genshinstrument.accurate_accidentals": "סימני היתק מדוייקים", + "button.genshinstrument.accurate_accidentals.tooltip": "כאשר אופציה זו מופעלת, יוצגו יתקיהם של כל התווים בהתאם לגובה הצליל הנבחר", + "button.genshinstrument.instrumentOptions": "אפשרויות כלי נגינה", - "button.genshinstrument.zither_options": "אפשרויות הציטר", + "label.genshinstrument.zither_options": "אפשרויות הציטר", "button.genshinstrument.label": "תגיות תווים", @@ -41,6 +49,7 @@ "button.genshinstrument.label.do_re_mi": "דו רה מי", + "button.genshinstrument.label.note_name": "שם תו", "button.genshinstrument.label.keyboard_layout": "מקלדת", diff --git a/src/main/resources/assets/genshinstrument/lang/ru_ru.json b/src/main/resources/assets/genshinstrument/lang/ru_ru.json index 032cce1..44a6e0b 100644 --- a/src/main/resources/assets/genshinstrument/lang/ru_ru.json +++ b/src/main/resources/assets/genshinstrument/lang/ru_ru.json @@ -25,11 +25,12 @@ "button.genshinstrument.shared_instrument": "Экран общего инструмента", "button.genshinstrument.render_background": "Показать фоновые визуальные", - + "button.genshinstrument.accurate_accidentals": "Точные случайности", + "button.genshinstrument.accurate_accidentals.tooltip": "Во включенном состоянии обеспечивает точное отображение питч-аккомпанемента, используемого в схеме данного инструмента", "button.genshinstrument.instrumentOptions": "Варианты инструментов", - "button.genshinstrument.zither_options": "Варианты цитры", + "label.genshinstrument.zither_options": "Варианты цитры", "button.genshinstrument.label": "Наклейки для заметок", @@ -52,6 +53,7 @@ "button.genshinstrument.label.keyboard_layout": "Клавиатура", + "button.genshinstrument.label.note_name": "Название Ноты", "button.genshinstrument.label.none": "Без этикетки", diff --git a/src/main/resources/assets/genshinstrument/sounds.json b/src/main/resources/assets/genshinstrument/sounds.json index dd9a88d..3b9d3b2 100644 --- a/src/main/resources/assets/genshinstrument/sounds.json +++ b/src/main/resources/assets/genshinstrument/sounds.json @@ -434,5 +434,9 @@ "glorious_drum_ka": { "category": "record", "sounds": ["genshinstrument:glorious_drum/ka"] + }, + "glorious_drum_ka_stereo": { + "category": "record", + "sounds": ["genshinstrument:glorious_drum/ka.stereo"] } } \ No newline at end of file diff --git a/src/main/resources/assets/genshinstrument/sounds/glorious_drum/don.ogg b/src/main/resources/assets/genshinstrument/sounds/glorious_drum/don.ogg index 5c41642..3a5c106 100644 Binary files a/src/main/resources/assets/genshinstrument/sounds/glorious_drum/don.ogg and b/src/main/resources/assets/genshinstrument/sounds/glorious_drum/don.ogg differ diff --git a/src/main/resources/assets/genshinstrument/sounds/glorious_drum/ka.ogg b/src/main/resources/assets/genshinstrument/sounds/glorious_drum/ka.ogg index ef74b11..3e9556e 100644 Binary files a/src/main/resources/assets/genshinstrument/sounds/glorious_drum/ka.ogg and b/src/main/resources/assets/genshinstrument/sounds/glorious_drum/ka.ogg differ diff --git a/src/main/resources/assets/genshinstrument/sounds/glorious_drum/ka.stereo.ogg b/src/main/resources/assets/genshinstrument/sounds/glorious_drum/ka.stereo.ogg new file mode 100644 index 0000000..9078521 Binary files /dev/null and b/src/main/resources/assets/genshinstrument/sounds/glorious_drum/ka.stereo.ogg differ diff --git a/src/main/resources/assets/genshinstrument/textures/gui/instrument/background/clefs.png b/src/main/resources/assets/genshinstrument/textures/gui/instrument/background/clefs.png index 363c456..91d454e 100644 Binary files a/src/main/resources/assets/genshinstrument/textures/gui/instrument/background/clefs.png and b/src/main/resources/assets/genshinstrument/textures/gui/instrument/background/clefs.png differ diff --git a/src/main/resources/assets/genshinstrument/textures/gui/instrument/floral_zither/note/accidentals.png b/src/main/resources/assets/genshinstrument/textures/gui/instrument/floral_zither/note/accidentals.png new file mode 100644 index 0000000..6b2d925 Binary files /dev/null and b/src/main/resources/assets/genshinstrument/textures/gui/instrument/floral_zither/note/accidentals.png differ diff --git a/src/main/resources/assets/genshinstrument/textures/gui/instrument/vintage_lyre/note/accidentals.png b/src/main/resources/assets/genshinstrument/textures/gui/instrument/vintage_lyre/note/accidentals.png new file mode 100644 index 0000000..40c0060 Binary files /dev/null and b/src/main/resources/assets/genshinstrument/textures/gui/instrument/vintage_lyre/note/accidentals.png differ diff --git a/src/main/resources/assets/genshinstrument/textures/gui/instrument/vintage_lyre/note/thing.png b/src/main/resources/assets/genshinstrument/textures/gui/instrument/vintage_lyre/note/thing.png deleted file mode 100644 index d53f8a1..0000000 Binary files a/src/main/resources/assets/genshinstrument/textures/gui/instrument/vintage_lyre/note/thing.png and /dev/null differ diff --git a/src/main/resources/assets/genshinstrument/textures/gui/instrument/windsong_lyre/note/accidentals.png b/src/main/resources/assets/genshinstrument/textures/gui/instrument/windsong_lyre/note/accidentals.png new file mode 100644 index 0000000..53fa390 Binary files /dev/null and b/src/main/resources/assets/genshinstrument/textures/gui/instrument/windsong_lyre/note/accidentals.png differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 1032714..59e4805 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "genshinstrument", - "version": "2.8", + "version": "3.0", "name": "Genshin Instruments", "description": "A mod that brings Genshin Impact's instruments to Minecraft!\nThis is my first ever published mod, and I am quite proud of it :')\nHope you enjoy it as much as I do!!", "authors": [