sonolus-next-rush-plus-engine 1.3.3 → 1.3.4-kizuruki

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
Binary file
package/dist/index.d.ts CHANGED
@@ -1,7 +1,12 @@
1
- export { susToUSC } from './sus/convert.js';
2
- export { uscToLevelData } from './usc/convert.js';
1
+ import { LevelData } from '@sonolus/core';
2
+ import { mmwsToUSC } from './mmw/convert.js';
3
+ import { susToUSC } from './sus/convert.js';
4
+ import { uscToLevelData } from './usc/convert.js';
5
+ import { USC } from './usc/index.js';
6
+ export { susToUSC, mmwsToUSC, uscToLevelData };
3
7
  export * from './usc/index.js';
4
- export declare const version = "1.3.3";
8
+ export declare const convertToLevelData: (input: string | Uint8Array | USC | LevelData, offset?: number) => LevelData;
9
+ export declare const version = "1.3.4-kizuruki";
5
10
  export declare const databaseEngineItem: {
6
11
  readonly name: "next-rush-plus";
7
12
  readonly version: 13;
package/dist/index.js CHANGED
@@ -1,7 +1,54 @@
1
- export { susToUSC } from './sus/convert.js';
2
- export { uscToLevelData } from './usc/convert.js';
1
+ import { mmwsToUSC } from './mmw/convert.js';
2
+ import { susToUSC } from './sus/convert.js';
3
+ import { uscToLevelData } from './usc/convert.js';
4
+ export { susToUSC, mmwsToUSC, uscToLevelData };
3
5
  export * from './usc/index.js';
4
- export const version = '1.3.3';
6
+ export const convertToLevelData = (input, offset = 0) => {
7
+ if (isLevelData(input)) {
8
+ return input;
9
+ }
10
+ let usc;
11
+ if (isUSC(input)) {
12
+ usc = input;
13
+ }
14
+ else if (input instanceof Uint8Array) {
15
+ usc = mmwsToUSC(input);
16
+ }
17
+ else if (typeof input === 'string') {
18
+ try {
19
+ const parsed = JSON.parse(input);
20
+ if (isLevelData(parsed)) {
21
+ return parsed;
22
+ }
23
+ if (isUSC(parsed)) {
24
+ usc = parsed;
25
+ }
26
+ else {
27
+ usc = susToUSC(input);
28
+ }
29
+ }
30
+ catch {
31
+ usc = susToUSC(input);
32
+ }
33
+ }
34
+ else {
35
+ throw new Error('Unsupported input type: Input must be string(SUS/USC/LevelData), Uint8Array(MMWS), or USC/LevelData object.');
36
+ }
37
+ return uscToLevelData(usc, offset);
38
+ };
39
+ function isUSC(data) {
40
+ return (typeof data === 'object' &&
41
+ data !== null &&
42
+ 'objects' in data &&
43
+ Array.isArray(data.objects));
44
+ }
45
+ function isLevelData(data) {
46
+ return (typeof data === 'object' &&
47
+ data !== null &&
48
+ 'entities' in data &&
49
+ Array.isArray(data.entities));
50
+ }
51
+ export const version = '1.3.4-kizuruki';
5
52
  export const databaseEngineItem = {
6
53
  name: 'next-rush-plus',
7
54
  version: 13,
@@ -0,0 +1,101 @@
1
+ declare const FlickType: readonly ["none", "up", "left", "right"];
2
+ type FlickType = (typeof FlickType)[number];
3
+ declare const StepType: readonly ["visible", "hidden", "ignored"];
4
+ type StepType = (typeof StepType)[number];
5
+ declare const EaseType: readonly ["linear", "easeIn", "easeOut", "easeInOut", "easeOutIn"];
6
+ export type EaseType = (typeof EaseType)[number];
7
+ export type Score = {
8
+ metadata: {
9
+ title: string;
10
+ author: string;
11
+ artist: string;
12
+ musicFile: string;
13
+ musicOffset: number;
14
+ jacketFile: string;
15
+ };
16
+ events: {
17
+ timeSignatures: {
18
+ measure: number;
19
+ numerator: number;
20
+ denominator: number;
21
+ }[];
22
+ bpmChanges: {
23
+ tick: number;
24
+ bpm: number;
25
+ }[];
26
+ hispeedChanges: {
27
+ tick: number;
28
+ speed: number;
29
+ layer: number;
30
+ }[];
31
+ skills: number[];
32
+ fever: {
33
+ start: number;
34
+ end: number;
35
+ };
36
+ };
37
+ taps: {
38
+ tick: number;
39
+ lane: number;
40
+ width: number;
41
+ flickType: FlickType;
42
+ flags: {
43
+ critical: boolean;
44
+ friction: boolean;
45
+ };
46
+ layer: number;
47
+ }[];
48
+ holds: {
49
+ flags: {
50
+ startHidden: boolean;
51
+ endHidden: boolean;
52
+ guide: boolean;
53
+ };
54
+ start: {
55
+ tick: number;
56
+ lane: number;
57
+ width: number;
58
+ flags: {
59
+ critical: boolean;
60
+ friction: boolean;
61
+ };
62
+ layer: number;
63
+ ease: EaseType;
64
+ };
65
+ fadeType: number;
66
+ guideColor: number;
67
+ steps: {
68
+ tick: number;
69
+ lane: number;
70
+ width: number;
71
+ type: StepType;
72
+ ease: EaseType;
73
+ layer: number;
74
+ }[];
75
+ end: {
76
+ tick: number;
77
+ lane: number;
78
+ width: number;
79
+ flickType: FlickType;
80
+ flags: {
81
+ critical: boolean;
82
+ friction: boolean;
83
+ };
84
+ layer: number;
85
+ };
86
+ }[];
87
+ damages: {
88
+ tick: number;
89
+ lane: number;
90
+ width: number;
91
+ flickType: FlickType;
92
+ flags: {
93
+ critical: boolean;
94
+ friction: boolean;
95
+ };
96
+ layer: number;
97
+ }[];
98
+ numLayers: number;
99
+ };
100
+ export declare const analyze: (mmws: Uint8Array) => Score;
101
+ export {};
@@ -0,0 +1,212 @@
1
+ import BinarySeeker from '@sevenc-nanashi/binaryseeker';
2
+ const FlickType = ['none', 'up', 'left', 'right'];
3
+ const StepType = ['visible', 'hidden', 'ignored'];
4
+ const EaseType = ['linear', 'easeIn', 'easeOut', 'easeInOut', 'easeOutIn'];
5
+ export const analyze = (mmws) => {
6
+ const buffer = new BinarySeeker(mmws.buffer);
7
+ const header = buffer.readString();
8
+ if (header !== 'MMWS' && header !== 'CCMMWS') {
9
+ throw new Error('Invalid MMWS file');
10
+ }
11
+ const version = buffer.readInt16LE();
12
+ let cyanvasVersion = buffer.readInt16LE();
13
+ if (version < 3) {
14
+ throw new Error('Unsupported MMWS version');
15
+ }
16
+ if (header === 'CCMMWS' && cyanvasVersion === 0) {
17
+ cyanvasVersion = 1;
18
+ }
19
+ const metadataPointer = buffer.readUInt32LE();
20
+ const eventsPointer = buffer.readUInt32LE();
21
+ const tapsPointer = buffer.readUInt32LE();
22
+ const holdsPointer = buffer.readUInt32LE();
23
+ const damagesPointer = cyanvasVersion > 0 ? buffer.readUInt32LE() : 0;
24
+ const layersPointer = cyanvasVersion >= 4 ? buffer.readUInt32LE() : 0;
25
+ // const waypointsPointer = cyanvasVersion >= 5 ? buffer.readUInt32LE() : 0
26
+ buffer.seek(metadataPointer);
27
+ const metadata = {
28
+ title: buffer.readString(),
29
+ author: buffer.readString(),
30
+ artist: buffer.readString(),
31
+ musicFile: buffer.readString(),
32
+ musicOffset: buffer.readFloat32LE(),
33
+ jacketFile: buffer.readString(),
34
+ };
35
+ buffer.seek(eventsPointer);
36
+ const events = {
37
+ timeSignatures: [],
38
+ bpmChanges: [],
39
+ hispeedChanges: [],
40
+ skills: [],
41
+ fever: {
42
+ start: 0,
43
+ end: 0,
44
+ },
45
+ };
46
+ const timeSignaturesCount = buffer.readInt32LE();
47
+ for (let i = 0; i < timeSignaturesCount; i++) {
48
+ events.timeSignatures.push({
49
+ measure: buffer.readInt32LE(),
50
+ numerator: buffer.readInt32LE(),
51
+ denominator: buffer.readInt32LE(),
52
+ });
53
+ }
54
+ const bpmChangesCount = buffer.readInt32LE();
55
+ for (let i = 0; i < bpmChangesCount; i++) {
56
+ events.bpmChanges.push({
57
+ tick: buffer.readInt32LE(),
58
+ bpm: buffer.readFloat32LE(),
59
+ });
60
+ }
61
+ const hispeedChangesCount = buffer.readInt32LE();
62
+ for (let i = 0; i < hispeedChangesCount; i++) {
63
+ events.hispeedChanges.push({
64
+ tick: buffer.readInt32LE(),
65
+ speed: buffer.readFloat32LE(),
66
+ layer: cyanvasVersion >= 4 ? buffer.readInt32LE() : 0,
67
+ });
68
+ }
69
+ const skillsCount = buffer.readInt32LE();
70
+ for (let i = 0; i < skillsCount; i++) {
71
+ events.skills.push(buffer.readInt32LE());
72
+ }
73
+ events.fever.start = buffer.readInt32LE();
74
+ events.fever.end = buffer.readInt32LE();
75
+ buffer.seek(tapsPointer);
76
+ const taps = [];
77
+ const tapsCount = buffer.readInt32LE();
78
+ for (let i = 0; i < tapsCount; i++) {
79
+ const tick = buffer.readInt32LE();
80
+ const lane = buffer.readInt32LE();
81
+ const width = buffer.readInt32LE();
82
+ const layer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
83
+ const flickType = FlickType[buffer.readInt32LE()];
84
+ const flags = buffer.readInt32LE();
85
+ taps.push({
86
+ tick,
87
+ lane,
88
+ width,
89
+ flickType,
90
+ flags: {
91
+ critical: !!(flags & (1 << 0)),
92
+ friction: !!(flags & (1 << 1)),
93
+ },
94
+ layer,
95
+ });
96
+ }
97
+ buffer.seek(holdsPointer);
98
+ const holds = [];
99
+ const holdsCount = buffer.readInt32LE();
100
+ for (let i = 0; i < holdsCount; i++) {
101
+ const holdFlags = version >= 4 ? buffer.readInt32LE() : 0;
102
+ const startTick = buffer.readInt32LE();
103
+ const startLane = buffer.readInt32LE();
104
+ const startWidth = buffer.readInt32LE();
105
+ const startLayer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
106
+ const startFlags = buffer.readInt32LE();
107
+ const startEase = EaseType[buffer.readInt32LE()];
108
+ const fadeType = cyanvasVersion >= 2 ? buffer.readInt32LE() : 0;
109
+ const guideColor = cyanvasVersion >= 3 ? buffer.readInt32LE() : startFlags & (1 << 0) ? 4 : 2;
110
+ const stepsCount = buffer.readInt32LE();
111
+ const steps = [];
112
+ for (let j = 0; j < stepsCount; j++) {
113
+ const tick = buffer.readInt32LE();
114
+ const lane = buffer.readInt32LE();
115
+ const width = buffer.readInt32LE();
116
+ const layer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
117
+ buffer.readInt32LE(); // unused flags
118
+ const type = StepType[buffer.readInt32LE()];
119
+ const ease = EaseType[buffer.readInt32LE()];
120
+ steps.push({
121
+ tick,
122
+ lane,
123
+ width,
124
+ type,
125
+ ease,
126
+ layer,
127
+ });
128
+ }
129
+ const endTick = buffer.readInt32LE();
130
+ const endLane = buffer.readInt32LE();
131
+ const endWidth = buffer.readInt32LE();
132
+ const endLayer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
133
+ const endFlickType = FlickType[buffer.readInt32LE()];
134
+ const endFlags = buffer.readInt32LE();
135
+ holds.push({
136
+ flags: {
137
+ startHidden: !!(holdFlags & (1 << 0)),
138
+ endHidden: !!(holdFlags & (1 << 1)),
139
+ guide: !!(holdFlags & (1 << 2)),
140
+ },
141
+ start: {
142
+ tick: startTick,
143
+ lane: startLane,
144
+ width: startWidth,
145
+ ease: startEase,
146
+ flags: {
147
+ critical: !!(startFlags & (1 << 0)),
148
+ friction: !!(startFlags & (1 << 1)),
149
+ },
150
+ layer: startLayer,
151
+ },
152
+ fadeType,
153
+ guideColor,
154
+ steps,
155
+ end: {
156
+ tick: endTick,
157
+ lane: endLane,
158
+ width: endWidth,
159
+ flags: {
160
+ critical: !!(endFlags & (1 << 0)),
161
+ friction: !!(endFlags & (1 << 1)),
162
+ },
163
+ flickType: endFlickType,
164
+ layer: endLayer,
165
+ },
166
+ });
167
+ }
168
+ events.timeSignatures.sort((a, b) => a.measure - b.measure);
169
+ events.bpmChanges.sort((a, b) => a.tick - b.tick);
170
+ events.hispeedChanges.sort((a, b) => a.tick - b.tick);
171
+ events.skills.sort((a, b) => a - b);
172
+ taps.sort((a, b) => a.tick - b.tick);
173
+ holds.sort((a, b) => a.start.tick - b.start.tick);
174
+ const damages = [];
175
+ if (cyanvasVersion >= 1) {
176
+ buffer.seek(damagesPointer);
177
+ const damagesCount = buffer.readInt32LE();
178
+ for (let i = 0; i < damagesCount; i++) {
179
+ const tick = buffer.readInt32LE();
180
+ const lane = buffer.readInt32LE();
181
+ const width = buffer.readInt32LE();
182
+ const layer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
183
+ const flickType = FlickType[buffer.readInt32LE()];
184
+ const flags = buffer.readInt32LE();
185
+ damages.push({
186
+ tick,
187
+ lane,
188
+ width,
189
+ flickType,
190
+ layer,
191
+ flags: {
192
+ critical: !!(flags & (1 << 0)),
193
+ friction: !!(flags & (1 << 1)),
194
+ },
195
+ });
196
+ }
197
+ damages.sort((a, b) => a.tick - b.tick);
198
+ }
199
+ let numLayers = 1;
200
+ if (cyanvasVersion >= 4) {
201
+ buffer.seek(layersPointer);
202
+ numLayers = buffer.readInt32LE();
203
+ }
204
+ return {
205
+ metadata,
206
+ events,
207
+ taps,
208
+ holds,
209
+ damages,
210
+ numLayers,
211
+ };
212
+ };
@@ -0,0 +1,9 @@
1
+ import { USC } from '../usc/index.js';
2
+ /**
3
+ * Convert MMWS or CCMMWS to a USC
4
+ */
5
+ export declare const mmwsToUSC: (mmws: Uint8Array) => USC;
6
+ /**
7
+ * Convert CCMMWS to a USC
8
+ */
9
+ export declare const ccmmwsToUSC: (mmws: Uint8Array) => USC;
@@ -0,0 +1,161 @@
1
+ import { USCColor, } from '../usc/index.js';
2
+ import { analyze } from './analyze.js';
3
+ const mmwsEaseToUSCEase = {
4
+ linear: 'linear',
5
+ easeOut: 'out',
6
+ easeIn: 'in',
7
+ easeInOut: 'inout',
8
+ easeOutIn: 'outin',
9
+ };
10
+ const ticksPerBeat = 480;
11
+ const laneToUSCLane = ({ lane, width }) => {
12
+ return lane - 6 + width / 2;
13
+ };
14
+ /**
15
+ * Convert MMWS or CCMMWS to a USC
16
+ */
17
+ export const mmwsToUSC = (mmws) => {
18
+ const score = analyze(mmws);
19
+ const usc = {
20
+ objects: [],
21
+ offset: score.metadata.musicOffset / -1000,
22
+ };
23
+ for (const bpmChange of score.events.bpmChanges) {
24
+ usc.objects.push({
25
+ type: 'bpm',
26
+ beat: bpmChange.tick / ticksPerBeat,
27
+ bpm: bpmChange.bpm,
28
+ });
29
+ }
30
+ const tsGroups = new Map();
31
+ for (let i = 0; i < score.numLayers; i++) {
32
+ tsGroups.set(i, []);
33
+ }
34
+ for (const hispeedChange of score.events.hispeedChanges) {
35
+ const key = hispeedChange.layer;
36
+ if (!tsGroups.has(key)) {
37
+ throw new Error('Invalid layer');
38
+ }
39
+ tsGroups.get(key).push({
40
+ beat: hispeedChange.tick / ticksPerBeat,
41
+ timeScale: hispeedChange.speed,
42
+ });
43
+ }
44
+ for (const changes of tsGroups.values()) {
45
+ usc.objects.push({
46
+ type: 'timeScaleGroup',
47
+ changes,
48
+ });
49
+ }
50
+ for (const tap of score.taps) {
51
+ const uscTap = {
52
+ type: 'single',
53
+ beat: tap.tick / ticksPerBeat,
54
+ timeScaleGroup: tap.layer,
55
+ critical: tap.flags.critical,
56
+ lane: laneToUSCLane(tap),
57
+ size: tap.width / 2,
58
+ trace: tap.flags.friction,
59
+ };
60
+ if (tap.flickType !== 'none') {
61
+ uscTap.direction = tap.flickType;
62
+ }
63
+ usc.objects.push(uscTap);
64
+ }
65
+ for (const hold of score.holds) {
66
+ const uscStartNote = {
67
+ type: 'start',
68
+ beat: hold.start.tick / ticksPerBeat,
69
+ timeScaleGroup: hold.start.layer,
70
+ critical: hold.start.flags.critical,
71
+ ease: mmwsEaseToUSCEase[hold.start.ease],
72
+ lane: laneToUSCLane(hold.start),
73
+ size: hold.start.width / 2,
74
+ judgeType: hold.flags.startHidden
75
+ ? 'none'
76
+ : hold.start.flags.friction
77
+ ? 'trace'
78
+ : 'normal',
79
+ };
80
+ const uscEndNote = {
81
+ type: 'end',
82
+ beat: hold.end.tick / ticksPerBeat,
83
+ timeScaleGroup: hold.end.layer,
84
+ critical: hold.end.flags.critical,
85
+ lane: laneToUSCLane(hold.end),
86
+ size: hold.end.width / 2,
87
+ judgeType: hold.flags.endHidden ? 'none' : hold.end.flags.friction ? 'trace' : 'normal',
88
+ };
89
+ if (hold.end.flickType !== 'none') {
90
+ uscEndNote.direction = hold.end.flickType;
91
+ }
92
+ if (hold.flags.guide) {
93
+ const uscGuide = {
94
+ type: 'guide',
95
+ fade: hold.fadeType === 0 ? 'out' : hold.fadeType === 1 ? 'none' : 'in',
96
+ color: Object.entries(USCColor).find(([, i]) => i === hold.guideColor)[0],
97
+ midpoints: [hold.start, ...hold.steps, hold.end].map((step) => ({
98
+ beat: step.tick / ticksPerBeat,
99
+ lane: laneToUSCLane(step),
100
+ size: step.width / 2,
101
+ timeScaleGroup: step.layer,
102
+ ease: 'ease' in step ? mmwsEaseToUSCEase[step.ease] : 'linear',
103
+ })),
104
+ };
105
+ usc.objects.push(uscGuide);
106
+ }
107
+ else {
108
+ const uscSlide = {
109
+ type: 'slide',
110
+ critical: hold.start.flags.critical,
111
+ connections: [
112
+ uscStartNote,
113
+ ...hold.steps.map((step) => {
114
+ const beat = step.tick / ticksPerBeat;
115
+ const lane = laneToUSCLane(step);
116
+ const size = step.width / 2;
117
+ if (step.type === 'ignored') {
118
+ return {
119
+ type: 'attach',
120
+ beat,
121
+ critical: hold.start.flags.critical,
122
+ timeScaleGroup: step.layer,
123
+ };
124
+ }
125
+ else {
126
+ const uscStep = {
127
+ type: 'tick',
128
+ beat,
129
+ timeScaleGroup: step.layer,
130
+ lane,
131
+ size,
132
+ ease: mmwsEaseToUSCEase[step.ease],
133
+ };
134
+ if (step.type === 'visible') {
135
+ uscStep.critical = hold.start.flags.critical;
136
+ }
137
+ return uscStep;
138
+ }
139
+ }),
140
+ uscEndNote,
141
+ ],
142
+ };
143
+ usc.objects.push(uscSlide);
144
+ }
145
+ }
146
+ for (const damage of score.damages) {
147
+ const uscDamage = {
148
+ type: 'damage',
149
+ beat: damage.tick / ticksPerBeat,
150
+ timeScaleGroup: damage.layer,
151
+ lane: laneToUSCLane(damage),
152
+ size: damage.width / 2,
153
+ };
154
+ usc.objects.push(uscDamage);
155
+ }
156
+ return usc;
157
+ };
158
+ /**
159
+ * Convert CCMMWS to a USC
160
+ */
161
+ export const ccmmwsToUSC = mmwsToUSC;
@@ -357,8 +357,17 @@ export const uscToLevelData = (usc, offset = 0) => {
357
357
  let prevMidpointIntermediate = null;
358
358
  let headMidpointIntermediate = null;
359
359
  const guideConnectors = [];
360
+ const stepSize = Math.max(1, connections.length - 1);
361
+ let stepIdx = 0;
360
362
  for (const midpointNote of connections) {
361
363
  const timeScaleGroupRef = timeScaleGroupIntermediates[midpointNote.timeScaleGroup ?? 0];
364
+ let segmentAlpha = 1;
365
+ if (guideNote.fade === 'out') {
366
+ segmentAlpha = 1 - 0.8 * (stepIdx / stepSize);
367
+ }
368
+ else if (guideNote.fade === 'in') {
369
+ segmentAlpha = 1 - 0.8 * ((stepSize - stepIdx) / stepSize);
370
+ }
362
371
  const midpointIntermediate = createIntermediate('AnchorNote', {
363
372
  '#BEAT': midpointNote.beat,
364
373
  lane: midpointNote.lane,
@@ -366,9 +375,9 @@ export const uscToLevelData = (usc, offset = 0) => {
366
375
  direction: SONOLUS_DIRECTIONS.up,
367
376
  isAttached: 0,
368
377
  connectorEase: SONOLUS_CONNECTOR_EASES[mapUscEaseToSonolusEase(midpointNote.ease)],
369
- isSeparator: 0,
378
+ isSeparator: 1,
370
379
  segmentKind: SONOLUS_GUIDE_COLORS[guideNote.color],
371
- segmentAlpha: 1,
380
+ segmentAlpha: segmentAlpha,
372
381
  '#TIMESCALE_GROUP': timeScaleGroupRef,
373
382
  });
374
383
  if (headMidpointIntermediate === null) {
@@ -383,6 +392,7 @@ export const uscToLevelData = (usc, offset = 0) => {
383
392
  prevMidpointIntermediate.data['next'] = midpointIntermediate;
384
393
  }
385
394
  prevMidpointIntermediate = midpointIntermediate;
395
+ stepIdx++;
386
396
  }
387
397
  if (!headMidpointIntermediate || !prevMidpointIntermediate) {
388
398
  continue;
@@ -393,16 +403,6 @@ export const uscToLevelData = (usc, offset = 0) => {
393
403
  connectorIntermediate.data['activeHead'] = headMidpointIntermediate;
394
404
  connectorIntermediate.data['activeTail'] = prevMidpointIntermediate;
395
405
  }
396
- switch (guideNote.fade) {
397
- case 'in':
398
- headMidpointIntermediate.data['segmentAlpha'] = 0;
399
- break;
400
- case 'out':
401
- prevMidpointIntermediate.data['segmentAlpha'] = 0;
402
- break;
403
- case 'none':
404
- break;
405
- }
406
406
  }
407
407
  simLineEligibleNotes.sort((noteA, noteB) => {
408
408
  const beatA = noteA.data['#BEAT'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonolus-next-rush-plus-engine",
3
- "version": "1.3.3",
3
+ "version": "1.3.4-kizuruki",
4
4
  "description": "A new Project Sekai inspired engine for Sonolus",
5
5
  "author": "Hyeon2",
6
6
  "repository": {
@@ -33,6 +33,7 @@
33
33
  "build": "tsc -p . && node ./build.js"
34
34
  },
35
35
  "dependencies": {
36
+ "@sevenc-nanashi/binaryseeker": "npm:@jsr/sevenc-nanashi__binaryseeker@^1.2.1",
36
37
  "@sonolus/core": "~7.14.2"
37
38
  },
38
39
  "devDependencies": {