sonolus-next-rush-plus-engine 1.5.7 → 1.5.9

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
@@ -1,7 +1,13 @@
1
1
  import { type LevelData } from '@sonolus/core';
2
+ type ExtendedEntityDataField = {
3
+ name: string;
4
+ value?: number;
5
+ ref?: string;
6
+ };
2
7
  export type ExtendedEntityData = {
3
8
  archetype: string;
4
- data: Record<string, number | string>;
9
+ name?: string;
10
+ data: ExtendedEntityDataField[];
5
11
  };
6
12
  export type ExtendedLevelData = {
7
13
  bgmOffset: number;
@@ -9,3 +15,4 @@ export type ExtendedLevelData = {
9
15
  };
10
16
  /** Convert a PJSekaiExtendedLevelData to a Level Data (Next Sekai) */
11
17
  export declare const extendedToLevelData: (data: ExtendedLevelData, offset?: number) => LevelData;
18
+ export {};
@@ -82,143 +82,220 @@ const guideKindMapping = {
82
82
  6: ConnectorKind.GUIDE_CYAN,
83
83
  7: ConnectorKind.GUIDE_BLACK,
84
84
  };
85
+ /** data 배열 → 평탄한 Record로 변환 (value → number, ref → string) */
86
+ const flattenData = (fields) => {
87
+ const result = {};
88
+ for (const field of fields) {
89
+ if (field.value !== undefined)
90
+ result[field.name] = field.value;
91
+ else if (field.ref !== undefined)
92
+ result[field.name] = field.ref;
93
+ }
94
+ return result;
95
+ };
96
+ /** 숫자 값 읽기 */
97
+ const getNum = (data, key, defaultValue = 0) => {
98
+ const val = data[key];
99
+ if (typeof val === 'number')
100
+ return val;
101
+ if (typeof val === 'string') {
102
+ const n = Number(val);
103
+ return isNaN(n) ? defaultValue : n;
104
+ }
105
+ return defaultValue;
106
+ };
107
+ /** 참조 값 읽기 (number | string) */
108
+ const getEntityRef = (data, key) => {
109
+ const val = data[key];
110
+ if (val === undefined)
111
+ return undefined;
112
+ return val;
113
+ };
114
+ /** 참조로 FlatEntity 조회 (number → 인덱스, string → 이름) */
115
+ const resolveEntity = (ref, entities, entitiesByName) => {
116
+ if (typeof ref === 'number')
117
+ return entities[ref];
118
+ return entitiesByName.get(ref);
119
+ };
85
120
  /** Convert a PJSekaiExtendedLevelData to a Level Data (Next Sekai) */
86
121
  export const extendedToLevelData = (data, offset = 0) => {
122
+ const flatEntities = data.entities.map((e) => ({
123
+ archetype: e.archetype,
124
+ name: e.name,
125
+ data: flattenData(e.data),
126
+ }));
127
+ const entitiesByName = new Map();
128
+ for (const entity of flatEntities) {
129
+ if (entity.name)
130
+ entitiesByName.set(entity.name, entity);
131
+ }
132
+ const resolve = (ref) => {
133
+ if (ref === undefined)
134
+ return undefined;
135
+ return resolveEntity(ref, flatEntities, entitiesByName);
136
+ };
87
137
  const allIntermediateEntities = [];
88
138
  const createIntermediate = (archetype, entityData) => {
89
- const intermediateEntity = { archetype, data: entityData };
90
- allIntermediateEntities.push(intermediateEntity);
91
- return intermediateEntity;
139
+ const entity = { archetype, data: entityData };
140
+ allIntermediateEntities.push(entity);
141
+ return entity;
92
142
  };
93
143
  createIntermediate('Initialization', {});
94
- for (const entity of data.entities) {
95
- if (entity.archetype === '#BPM_CHANGE') {
96
- createIntermediate('#BPM_CHANGE', {
97
- '#BEAT': entity.data['#BEAT'],
98
- '#BPM': entity.data['#BPM'],
99
- });
100
- }
144
+ for (const entity of flatEntities) {
145
+ if (entity.archetype !== '#BPM_CHANGE')
146
+ continue;
147
+ createIntermediate('#BPM_CHANGE', {
148
+ '#BEAT': getNum(entity.data, '#BEAT'),
149
+ '#BPM': getNum(entity.data, '#BPM'),
150
+ });
101
151
  }
102
152
  const timescaleGroupsByIndex = new Map();
103
- for (let i = 0; i < data.entities.length; i++) {
104
- const entity = data.entities[i];
105
- if (entity.archetype === 'TimeScaleGroup') {
106
- const groupIntermediate = createIntermediate('TimeScaleGroup', {});
107
- timescaleGroupsByIndex.set(i, groupIntermediate);
108
- let rawChangeIdx = entity.data['first'];
109
- let lastChangeIntermediate = null;
110
- while (rawChangeIdx !== undefined && rawChangeIdx > 0) {
111
- const rawChange = data.entities[rawChangeIdx];
112
- const changeIntermediate = createIntermediate('TimeScaleChange', {
113
- '#BEAT': rawChange.data['#BEAT'],
114
- timeScale: rawChange.data['timeScale'],
115
- timeScaleSkip: 0.0,
116
- timeScaleGroup: groupIntermediate,
117
- timeScaleEase: 0,
118
- });
119
- if (lastChangeIntermediate) {
120
- lastChangeIntermediate.data['next'] = changeIntermediate;
121
- }
122
- else {
123
- groupIntermediate.data['first'] = changeIntermediate;
124
- }
125
- lastChangeIntermediate = changeIntermediate;
126
- const nextIdx = rawChange.data['next'];
127
- if (nextIdx !== undefined && nextIdx > 0) {
128
- rawChangeIdx = nextIdx;
129
- }
130
- else {
131
- break;
132
- }
153
+ const timescaleGroupsByName = new Map();
154
+ for (let i = 0; i < flatEntities.length; i++) {
155
+ const entity = flatEntities[i];
156
+ if (entity.archetype !== 'TimeScaleGroup')
157
+ continue;
158
+ const groupIntermediate = createIntermediate('TimeScaleGroup', {});
159
+ timescaleGroupsByIndex.set(i, groupIntermediate);
160
+ if (entity.name)
161
+ timescaleGroupsByName.set(entity.name, groupIntermediate);
162
+ let rawChangeRef = getEntityRef(entity.data, 'first');
163
+ let lastChangeIntermediate = null;
164
+ while (rawChangeRef !== undefined) {
165
+ const rawChange = resolve(rawChangeRef);
166
+ if (!rawChange)
167
+ break;
168
+ const changeIntermediate = createIntermediate('TimeScaleChange', {
169
+ '#BEAT': getNum(rawChange.data, '#BEAT'),
170
+ timeScale: getNum(rawChange.data, 'timeScale'),
171
+ timeScaleSkip: 0.0,
172
+ timeScaleGroup: groupIntermediate,
173
+ timeScaleEase: 0,
174
+ });
175
+ if (lastChangeIntermediate) {
176
+ lastChangeIntermediate.data['next'] = changeIntermediate;
177
+ }
178
+ else {
179
+ groupIntermediate.data['first'] = changeIntermediate;
133
180
  }
181
+ lastChangeIntermediate = changeIntermediate;
182
+ rawChangeRef = getEntityRef(rawChange.data, 'next');
134
183
  }
135
184
  }
136
- const notesByOriginalIndex = new Map();
137
- for (let i = 0; i < data.entities.length; i++) {
138
- const entity = data.entities[i];
139
- if (noteTypeMapping[entity.archetype]) {
140
- const mappedArchetype = noteTypeMapping[entity.archetype];
141
- const directionData = entity.data['direction'] ?? 0;
142
- const noteIntermediate = createIntermediate(mappedArchetype, {
143
- '#BEAT': entity.data['#BEAT'],
144
- lane: entity.data['lane'] ?? 0.0,
145
- size: entity.data['size'] ?? 0.0,
146
- direction: flickDirectionMapping[directionData],
147
- segmentKind: ConnectorKind.ACTIVE_NORMAL,
148
- });
149
- notesByOriginalIndex.set(i, noteIntermediate);
150
- }
185
+ const resolveTimescaleGroup = (ref) => {
186
+ if (ref === undefined)
187
+ return undefined;
188
+ if (typeof ref === 'number')
189
+ return timescaleGroupsByIndex.get(ref);
190
+ return timescaleGroupsByName.get(ref);
191
+ };
192
+ const notesByIndex = new Map();
193
+ const notesByName = new Map();
194
+ for (let i = 0; i < flatEntities.length; i++) {
195
+ const entity = flatEntities[i];
196
+ const mappedArchetype = noteTypeMapping[entity.archetype];
197
+ if (!mappedArchetype)
198
+ continue;
199
+ const tsg = resolveTimescaleGroup(getEntityRef(entity.data, 'timeScaleGroup'));
200
+ const noteData = {
201
+ '#BEAT': getNum(entity.data, '#BEAT'),
202
+ lane: getNum(entity.data, 'lane', 0),
203
+ size: getNum(entity.data, 'size', 0),
204
+ direction: flickDirectionMapping[getNum(entity.data, 'direction', 0)],
205
+ segmentKind: ConnectorKind.ACTIVE_NORMAL,
206
+ };
207
+ if (tsg !== undefined)
208
+ noteData['#TIMESCALE_GROUP'] = tsg;
209
+ const noteIntermediate = createIntermediate(mappedArchetype, noteData);
210
+ notesByIndex.set(i, noteIntermediate);
211
+ if (entity.name)
212
+ notesByName.set(entity.name, noteIntermediate);
151
213
  }
152
- const connectorsByOriginalIndex = new Map();
153
- for (let i = 0; i < data.entities.length; i++) {
154
- const entity = data.entities[i];
155
- if (activeConnectorKindMapping[entity.archetype]) {
156
- const connectorKind = activeConnectorKindMapping[entity.archetype];
157
- const head = notesByOriginalIndex.get(entity.data['head']);
158
- const tail = notesByOriginalIndex.get(entity.data['tail']);
159
- const segmentHead = notesByOriginalIndex.get(entity.data['start']);
160
- const segmentTail = notesByOriginalIndex.get(entity.data['end']);
161
- if (!head || !tail || !segmentHead || !segmentTail)
162
- continue;
163
- const connectorIntermediate = createIntermediate('Connector', {
164
- head,
165
- tail,
166
- segmentHead,
167
- segmentTail,
168
- activeHead: segmentHead,
169
- activeTail: segmentTail,
170
- });
171
- head.data['connectorEase'] = easeTypeMapping[entity.data['ease'] ?? 0];
172
- head.data['segmentKind'] = connectorKind;
173
- tail.data['segmentKind'] = connectorKind;
174
- segmentHead.data['segmentKind'] = connectorKind;
175
- connectorsByOriginalIndex.set(i, connectorIntermediate);
176
- }
214
+ const resolveNote = (ref) => {
215
+ if (ref === undefined)
216
+ return undefined;
217
+ if (typeof ref === 'number')
218
+ return notesByIndex.get(ref);
219
+ return notesByName.get(ref);
220
+ };
221
+ const connectorsByIndex = new Map();
222
+ const connectorsByName = new Map();
223
+ for (let i = 0; i < flatEntities.length; i++) {
224
+ const entity = flatEntities[i];
225
+ const connectorKind = activeConnectorKindMapping[entity.archetype];
226
+ if (!connectorKind)
227
+ continue;
228
+ const headNote = resolveNote(getEntityRef(entity.data, 'head'));
229
+ const tailNote = resolveNote(getEntityRef(entity.data, 'tail'));
230
+ const segmentHeadNote = resolveNote(getEntityRef(entity.data, 'start'));
231
+ const segmentTailNote = resolveNote(getEntityRef(entity.data, 'end'));
232
+ if (!headNote || !tailNote || !segmentHeadNote || !segmentTailNote)
233
+ continue;
234
+ const connectorIntermediate = createIntermediate('Connector', {
235
+ head: headNote,
236
+ tail: tailNote,
237
+ segmentHead: segmentHeadNote,
238
+ segmentTail: segmentTailNote,
239
+ activeHead: segmentHeadNote,
240
+ activeTail: segmentTailNote,
241
+ });
242
+ headNote.data['connectorEase'] =
243
+ easeTypeMapping[getNum(entity.data, 'ease', 0)] ?? EaseType.LINEAR;
244
+ headNote.data['segmentKind'] = connectorKind;
245
+ tailNote.data['segmentKind'] = connectorKind;
246
+ segmentHeadNote.data['segmentKind'] = connectorKind;
247
+ connectorsByIndex.set(i, connectorIntermediate);
248
+ if (entity.name)
249
+ connectorsByName.set(entity.name, connectorIntermediate);
177
250
  }
178
- for (const [i, note] of notesByOriginalIndex.entries()) {
179
- const entity = data.entities[i];
180
- const timescaleGroupIndex = entity.data['timeScaleGroup'] ?? -1;
181
- if (timescaleGroupIndex >= 0 && timescaleGroupsByIndex.has(timescaleGroupIndex)) {
182
- note.data['#TIMESCALE_GROUP'] = timescaleGroupsByIndex.get(timescaleGroupIndex);
183
- }
184
- const attachIndex = entity.data['attach'] ?? -1;
185
- if (attachIndex > 0) {
186
- const attachConnector = connectorsByOriginalIndex.get(attachIndex);
251
+ const resolveConnector = (ref) => {
252
+ if (ref === undefined)
253
+ return undefined;
254
+ if (typeof ref === 'number')
255
+ return connectorsByIndex.get(ref);
256
+ return connectorsByName.get(ref);
257
+ };
258
+ for (let i = 0; i < flatEntities.length; i++) {
259
+ const entity = flatEntities[i];
260
+ const note = notesByIndex.get(i);
261
+ if (!note)
262
+ continue;
263
+ const attachRef = getEntityRef(entity.data, 'attach');
264
+ if (attachRef !== undefined) {
265
+ const attachConnector = resolveConnector(attachRef);
187
266
  if (attachConnector) {
188
267
  note.data['attachHead'] = attachConnector.data['head'];
189
268
  note.data['attachTail'] = attachConnector.data['tail'];
190
269
  note.data['isAttached'] = 1;
191
270
  }
192
271
  }
193
- const slideIndex = entity.data['slide'] ?? -1;
194
- if (slideIndex > 0) {
195
- const slideConnector = connectorsByOriginalIndex.get(slideIndex);
272
+ const slideRef = getEntityRef(entity.data, 'slide');
273
+ if (slideRef !== undefined) {
274
+ const slideConnector = resolveConnector(slideRef);
196
275
  if (slideConnector) {
197
276
  note.data['activeHead'] = slideConnector.data['activeHead'];
198
277
  }
199
278
  }
200
279
  }
201
- for (let i = 0; i < data.entities.length; i++) {
202
- const entity = data.entities[i];
203
- if (entity.archetype === 'SimLine') {
204
- const left = notesByOriginalIndex.get(entity.data['a']);
205
- const right = notesByOriginalIndex.get(entity.data['b']);
206
- if (left && right) {
207
- createIntermediate('SimLine', { left, right });
208
- }
209
- }
280
+ for (const entity of flatEntities) {
281
+ if (entity.archetype !== 'SimLine')
282
+ continue;
283
+ const left = resolveNote(getEntityRef(entity.data, 'a'));
284
+ const right = resolveNote(getEntityRef(entity.data, 'b'));
285
+ if (left && right)
286
+ createIntermediate('SimLine', { left, right });
210
287
  }
211
288
  const anchorsByBeat = new Map();
212
289
  const anchorPositions = new Map();
213
- const getAnchor = (beat, lane, size, timescaleGroup, pos, segmentKind = -1, segmentAlpha = -1, connectorEase = -1) => {
214
- let anchors = anchorsByBeat.get(beat);
290
+ const getAnchor = (beat, lane, size, tsg, pos, segmentKind = -1, segmentAlpha = -1, connectorEase = -1) => {
291
+ const anchors = anchorsByBeat.get(beat);
215
292
  if (anchors) {
216
293
  for (const anchor of anchors) {
217
294
  if (anchorPositions.get(anchor)?.has(pos))
218
295
  continue;
219
296
  if (anchor.data['lane'] === lane &&
220
297
  anchor.data['size'] === size &&
221
- anchor.data['#TIMESCALE_GROUP'] === timescaleGroup &&
298
+ anchor.data['#TIMESCALE_GROUP'] === tsg &&
222
299
  (segmentKind === -1 ||
223
300
  anchor.data['segmentKind'] === segmentKind ||
224
301
  anchor.data['segmentKind'] === -1) &&
@@ -228,92 +305,79 @@ export const extendedToLevelData = (data, offset = 0) => {
228
305
  (connectorEase === -1 ||
229
306
  anchor.data['connectorEase'] === connectorEase ||
230
307
  anchor.data['connectorEase'] === -1)) {
231
- if (segmentKind !== -1 && anchor.data['segmentKind'] === -1) {
308
+ if (segmentKind !== -1 && anchor.data['segmentKind'] === -1)
232
309
  anchor.data['segmentKind'] = segmentKind;
233
- }
234
- if (segmentAlpha !== -1 && anchor.data['segmentAlpha'] === -1) {
310
+ if (segmentAlpha !== -1 && anchor.data['segmentAlpha'] === -1)
235
311
  anchor.data['segmentAlpha'] = segmentAlpha;
236
- }
237
- if (connectorEase !== -1 && anchor.data['connectorEase'] === -1) {
312
+ if (connectorEase !== -1 && anchor.data['connectorEase'] === -1)
238
313
  anchor.data['connectorEase'] = connectorEase;
239
- }
240
314
  anchorPositions.get(anchor).add(pos);
241
315
  return anchor;
242
316
  }
243
317
  }
244
318
  }
245
- const anchor = createIntermediate('AnchorNote', {
319
+ const anchorData = {
246
320
  '#BEAT': beat,
247
321
  lane,
248
322
  size,
249
- '#TIMESCALE_GROUP': timescaleGroup,
250
323
  segmentKind,
251
324
  segmentAlpha,
252
325
  connectorEase,
253
- });
254
- if (!anchorsByBeat.has(beat)) {
326
+ };
327
+ if (tsg !== undefined)
328
+ anchorData['#TIMESCALE_GROUP'] = tsg;
329
+ const anchor = createIntermediate('AnchorNote', anchorData);
330
+ if (!anchorsByBeat.has(beat))
255
331
  anchorsByBeat.set(beat, []);
256
- }
257
332
  anchorsByBeat.get(beat).push(anchor);
258
333
  anchorPositions.set(anchor, new Set([pos]));
259
334
  return anchor;
260
335
  };
261
- for (let i = 0; i < data.entities.length; i++) {
262
- const entity = data.entities[i];
263
- if (entity.archetype === 'Guide') {
264
- const startBeat = entity.data['startBeat'];
265
- const startLane = entity.data['startLane'];
266
- const startSize = entity.data['startSize'];
267
- const startTimeScaleGroup = timescaleGroupsByIndex.get(entity.data['startTimeScaleGroup']);
268
- const headBeat = entity.data['headBeat'];
269
- const headLane = entity.data['headLane'];
270
- const headSize = entity.data['headSize'];
271
- const headTimeScaleGroup = timescaleGroupsByIndex.get(entity.data['headTimeScaleGroup']);
272
- const tailBeat = entity.data['tailBeat'];
273
- const tailLane = entity.data['tailLane'];
274
- const tailSize = entity.data['tailSize'];
275
- const tailTimeScaleGroup = timescaleGroupsByIndex.get(entity.data['tailTimeScaleGroup']);
276
- const endBeat = entity.data['endBeat'];
277
- const endLane = entity.data['endLane'];
278
- const endSize = entity.data['endSize'];
279
- const endTimeScaleGroup = timescaleGroupsByIndex.get(entity.data['endTimeScaleGroup']);
280
- const ease = easeTypeMapping[entity.data['ease'] ?? 0];
281
- const fade = entity.data['fade'] ?? 1;
282
- const [startAlpha, endAlpha] = fadeAlphaMapping[fade];
283
- const kind = guideKindMapping[entity.data['color'] ?? 0];
284
- const start = getAnchor(startBeat, startLane, startSize, startTimeScaleGroup, 'segmentHead', kind, startAlpha);
285
- const end = getAnchor(endBeat, endLane, endSize, endTimeScaleGroup, 'segmentTail', kind, endAlpha);
286
- const head = getAnchor(headBeat, headLane, headSize, headTimeScaleGroup, 'head', kind, -1, ease);
287
- const tail = getAnchor(tailBeat, tailLane, tailSize, tailTimeScaleGroup, 'tail', kind);
288
- createIntermediate('Connector', {
289
- head,
290
- tail,
291
- segmentHead: start,
292
- segmentTail: end,
293
- });
294
- }
336
+ for (const entity of flatEntities) {
337
+ if (entity.archetype !== 'Guide')
338
+ continue;
339
+ const startBeat = getNum(entity.data, 'startBeat');
340
+ const startLane = getNum(entity.data, 'startLane');
341
+ const startSize = getNum(entity.data, 'startSize');
342
+ const startTSG = resolveTimescaleGroup(getEntityRef(entity.data, 'startTimeScaleGroup'));
343
+ const headBeat = getNum(entity.data, 'headBeat');
344
+ const headLane = getNum(entity.data, 'headLane');
345
+ const headSize = getNum(entity.data, 'headSize');
346
+ const headTSG = resolveTimescaleGroup(getEntityRef(entity.data, 'headTimeScaleGroup'));
347
+ const tailBeat = getNum(entity.data, 'tailBeat');
348
+ const tailLane = getNum(entity.data, 'tailLane');
349
+ const tailSize = getNum(entity.data, 'tailSize');
350
+ const tailTSG = resolveTimescaleGroup(getEntityRef(entity.data, 'tailTimeScaleGroup'));
351
+ const endBeat = getNum(entity.data, 'endBeat');
352
+ const endLane = getNum(entity.data, 'endLane');
353
+ const endSize = getNum(entity.data, 'endSize');
354
+ const endTSG = resolveTimescaleGroup(getEntityRef(entity.data, 'endTimeScaleGroup'));
355
+ const ease = easeTypeMapping[getNum(entity.data, 'ease', 0)] ?? EaseType.LINEAR;
356
+ const [startAlpha, endAlpha] = fadeAlphaMapping[getNum(entity.data, 'fade', 1)];
357
+ const kind = guideKindMapping[getNum(entity.data, 'color', 0)] ?? ConnectorKind.GUIDE_NEUTRAL;
358
+ const start = getAnchor(startBeat, startLane, startSize, startTSG, 'segmentHead', kind, startAlpha);
359
+ const end = getAnchor(endBeat, endLane, endSize, endTSG, 'segmentTail', kind, endAlpha);
360
+ const head = getAnchor(headBeat, headLane, headSize, headTSG, 'head', kind, -1, ease);
361
+ const tail = getAnchor(tailBeat, tailLane, tailSize, tailTSG, 'tail', kind);
362
+ createIntermediate('Connector', { head, tail, segmentHead: start, segmentTail: end });
295
363
  }
296
364
  for (const anchorList of anchorsByBeat.values()) {
297
365
  for (const anchor of anchorList) {
298
- if (anchor.data['segmentKind'] === -1) {
366
+ if (anchor.data['segmentKind'] === -1)
299
367
  anchor.data['segmentKind'] = ConnectorKind.GUIDE_NEUTRAL;
300
- }
301
- if (anchor.data['segmentAlpha'] === -1) {
368
+ if (anchor.data['segmentAlpha'] === -1)
302
369
  anchor.data['segmentAlpha'] = 1.0;
303
- }
304
- if (anchor.data['connectorEase'] === -1) {
370
+ if (anchor.data['connectorEase'] === -1)
305
371
  anchor.data['connectorEase'] = EaseType.LINEAR;
306
- }
307
372
  }
308
373
  }
309
374
  for (const entity of allIntermediateEntities) {
310
- if (entity.archetype === 'Connector') {
311
- const head = entity.data['head'];
312
- const tail = entity.data['tail'];
313
- if (head && tail) {
314
- head.data['next'] = tail;
315
- }
316
- }
375
+ if (entity.archetype !== 'Connector')
376
+ continue;
377
+ const head = entity.data['head'];
378
+ const tail = entity.data['tail'];
379
+ if (head && tail)
380
+ head.data['next'] = tail;
317
381
  }
318
382
  allIntermediateEntities.sort((a, b) => {
319
383
  const isInitA = a.archetype === 'Initialization' ? 0 : 1;
@@ -327,9 +391,9 @@ export const extendedToLevelData = (data, offset = 0) => {
327
391
  const entities = [];
328
392
  const intermediateToRef = new Map();
329
393
  let entityRefCounter = 0;
330
- const getRef = (intermediateEntity) => {
394
+ const getOutputRef = (intermediateEntity) => {
331
395
  let ref = intermediateToRef.get(intermediateEntity);
332
- if (ref)
396
+ if (ref !== undefined)
333
397
  return ref;
334
398
  ref = (entityRefCounter++).toString(16);
335
399
  intermediateToRef.set(intermediateEntity, ref);
@@ -338,7 +402,7 @@ export const extendedToLevelData = (data, offset = 0) => {
338
402
  for (const intermediateEntity of allIntermediateEntities) {
339
403
  const entity = {
340
404
  archetype: intermediateEntity.archetype,
341
- name: getRef(intermediateEntity),
405
+ name: getOutputRef(intermediateEntity),
342
406
  data: [],
343
407
  };
344
408
  for (const [dataName, dataValue] of Object.entries(intermediateEntity.data)) {
@@ -346,7 +410,10 @@ export const extendedToLevelData = (data, offset = 0) => {
346
410
  entity.data.push({ name: dataName, value: dataValue });
347
411
  }
348
412
  else if (dataValue !== undefined && dataValue !== null) {
349
- entity.data.push({ name: dataName, ref: getRef(dataValue) });
413
+ entity.data.push({
414
+ name: dataName,
415
+ ref: getOutputRef(dataValue),
416
+ });
350
417
  }
351
418
  }
352
419
  entities.push(entity);
package/dist/index.d.ts CHANGED
@@ -4,11 +4,11 @@ import { ucmmwsToLevelData } from './mmw/convert.js';
4
4
  import { susToUSC } from './sus/convert.js';
5
5
  import { uscToLevelData } from './usc/convert.js';
6
6
  import { USC } from './usc/index.js';
7
- import { extendedToLevelData } from './extended/convert.js';
8
- export { susToUSC, mmwsToUSC, uscToLevelData, ucmmwsToLevelData, extendedToLevelData };
7
+ import { extendedToLevelData, type ExtendedEntityData, type ExtendedLevelData } from './extended/convert.js';
8
+ export { susToUSC, mmwsToUSC, uscToLevelData, ucmmwsToLevelData, extendedToLevelData, type ExtendedEntityData, type ExtendedLevelData, };
9
9
  export * from './usc/index.js';
10
10
  export declare const convertToLevelData: (input: string | Uint8Array | USC | LevelData, offset?: number) => LevelData;
11
- export declare const version = "1.5.7";
11
+ export declare const version = "1.5.9";
12
12
  export declare const databaseEngineItem: {
13
13
  readonly name: "next-rush-plus";
14
14
  readonly version: 13;
package/dist/index.js CHANGED
@@ -7,8 +7,8 @@ import { isUSC } from './usc/analyze.js';
7
7
  import { isLevelData } from './LevelData/analyze.js';
8
8
  import { isPJSK } from './pjsk/analyze.js';
9
9
  import { pjskToUSC } from './pjsk/convert.js';
10
- import { extendedToLevelData } from './extended/convert.js';
11
- export { susToUSC, mmwsToUSC, uscToLevelData, ucmmwsToLevelData, extendedToLevelData };
10
+ import { extendedToLevelData, } from './extended/convert.js';
11
+ export { susToUSC, mmwsToUSC, uscToLevelData, ucmmwsToLevelData, extendedToLevelData, };
12
12
  export * from './usc/index.js';
13
13
  export const convertToLevelData = (input, offset = 0) => {
14
14
  if (isLevelData(input)) {
@@ -60,7 +60,7 @@ export const convertToLevelData = (input, offset = 0) => {
60
60
  }
61
61
  return uscToLevelData(usc, offset, true, true);
62
62
  };
63
- export const version = '1.5.7';
63
+ export const version = '1.5.9';
64
64
  export const databaseEngineItem = {
65
65
  name: 'next-rush-plus',
66
66
  version: 13,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonolus-next-rush-plus-engine",
3
- "version": "1.5.7",
3
+ "version": "1.5.9",
4
4
  "description": "A new Project Sekai inspired engine for Sonolus",
5
5
  "author": "Hyeon2",
6
6
  "repository": {