sonolus-next-rush-engine 0.1.0
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.
- package/LICENSE.txt +21 -0
- package/README.md +38 -0
- package/dist/EngineConfiguration +0 -0
- package/dist/EnginePlayData +0 -0
- package/dist/EnginePreviewData +0 -0
- package/dist/EngineRom +0 -0
- package/dist/EngineTutorialData +0 -0
- package/dist/EngineWatchData +0 -0
- package/dist/LevelData/analyze.d.ts +3 -0
- package/dist/LevelData/analyze.js +7 -0
- package/dist/extended/analyze.d.ts +3 -0
- package/dist/extended/analyze.js +8 -0
- package/dist/extended/convert.d.ts +12 -0
- package/dist/extended/convert.js +453 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +84 -0
- package/dist/lib/binaryseeker/mod.d.ts +14 -0
- package/dist/lib/binaryseeker/mod.js +9 -0
- package/dist/lib/binaryseeker/reader.d.ts +157 -0
- package/dist/lib/binaryseeker/reader.js +305 -0
- package/dist/lib/binaryseeker/writer.d.ts +171 -0
- package/dist/lib/binaryseeker/writer.js +360 -0
- package/dist/mmw/analyze.d.ts +109 -0
- package/dist/mmw/analyze.js +256 -0
- package/dist/mmw/convert.d.ts +14 -0
- package/dist/mmw/convert.js +681 -0
- package/dist/sus/analyze.d.ts +32 -0
- package/dist/sus/analyze.js +287 -0
- package/dist/sus/convert.d.ts +5 -0
- package/dist/sus/convert.js +320 -0
- package/dist/thumbnail.png +0 -0
- package/dist/usc/analyze.d.ts +3 -0
- package/dist/usc/analyze.js +7 -0
- package/dist/usc/convert.d.ts +4 -0
- package/dist/usc/convert.js +496 -0
- package/dist/usc/index.d.ts +112 -0
- package/dist/usc/index.js +21 -0
- package/package.json +47 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { BinarySeeker } from '../lib/binaryseeker/mod.js';
|
|
2
|
+
const FlickType = ['none', 'up', 'left', 'right', 'down', 'down_left', 'down_right'];
|
|
3
|
+
const StepType = ['visible', 'hidden', 'ignored'];
|
|
4
|
+
const EaseType = ['linear', 'easeIn', 'easeOut', 'easeInOut', 'easeOutIn'];
|
|
5
|
+
/** Detect MMWS Type */
|
|
6
|
+
export const detectMMWSType = (mmws) => {
|
|
7
|
+
const buffer = new BinarySeeker(mmws.buffer);
|
|
8
|
+
const header = buffer.readString();
|
|
9
|
+
return header;
|
|
10
|
+
};
|
|
11
|
+
export const analyze = (mmws) => {
|
|
12
|
+
const buffer = new BinarySeeker(mmws.buffer);
|
|
13
|
+
const header = buffer.readString();
|
|
14
|
+
if (header !== 'MMWS' && header !== 'CCMMWS' && header !== 'UCMMWS') {
|
|
15
|
+
throw new Error('Invalid MMWS file');
|
|
16
|
+
}
|
|
17
|
+
let version = 0;
|
|
18
|
+
let cyanvasVersion = 0;
|
|
19
|
+
let untitledVersion = 0;
|
|
20
|
+
if (header === 'UCMMWS') {
|
|
21
|
+
untitledVersion = buffer.readInt32LE();
|
|
22
|
+
cyanvasVersion = 6;
|
|
23
|
+
version = 4;
|
|
24
|
+
}
|
|
25
|
+
else if (header === 'CCMMWS') {
|
|
26
|
+
cyanvasVersion = Math.max(buffer.readInt16LE(), 1);
|
|
27
|
+
version = buffer.readInt16LE();
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
version = buffer.readInt16LE();
|
|
31
|
+
cyanvasVersion = buffer.readInt16LE();
|
|
32
|
+
}
|
|
33
|
+
if (version < 3 && header !== 'UCMMWS') {
|
|
34
|
+
throw new Error('Unsupported MMWS version');
|
|
35
|
+
}
|
|
36
|
+
const metadataPointer = buffer.readUInt32LE();
|
|
37
|
+
const eventsPointer = buffer.readUInt32LE();
|
|
38
|
+
const tapsPointer = buffer.readUInt32LE();
|
|
39
|
+
const holdsPointer = buffer.readUInt32LE();
|
|
40
|
+
const damagesPointer = cyanvasVersion > 0 ? buffer.readUInt32LE() : 0;
|
|
41
|
+
const layersPointer = cyanvasVersion >= 4 ? buffer.readUInt32LE() : 0;
|
|
42
|
+
buffer.seek(metadataPointer);
|
|
43
|
+
const metadata = {
|
|
44
|
+
title: buffer.readString(),
|
|
45
|
+
author: buffer.readString(),
|
|
46
|
+
artist: buffer.readString(),
|
|
47
|
+
musicFile: buffer.readString(),
|
|
48
|
+
musicOffset: buffer.readFloat32LE(),
|
|
49
|
+
jacketFile: version >= 2 ? buffer.readString() : '',
|
|
50
|
+
};
|
|
51
|
+
if (cyanvasVersion >= 1) {
|
|
52
|
+
buffer.readInt32LE();
|
|
53
|
+
}
|
|
54
|
+
buffer.seek(eventsPointer);
|
|
55
|
+
const events = {
|
|
56
|
+
timeSignatures: [],
|
|
57
|
+
bpmChanges: [],
|
|
58
|
+
hispeedChanges: [],
|
|
59
|
+
skills: [],
|
|
60
|
+
fever: {
|
|
61
|
+
start: 0,
|
|
62
|
+
end: 0,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
const timeSignaturesCount = buffer.readInt32LE();
|
|
66
|
+
for (let i = 0; i < timeSignaturesCount; i++) {
|
|
67
|
+
events.timeSignatures.push({
|
|
68
|
+
measure: buffer.readInt32LE(),
|
|
69
|
+
numerator: buffer.readInt32LE(),
|
|
70
|
+
denominator: buffer.readInt32LE(),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const bpmChangesCount = buffer.readInt32LE();
|
|
74
|
+
for (let i = 0; i < bpmChangesCount; i++) {
|
|
75
|
+
events.bpmChanges.push({
|
|
76
|
+
tick: buffer.readInt32LE(),
|
|
77
|
+
bpm: buffer.readFloat32LE(),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (version >= 3) {
|
|
81
|
+
const hispeedChangesCount = buffer.readInt32LE();
|
|
82
|
+
for (let i = 0; i < hispeedChangesCount; i++) {
|
|
83
|
+
const tick = buffer.readInt32LE();
|
|
84
|
+
const speed = buffer.readFloat32LE();
|
|
85
|
+
const layer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
|
|
86
|
+
let skip = 0;
|
|
87
|
+
let ease = 0;
|
|
88
|
+
let hideNotes = false;
|
|
89
|
+
if (untitledVersion >= 2) {
|
|
90
|
+
skip = buffer.readFloat32LE();
|
|
91
|
+
ease = buffer.readInt16LE();
|
|
92
|
+
hideNotes = !!buffer.readInt16LE();
|
|
93
|
+
}
|
|
94
|
+
events.hispeedChanges.push({
|
|
95
|
+
tick,
|
|
96
|
+
speed,
|
|
97
|
+
layer,
|
|
98
|
+
skip,
|
|
99
|
+
ease,
|
|
100
|
+
hideNotes,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (version >= 2) {
|
|
105
|
+
const skillsCount = buffer.readInt32LE();
|
|
106
|
+
for (let i = 0; i < skillsCount; i++) {
|
|
107
|
+
const skillTick = buffer.readInt32LE();
|
|
108
|
+
events.skills.push(skillTick);
|
|
109
|
+
}
|
|
110
|
+
events.fever.start = buffer.readInt32LE();
|
|
111
|
+
events.fever.end = buffer.readInt32LE();
|
|
112
|
+
}
|
|
113
|
+
buffer.seek(tapsPointer);
|
|
114
|
+
const taps = [];
|
|
115
|
+
const tapsCount = buffer.readInt32LE();
|
|
116
|
+
for (let i = 0; i < tapsCount; i++) {
|
|
117
|
+
const tick = buffer.readInt32LE();
|
|
118
|
+
const lane = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
119
|
+
const width = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
120
|
+
const layer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
|
|
121
|
+
const flickTypeRaw = buffer.readInt32LE();
|
|
122
|
+
const flickType = FlickType[flickTypeRaw] || 'none';
|
|
123
|
+
const flags = buffer.readInt32LE();
|
|
124
|
+
taps.push({
|
|
125
|
+
tick,
|
|
126
|
+
lane,
|
|
127
|
+
width,
|
|
128
|
+
flickType,
|
|
129
|
+
flags: {
|
|
130
|
+
critical: !!(flags & (1 << 0)),
|
|
131
|
+
friction: !!(flags & (1 << 1)),
|
|
132
|
+
dummy: cyanvasVersion >= 6 && untitledVersion >= 1 ? !!(flags & (1 << 2)) : false,
|
|
133
|
+
},
|
|
134
|
+
layer,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
buffer.seek(holdsPointer);
|
|
138
|
+
const holds = [];
|
|
139
|
+
const holdsCount = buffer.readInt32LE();
|
|
140
|
+
for (let i = 0; i < holdsCount; i++) {
|
|
141
|
+
const holdFlags = version >= 4 ? buffer.readInt32LE() : 0;
|
|
142
|
+
const startTick = buffer.readInt32LE();
|
|
143
|
+
const startLane = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
144
|
+
const startWidth = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
145
|
+
const startLayer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
|
|
146
|
+
const startFlags = buffer.readInt32LE();
|
|
147
|
+
const startEase = EaseType[buffer.readInt32LE()];
|
|
148
|
+
const fadeType = cyanvasVersion >= 2 ? buffer.readInt32LE() : 0;
|
|
149
|
+
const guideColor = cyanvasVersion >= 3 ? buffer.readInt32LE() : startFlags & (1 << 0) ? 4 : 2;
|
|
150
|
+
const stepsCount = buffer.readInt32LE();
|
|
151
|
+
const steps = [];
|
|
152
|
+
for (let j = 0; j < stepsCount; j++) {
|
|
153
|
+
const tick = buffer.readInt32LE();
|
|
154
|
+
const lane = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
155
|
+
const width = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
156
|
+
const layer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
|
|
157
|
+
buffer.readInt32LE();
|
|
158
|
+
const type = StepType[buffer.readInt32LE()];
|
|
159
|
+
const ease = EaseType[buffer.readInt32LE()];
|
|
160
|
+
steps.push({
|
|
161
|
+
tick,
|
|
162
|
+
lane,
|
|
163
|
+
width,
|
|
164
|
+
type,
|
|
165
|
+
ease,
|
|
166
|
+
layer,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
const endTick = buffer.readInt32LE();
|
|
170
|
+
const endLane = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
171
|
+
const endWidth = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
172
|
+
const endLayer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
|
|
173
|
+
const endFlickTypeRaw = buffer.readInt32LE();
|
|
174
|
+
const endFlickType = FlickType[endFlickTypeRaw] || 'none';
|
|
175
|
+
const endFlags = buffer.readInt32LE();
|
|
176
|
+
holds.push({
|
|
177
|
+
flags: {
|
|
178
|
+
startHidden: !!(holdFlags & (1 << 0)),
|
|
179
|
+
endHidden: !!(holdFlags & (1 << 1)),
|
|
180
|
+
guide: !!(holdFlags & (1 << 2)),
|
|
181
|
+
dummy: !!(holdFlags & (1 << 3)),
|
|
182
|
+
},
|
|
183
|
+
start: {
|
|
184
|
+
tick: startTick,
|
|
185
|
+
lane: startLane,
|
|
186
|
+
width: startWidth,
|
|
187
|
+
ease: startEase,
|
|
188
|
+
flags: {
|
|
189
|
+
critical: !!(startFlags & (1 << 0)),
|
|
190
|
+
friction: !!(startFlags & (1 << 1)),
|
|
191
|
+
},
|
|
192
|
+
layer: startLayer,
|
|
193
|
+
},
|
|
194
|
+
fadeType,
|
|
195
|
+
guideColor,
|
|
196
|
+
steps,
|
|
197
|
+
end: {
|
|
198
|
+
tick: endTick,
|
|
199
|
+
lane: endLane,
|
|
200
|
+
width: endWidth,
|
|
201
|
+
flags: {
|
|
202
|
+
critical: !!(endFlags & (1 << 0)),
|
|
203
|
+
friction: !!(endFlags & (1 << 1)),
|
|
204
|
+
},
|
|
205
|
+
flickType: endFlickType,
|
|
206
|
+
layer: endLayer,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
events.timeSignatures.sort((a, b) => a.measure - b.measure);
|
|
211
|
+
events.bpmChanges.sort((a, b) => a.tick - b.tick);
|
|
212
|
+
events.hispeedChanges.sort((a, b) => a.tick - b.tick);
|
|
213
|
+
events.skills.sort((a, b) => a - b);
|
|
214
|
+
taps.sort((a, b) => a.tick - b.tick);
|
|
215
|
+
holds.sort((a, b) => a.start.tick - b.start.tick);
|
|
216
|
+
const damages = [];
|
|
217
|
+
if (cyanvasVersion >= 1) {
|
|
218
|
+
buffer.seek(damagesPointer);
|
|
219
|
+
const damagesCount = buffer.readInt32LE();
|
|
220
|
+
for (let i = 0; i < damagesCount; i++) {
|
|
221
|
+
const tick = buffer.readInt32LE();
|
|
222
|
+
const lane = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
223
|
+
const width = cyanvasVersion >= 6 ? buffer.readFloat32LE() : buffer.readInt32LE();
|
|
224
|
+
const layer = cyanvasVersion >= 4 ? buffer.readInt32LE() : 0;
|
|
225
|
+
const flickTypeRaw = buffer.readInt32LE();
|
|
226
|
+
const flickType = FlickType[flickTypeRaw] || 'none';
|
|
227
|
+
const flags = buffer.readInt32LE();
|
|
228
|
+
damages.push({
|
|
229
|
+
tick,
|
|
230
|
+
lane,
|
|
231
|
+
width,
|
|
232
|
+
flickType,
|
|
233
|
+
layer,
|
|
234
|
+
flags: {
|
|
235
|
+
critical: !!(flags & (1 << 0)),
|
|
236
|
+
friction: !!(flags & (1 << 1)),
|
|
237
|
+
dummy: cyanvasVersion >= 6 && untitledVersion >= 1 ? !!(flags & (1 << 2)) : false,
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
damages.sort((a, b) => a.tick - b.tick);
|
|
242
|
+
}
|
|
243
|
+
let numLayers = 1;
|
|
244
|
+
if (cyanvasVersion >= 4) {
|
|
245
|
+
buffer.seek(layersPointer);
|
|
246
|
+
numLayers = buffer.readInt32LE();
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
metadata,
|
|
250
|
+
events,
|
|
251
|
+
taps,
|
|
252
|
+
holds,
|
|
253
|
+
damages,
|
|
254
|
+
numLayers,
|
|
255
|
+
};
|
|
256
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type LevelData } from '@sonolus/core';
|
|
2
|
+
import { USC } from '../usc/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Convert MMWS or CCMMWS to a USC
|
|
5
|
+
*/
|
|
6
|
+
export declare const mmwsToUSC: (mmws: Uint8Array) => USC;
|
|
7
|
+
/**
|
|
8
|
+
* Convert CCMMWS to a USC
|
|
9
|
+
*/
|
|
10
|
+
export declare const ccmmwsToUSC: (mmws: Uint8Array) => USC;
|
|
11
|
+
/**
|
|
12
|
+
* Convert UCMMWS to a LevelData
|
|
13
|
+
*/
|
|
14
|
+
export declare const ucmmwsToLevelData: (mmws: Uint8Array) => LevelData;
|