Skip to content

Commit 0dd108b

Browse files
committed
Implemented several NBS events
1 parent 46c3b0f commit 0dd108b

6 files changed

Lines changed: 213 additions & 28 deletions

File tree

src/main/java/net/raphimc/noteblocklib/format/nbs/NbsConverter.java

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
import net.raphimc.noteblocklib.format.nbs.model.NbsLayer;
2424
import net.raphimc.noteblocklib.format.nbs.model.NbsNote;
2525
import net.raphimc.noteblocklib.format.nbs.model.NbsSong;
26+
import net.raphimc.noteblocklib.format.nbs.model.event.NbsShowSavePopupEvent;
27+
import net.raphimc.noteblocklib.format.nbs.model.event.NbsToggleBackgroundAccentEvent;
28+
import net.raphimc.noteblocklib.format.nbs.model.event.NbsToggleRainbowEvent;
29+
import net.raphimc.noteblocklib.model.event.Event;
2630
import net.raphimc.noteblocklib.model.note.Note;
2731
import net.raphimc.noteblocklib.model.song.Song;
2832

@@ -82,26 +86,21 @@ public static NbsSong createSong(final Song song) {
8286
newSong.getCustomInstruments().replaceAll(NbsCustomInstrument::copy);
8387

8488
if (song.getTempoEvents().getTicks().size() > 1) {
85-
final NbsCustomInstrument tempoChangerInstrument = new NbsCustomInstrument();
86-
tempoChangerInstrument.setName(NbsDefinitions.TEMPO_CHANGER_CUSTOM_INSTRUMENT_NAME);
87-
final int instrumentId = newSong.getVanillaInstrumentCount() + newSong.getCustomInstruments().size();
88-
newSong.getCustomInstruments().add(tempoChangerInstrument);
89-
90-
final NbsLayer tempoChangerLayer = new NbsLayer();
91-
tempoChangerLayer.setName(NbsDefinitions.TEMPO_CHANGER_CUSTOM_INSTRUMENT_NAME);
92-
tempoChangerLayer.setVolume(0);
93-
newSong.getLayers().put(newSong.getLayers().size(), tempoChangerLayer);
94-
89+
final int instrumentId = addCustomInstrument(newSong, NbsDefinitions.TEMPO_CHANGER_CUSTOM_INSTRUMENT_NAME);
90+
final NbsLayer layer = addSilentLayer(newSong, NbsDefinitions.TEMPO_CHANGER_CUSTOM_INSTRUMENT_NAME);
9591
for (int tempoEventTick : song.getTempoEvents().getTicks()) {
96-
final float tps = song.getTempoEvents().get(tempoEventTick);
97-
final NbsNote tempoChangerNote = new NbsNote();
98-
tempoChangerNote.setInstrument(instrumentId);
99-
tempoChangerNote.setKey(NbsDefinitions.F_SHARP_4_KEY);
100-
tempoChangerNote.setPitch((short) Math.round(tps * 15F));
101-
tempoChangerLayer.getNotes().put(tempoEventTick, tempoChangerNote);
92+
final NbsNote note = new NbsNote();
93+
note.setInstrument(instrumentId);
94+
note.setKey(NbsDefinitions.F_SHARP_4_KEY);
95+
note.setPitch((short) Math.round(song.getTempoEvents().get(tempoEventTick) * 15F));
96+
layer.getNotes().put(tempoEventTick, note);
10297
}
10398
}
10499

100+
addEvents(song, newSong, NbsToggleRainbowEvent.class, NbsDefinitions.TOGGLE_RAINBOW_CUSTOM_INSTRUMENT_NAME);
101+
addEvents(song, newSong, NbsShowSavePopupEvent.class, NbsDefinitions.SHOW_SAVE_POPUP_CUSTOM_INSTRUMENT_NAME);
102+
addEvents(song, newSong, NbsToggleBackgroundAccentEvent.class, NbsDefinitions.TOGGLE_BACKGROUND_ACCENT_CUSTOM_INSTRUMENT_NAME);
103+
105104
newSong.setLayerCount((short) newSong.getLayers().size());
106105
newSong.setSourceFileName(song.getFileName());
107106

@@ -133,4 +132,37 @@ public static NbsSong createSong(final Song song) {
133132
return newSong;
134133
}
135134

135+
private static void addEvents(final Song song, final NbsSong newSong, final Class<? extends Event> eventClass, final String instrumentName) {
136+
if (song.getEvents().testEach(eventClass::isInstance)) {
137+
final int instrumentId = addCustomInstrument(newSong, instrumentName);
138+
final NbsLayer layer = addSilentLayer(newSong, instrumentName);
139+
for (int eventTick : song.getEvents().getTicks()) {
140+
for (Event event : song.getEvents().get(eventTick)) {
141+
if (eventClass.isInstance(event)) {
142+
final NbsNote note = new NbsNote();
143+
note.setInstrument(instrumentId);
144+
note.setKey(NbsDefinitions.F_SHARP_4_KEY);
145+
layer.getNotes().put(eventTick, note);
146+
}
147+
}
148+
}
149+
}
150+
}
151+
152+
private static int addCustomInstrument(final NbsSong song, final String name) {
153+
final NbsCustomInstrument instrument = new NbsCustomInstrument();
154+
instrument.setName(name);
155+
final int instrumentId = song.getVanillaInstrumentCount() + song.getCustomInstruments().size();
156+
song.getCustomInstruments().add(instrument);
157+
return instrumentId;
158+
}
159+
160+
private static NbsLayer addSilentLayer(final NbsSong song, final String name) {
161+
final NbsLayer layer = new NbsLayer();
162+
layer.setName(name);
163+
layer.setVolume(0);
164+
song.getLayers().put(song.getLayers().size(), layer);
165+
return layer;
166+
}
167+
136168
}

src/main/java/net/raphimc/noteblocklib/format/nbs/NbsIo.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,17 @@
2525
import net.raphimc.noteblocklib.format.nbs.model.NbsLayer;
2626
import net.raphimc.noteblocklib.format.nbs.model.NbsNote;
2727
import net.raphimc.noteblocklib.format.nbs.model.NbsSong;
28+
import net.raphimc.noteblocklib.format.nbs.model.event.NbsShowSavePopupEvent;
29+
import net.raphimc.noteblocklib.format.nbs.model.event.NbsToggleBackgroundAccentEvent;
30+
import net.raphimc.noteblocklib.format.nbs.model.event.NbsToggleRainbowEvent;
2831
import net.raphimc.noteblocklib.model.note.Note;
2932
import net.raphimc.noteblocklib.util.MathUtil;
3033

3134
import java.io.*;
32-
import java.util.*;
35+
import java.util.IdentityHashMap;
36+
import java.util.Locale;
37+
import java.util.Map;
38+
import java.util.TreeMap;
3339

3440
import static net.raphimc.noteblocklib.format.nbs.NbsDefinitions.*;
3541

@@ -132,7 +138,6 @@ public static NbsSong readSong(final InputStream is, final String fileName) thro
132138
}
133139
}
134140

135-
final List<NbsCustomInstrument> customInstruments = song.getCustomInstruments();
136141
if (dis.available() > 0) {
137142
final int customInstrumentCount = dis.readUnsignedByte();
138143
for (int i = 0; i < customInstrumentCount; i++) {
@@ -141,13 +146,13 @@ public static NbsSong readSong(final InputStream is, final String fileName) thro
141146
customInstrument.setSoundFilePath(readString(dis));
142147
customInstrument.setPitch(dis.readUnsignedByte());
143148
customInstrument.setPressKey(dis.readBoolean());
144-
customInstruments.add(customInstrument);
149+
song.getCustomInstruments().add(customInstrument);
145150
}
146151
}
147152

148153
{ // Fill generalized song structure with data
149-
final Map<NbsCustomInstrument, NbsCustomInstrument> customInstrumentMap = new IdentityHashMap<>(customInstruments.size()); // Cache map to avoid creating new instances for each note
150-
for (NbsCustomInstrument customInstrument : customInstruments) {
154+
final Map<NbsCustomInstrument, NbsCustomInstrument> customInstrumentMap = new IdentityHashMap<>(song.getCustomInstruments().size()); // Cache map to avoid creating new instances for each note
155+
for (NbsCustomInstrument customInstrument : song.getCustomInstruments()) {
151156
customInstrumentMap.put(customInstrument, customInstrument.copy().setPitch(F_SHARP_4_KEY));
152157
}
153158

@@ -170,13 +175,14 @@ public static NbsSong readSong(final InputStream is, final String fileName) thro
170175
if (nbsNote.getInstrument() < song.getVanillaInstrumentCount()) {
171176
note.setInstrument(MinecraftInstrument.fromNbsId(nbsNote.getInstrument()));
172177
} else {
173-
final NbsCustomInstrument nbsCustomInstrument = customInstruments.get(nbsNote.getInstrument() - song.getVanillaInstrumentCount());
178+
final NbsCustomInstrument nbsCustomInstrument = song.getCustomInstruments().get(nbsNote.getInstrument() - song.getVanillaInstrumentCount());
174179
if (song.getVersion() >= 4) {
175180
if (TEMPO_CHANGER_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
176181
song.getTempoEvents().set(noteEntry.getKey(), Math.abs(nbsNote.getPitch() / 15F));
177182
continue;
178183
}
179184
if (TOGGLE_RAINBOW_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
185+
song.getEvents().add(noteEntry.getKey(), NbsToggleRainbowEvent.INSTANCE);
180186
continue;
181187
}
182188
}
@@ -185,12 +191,14 @@ public static NbsSong readSong(final InputStream is, final String fileName) thro
185191
continue; // TODO: Implement sound stopper support
186192
}
187193
if (SHOW_SAVE_POPUP_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
194+
song.getEvents().add(noteEntry.getKey(), NbsShowSavePopupEvent.INSTANCE);
188195
continue;
189196
}
190197
if (nbsCustomInstrument.getNameOr("").toLowerCase(Locale.ROOT).contains(CHANGE_COLOR_CUSTOM_INSTRUMENT_NAME.toLowerCase(Locale.ROOT))) {
191198
continue;
192199
}
193200
if (TOGGLE_BACKGROUND_ACCENT_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
201+
song.getEvents().add(noteEntry.getKey(), NbsToggleBackgroundAccentEvent.INSTANCE);
194202
continue;
195203
}
196204
}
@@ -327,13 +335,11 @@ public static void writeSong(final NbsSong song, final OutputStream os) throws I
327335
}
328336

329337
private static String readString(final LittleEndianDataInputStream dis) throws IOException {
330-
int length = dis.readInt();
331-
final StringBuilder builder = new StringBuilder(length);
332-
while (length > 0) {
333-
builder.append((char) dis.readByte());
334-
length--;
338+
final char[] buffer = new char[dis.readInt()];
339+
for (int i = 0; i < buffer.length; i++) {
340+
buffer[i] = (char) dis.readUnsignedByte();
335341
}
336-
return builder.toString();
342+
return new String(buffer);
337343
}
338344

339345
private static void writeString(final LittleEndianDataOutputStream dos, final String string) throws IOException {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* This file is part of NoteBlockLib - https://github.com/RaphiMC/NoteBlockLib
3+
* Copyright (C) 2022-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.noteblocklib.format.nbs.model.event;
19+
20+
import net.raphimc.noteblocklib.model.event.Event;
21+
22+
public interface NbsEvent extends Event {
23+
24+
@Override
25+
NbsEvent copy();
26+
27+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* This file is part of NoteBlockLib - https://github.com/RaphiMC/NoteBlockLib
3+
* Copyright (C) 2022-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.noteblocklib.format.nbs.model.event;
19+
20+
public class NbsShowSavePopupEvent implements NbsEvent {
21+
22+
public static final NbsShowSavePopupEvent INSTANCE = new NbsShowSavePopupEvent();
23+
24+
@Override
25+
public NbsEvent copy() {
26+
return this;
27+
}
28+
29+
@Override
30+
public boolean equals(Object o) {
31+
return o != null && getClass() == o.getClass();
32+
}
33+
34+
@Override
35+
public int hashCode() {
36+
return NbsShowSavePopupEvent.class.hashCode();
37+
}
38+
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* This file is part of NoteBlockLib - https://github.com/RaphiMC/NoteBlockLib
3+
* Copyright (C) 2022-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.noteblocklib.format.nbs.model.event;
19+
20+
public class NbsToggleBackgroundAccentEvent implements NbsEvent {
21+
22+
public static final NbsToggleBackgroundAccentEvent INSTANCE = new NbsToggleBackgroundAccentEvent();
23+
24+
@Override
25+
public NbsEvent copy() {
26+
return this;
27+
}
28+
29+
@Override
30+
public boolean equals(Object o) {
31+
return o != null && getClass() == o.getClass();
32+
}
33+
34+
@Override
35+
public int hashCode() {
36+
return NbsToggleBackgroundAccentEvent.class.hashCode();
37+
}
38+
39+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* This file is part of NoteBlockLib - https://github.com/RaphiMC/NoteBlockLib
3+
* Copyright (C) 2022-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.noteblocklib.format.nbs.model.event;
19+
20+
/**
21+
* Event, which toggles a rainbow color effect for some UI elements.
22+
*/
23+
public class NbsToggleRainbowEvent implements NbsEvent {
24+
25+
public static final NbsToggleRainbowEvent INSTANCE = new NbsToggleRainbowEvent();
26+
27+
@Override
28+
public NbsEvent copy() {
29+
return this;
30+
}
31+
32+
@Override
33+
public boolean equals(Object o) {
34+
return o != null && getClass() == o.getClass();
35+
}
36+
37+
@Override
38+
public int hashCode() {
39+
return NbsToggleRainbowEvent.class.hashCode();
40+
}
41+
42+
}

0 commit comments

Comments
 (0)