kipphi 2.1.4-beta.1 → 2.1.4

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/env.ts CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
 
15
15
  // 就挺神奇的!明明typeof后面跟值,这里却可以写成类型导入
16
- import { type TimeT, type EventValueType } from "./chartTypes";
16
+ import { type TimeT, type EventValueType, EventValueESType } from "./chartTypes";
17
17
  import { EventNode } from "./event";
18
18
  import { toTimeString } from "./util";
19
19
 
@@ -206,16 +206,23 @@ interface _Error extends _CheckMap {
206
206
  error: "";
207
207
  }
208
208
 
209
+ type GetEnumKey<TEnum extends Record<string, any>, TValue extends TEnum[keyof TEnum]> = {
210
+ [K in keyof TEnum]: TEnum[K] extends TValue ? K : never
211
+ }[keyof TEnum];
209
212
 
210
- interface ErrorMap extends Record<keyof typeof ERROR_IDS, Array<any>>{
211
- EVENT_NODE_NOT_DENSE: [EventNode];
213
+ type ERROR_NAMES = keyof typeof ERROR_IDS;
214
+
215
+ interface ErrorMap extends Record<ERROR_NAMES, Array<any>>{
216
+ EVENT_NODE_NOT_DENSE: [EventNode<EventValueESType>];
217
+ EVENT_NODE_TIME_NOT_INCREMENTAL: [EventNode<EventValueESType>];
218
+
212
219
  }
213
220
 
214
- type ArgsOf<ET extends ERROR_IDS> = ET extends keyof ErrorMap ? ErrorMap[ET] : never;
221
+ type ArgsOf<ET extends ERROR_IDS> = GetEnumKey<typeof ERROR_IDS, ET> extends keyof ErrorMap ? ErrorMap[GetEnumKey<typeof ERROR_IDS, ET>] : [];
215
222
 
216
223
  export class KPAError<ET extends ERROR_IDS> extends Error {
217
224
  fixed = false;
218
- args: ArgsOf<ET> | [];
225
+ args: ArgsOf<ET>;
219
226
  constructor(message: string, public id: ET) {
220
227
  super(message);
221
228
  }
@@ -224,16 +231,16 @@ export class KPAError<ET extends ERROR_IDS> extends Error {
224
231
  *
225
232
  * 此时可以调用该方法,该方法会输出错误并把它保存到KPAError的一个`buffer`静态属性下。
226
233
  */
227
- warn(...args: ArgsOf<ET> | []) {
234
+ warn(...args: ArgsOf<ET>) {
228
235
  console.warn(this.stack);
229
236
  this.args = args;
230
- KPAError.buffer.push(this);
237
+ KPAError.buffer.push(this as any);
231
238
  }
232
- fix(...args: ArgsOf<ET> | []) {
239
+ fix(...args: ArgsOf<ET>) {
233
240
  console.warn("[Auto Fixed]" + this.stack);
234
241
  this.fixed = true;
235
242
  this.args = args;
236
- KPAError.buffer.push(this);
243
+ KPAError.buffer.push(this as any);
237
244
  }
238
245
  static buffer: KPAError<ERROR_IDS>[] = [];
239
246
  static flush() {
@@ -241,9 +248,10 @@ export class KPAError<ET extends ERROR_IDS> extends Error {
241
248
  }
242
249
  }
243
250
 
251
+
244
252
  export const err = new Proxy(ERRORS, {
245
253
  get(target, name) {
246
- return (...args: any[]) => new KPAError(target[name](...args) + `(KP${ERROR_IDS[name].toString(16)})`, ERROR_IDS[name]);
254
+ return (...args: any[]) => new KPAError<typeof ERROR_IDS[keyof typeof ERROR_IDS]>(target[name](...args) + `(KP${ERROR_IDS[name].toString(16)})`, ERROR_IDS[name]);
247
255
  }
248
256
  }) as unknown as { [key in keyof typeof ERRORS]: (...args: Parameters<typeof ERRORS[key]>) => KPAError<typeof ERROR_IDS[key]>};
249
257
 
package/event.ts CHANGED
@@ -541,16 +541,16 @@ export class EventNodeSequence<VT extends EventValueESType = number> { // 泛型
541
541
  // 读取事件列表
542
542
  for (let index = 0; index < length; index++) {
543
543
  const event = data[index];
544
+ const [start, end] = (type === EventType.text
545
+ ? EventNode.fromTextEvent(event as EventDataRPELike<string>, templates)
546
+ : EventNode.fromEvent(event as EventDataRPELike<number | RGB>, chart)) as unknown as [EventStartNode<VT>, EventEndNode<VT>];
544
547
  if (TC.lt(event.startTime, lastEndTime)) { // event.startTime < lastEndTime
545
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn()
548
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn(start)
546
549
  }
547
550
  if (!TC.lt(event.startTime, event.endTime)) {
548
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn()
551
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn(start)
549
552
  }
550
553
  lastEndTime = event.endTime;
551
- const [start, end] = (type === EventType.text
552
- ? EventNode.fromTextEvent(event as EventDataRPELike<string>, templates)
553
- : EventNode.fromEvent(event as EventDataRPELike<number | RGB>, chart)) as unknown as [EventStartNode<VT>, EventEndNode<VT>];
554
554
  // 刚开始时,上个节点是头
555
555
  if (lastEnd.type === NodeType.HEAD) {
556
556
  EventNode.connect(lastEnd, start)
@@ -650,21 +650,21 @@ export class EventNodeSequence<VT extends EventValueESType = number> { // 泛型
650
650
  // 从前面复制了,复用性减一
651
651
  // KPA2没有更改RPE的按事件存储的机制。
652
652
  if (TC.lt(event.startTime, lastEndTime)) { // event.startTime < lastEndTime
653
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn()
653
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn(start)
654
654
  }
655
655
  if (!TC.lt(event.startTime, event.endTime)) {
656
656
  if (TC.eq(event.startTime, event.endTime)) {
657
657
  // 零长事件直接忽略,并认为已经修复
658
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).fix();
658
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).fix(start);
659
659
  continue;
660
660
  } else {
661
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn()
661
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn(start)
662
662
  }
663
663
  }
664
664
  if (lastEnd.type === NodeType.HEAD) {
665
665
  EventNode.connect(lastEnd, start)
666
666
  } else if (TC.gt(event.startTime, lastEndTime)) {
667
- err.EVENT_NODE_NOT_DENSE(`${pos}.events[${index}]`).warn();
667
+ err.EVENT_NODE_NOT_DENSE(`${pos}.events[${index}]`).warn(start);
668
668
  const mid = new EventStartNode(lastEndTime, start.value);
669
669
  const midEnd = new EventEndNode(event.startTime, end.value);
670
670
  EventNode.connect(lastEnd, mid);
@@ -954,7 +954,7 @@ export class EventNodeSequence<VT extends EventValueESType = number> { // 泛型
954
954
  checkErrors() {
955
955
  let currentNode: EventStartNode<VT> = this.head.next;
956
956
  if (TC.ne(currentNode.time, [0, 0, 1])) {
957
- err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).fix();
957
+ err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).fix(currentNode);
958
958
  currentNode.time = [0, 0, 1];
959
959
  }
960
960
  const endNode = currentNode.next;
@@ -983,10 +983,10 @@ export class EventNodeSequence<VT extends EventValueESType = number> { // 泛型
983
983
  break;
984
984
  }
985
985
  if (!TC.gt(endNode.time, currentNode.time)) {
986
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${this.id}, ${currentNode.time}`).warn();
986
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${this.id}, ${currentNode.time}`).warn(currentNode);
987
987
  }
988
988
  if (TC.ne(lastEnd.time, currentNode.time)) {
989
- err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).warn();
989
+ err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).warn(currentNode);
990
990
  }
991
991
  currentNode = currentNode.next.next;
992
992
  lastEnd = endNode;
package/index.d.ts CHANGED
@@ -2120,7 +2120,7 @@ declare module "event" {
2120
2120
  };
2121
2121
  }
2122
2122
  declare module "env" {
2123
- import { type TimeT, type EventValueType } from "chartTypes";
2123
+ import { type TimeT, type EventValueType, EventValueESType } from "chartTypes";
2124
2124
  import { EventNode } from "event";
2125
2125
  export enum ERROR_IDS {
2126
2126
  UI_OCCUPIED = 272,
@@ -2200,22 +2200,27 @@ declare module "env" {
2200
2200
  TEMPLATE_EASING_CIRCULAR_REFERENCE: (temEasName: string) => string;
2201
2201
  EASING_DELTA_CANNOT_BE_ZERO: (seqName: string, time: TimeT) => string;
2202
2202
  };
2203
- interface ErrorMap extends Record<keyof typeof ERROR_IDS, Array<any>> {
2204
- EVENT_NODE_NOT_DENSE: [EventNode];
2205
- }
2206
- type ArgsOf<ET extends ERROR_IDS> = ET extends keyof ErrorMap ? ErrorMap[ET] : never;
2203
+ type GetEnumKey<TEnum extends Record<string, any>, TValue extends TEnum[keyof TEnum]> = {
2204
+ [K in keyof TEnum]: TEnum[K] extends TValue ? K : never;
2205
+ }[keyof TEnum];
2206
+ type ERROR_NAMES = keyof typeof ERROR_IDS;
2207
+ interface ErrorMap extends Record<ERROR_NAMES, Array<any>> {
2208
+ EVENT_NODE_NOT_DENSE: [EventNode<EventValueESType>];
2209
+ EVENT_NODE_TIME_NOT_INCREMENTAL: [EventNode<EventValueESType>];
2210
+ }
2211
+ type ArgsOf<ET extends ERROR_IDS> = GetEnumKey<typeof ERROR_IDS, ET> extends keyof ErrorMap ? ErrorMap[GetEnumKey<typeof ERROR_IDS, ET>] : [];
2207
2212
  export class KPAError<ET extends ERROR_IDS> extends Error {
2208
2213
  id: ET;
2209
2214
  fixed: boolean;
2210
- args: ArgsOf<ET> | [];
2215
+ args: ArgsOf<ET>;
2211
2216
  constructor(message: string, id: ET);
2212
2217
  /**
2213
2218
  * 对于解析谱面等场景,有时可能需要找出全部的错误,不宜直接抛出错误中断代码执行
2214
2219
  *
2215
2220
  * 此时可以调用该方法,该方法会输出错误并把它保存到KPAError的一个`buffer`静态属性下。
2216
2221
  */
2217
- warn(...args: ArgsOf<ET> | []): void;
2218
- fix(...args: ArgsOf<ET> | []): void;
2222
+ warn(...args: ArgsOf<ET>): void;
2223
+ fix(...args: ArgsOf<ET>): void;
2219
2224
  static buffer: KPAError<ERROR_IDS>[];
2220
2225
  static flush(): void;
2221
2226
  }
@@ -2972,7 +2977,7 @@ declare module "rpeChartCompiler" {
2972
2977
  deletesEmptyLines: boolean;
2973
2978
  constructor(chart: Chart);
2974
2979
  compileChart(): ChartDataRPE;
2975
- compileJudgeLine(judgeLine: JudgeLine): JudgeLineDataRPE;
2980
+ compileJudgeLine(judgeLine: JudgeLine, lines: JudgeLine[]): JudgeLineDataRPE;
2976
2981
  compileEasedEvent<VT extends EventValueESType>(snode: EventStartNode<VT> & {
2977
2982
  evaluator: EasedEvaluatorOfType<VT>;
2978
2983
  }, getValue: (node: EventStartNode<VT> | EventEndNode<VT>) => VT): EventDataRPELike<VT>;
@@ -2994,6 +2999,7 @@ declare module "rpeChartCompiler" {
2994
2999
  * @returns
2995
3000
  */
2996
3001
  substitute<VT extends EventValueESType>(seq: EventNodeSequence<VT>): EventNodeSequence<VT>;
3002
+ static replaceFilename(filename: string): string;
2997
3003
  }
2998
3004
  }
2999
3005
  declare module "index" {
package/index.js CHANGED
@@ -1782,14 +1782,14 @@ class EventNodeSequence {
1782
1782
  let lastEndTime = [0, 0, 1];
1783
1783
  for (let index = 0;index < length; index++) {
1784
1784
  const event = data[index];
1785
+ const [start, end] = type === 9 /* text */ ? EventNode.fromTextEvent(event, templates) : EventNode.fromEvent(event, chart);
1785
1786
  if (TC2.lt(event.startTime, lastEndTime)) {
1786
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn();
1787
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn(start);
1787
1788
  }
1788
1789
  if (!TC2.lt(event.startTime, event.endTime)) {
1789
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn();
1790
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn(start);
1790
1791
  }
1791
1792
  lastEndTime = event.endTime;
1792
- const [start, end] = type === 9 /* text */ ? EventNode.fromTextEvent(event, templates) : EventNode.fromEvent(event, chart);
1793
1793
  if (lastEnd.type === 0 /* HEAD */) {
1794
1794
  EventNode.connect(lastEnd, start);
1795
1795
  } else if (lastEnd.value === lastEnd.previous.value && lastEnd.previous.evaluator instanceof EasedEvaluator) {
@@ -1844,20 +1844,20 @@ class EventNodeSequence {
1844
1844
  chart.segmentedTemplates.set(evaluator.easing, [pos, start.time]);
1845
1845
  }
1846
1846
  if (TC2.lt(event.startTime, lastEndTime)) {
1847
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn();
1847
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn(start);
1848
1848
  }
1849
1849
  if (!TC2.lt(event.startTime, event.endTime)) {
1850
1850
  if (TC2.eq(event.startTime, event.endTime)) {
1851
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).fix();
1851
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).fix(start);
1852
1852
  continue;
1853
1853
  } else {
1854
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn();
1854
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn(start);
1855
1855
  }
1856
1856
  }
1857
1857
  if (lastEnd.type === 0 /* HEAD */) {
1858
1858
  EventNode.connect(lastEnd, start);
1859
1859
  } else if (TC2.gt(event.startTime, lastEndTime)) {
1860
- err.EVENT_NODE_NOT_DENSE(`${pos}.events[${index}]`).warn();
1860
+ err.EVENT_NODE_NOT_DENSE(`${pos}.events[${index}]`).warn(start);
1861
1861
  const mid = new EventStartNode(lastEndTime, start.value);
1862
1862
  const midEnd = new EventEndNode(event.startTime, end.value);
1863
1863
  EventNode.connect(lastEnd, mid);
@@ -2075,7 +2075,7 @@ class EventNodeSequence {
2075
2075
  checkErrors() {
2076
2076
  let currentNode = this.head.next;
2077
2077
  if (TC2.ne(currentNode.time, [0, 0, 1])) {
2078
- err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).fix();
2078
+ err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).fix(currentNode);
2079
2079
  currentNode.time = [0, 0, 1];
2080
2080
  }
2081
2081
  const endNode = currentNode.next;
@@ -2103,10 +2103,10 @@ class EventNodeSequence {
2103
2103
  break;
2104
2104
  }
2105
2105
  if (!TC2.gt(endNode2.time, currentNode.time)) {
2106
- err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${this.id}, ${currentNode.time}`).warn();
2106
+ err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${this.id}, ${currentNode.time}`).warn(currentNode);
2107
2107
  }
2108
2108
  if (TC2.ne(lastEnd.time, currentNode.time)) {
2109
- err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).warn();
2109
+ err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).warn(currentNode);
2110
2110
  }
2111
2111
  currentNode = currentNode.next.next;
2112
2112
  lastEnd = endNode2;
@@ -5454,17 +5454,18 @@ class RPEChartCompiler {
5454
5454
  node = endNode.next;
5455
5455
  }
5456
5456
  return true;
5457
- });
5457
+ }) || line2.children.size > 0;
5458
5458
  } : () => true;
5459
- const judgeLineList = chart2.judgeLines.filter(filter).map((line2) => this.compileJudgeLine(line2));
5459
+ const judgeLineList = chart2.judgeLines.filter(filter);
5460
+ const judgeLineDataList = judgeLineList.map((line2) => this.compileJudgeLine(line2, judgeLineList));
5460
5461
  const BPMList = chart2.timeCalculator.dump();
5461
5462
  const META = {
5462
- RPEVersion: 1,
5463
+ RPEVersion: 170,
5463
5464
  background: "illustration.png",
5464
5465
  charter: chart2.charter,
5465
5466
  composer: chart2.composer,
5466
5467
  illustration: chart2.illustrator,
5467
- id: Math.random().toString().slice(2, 10),
5468
+ id: Math.random().toString().slice(2, 18),
5468
5469
  level: chart2.level,
5469
5470
  name: chart2.name,
5470
5471
  offset: chart2.offset,
@@ -5475,9 +5476,9 @@ class RPEChartCompiler {
5475
5476
  if (!target) {
5476
5477
  continue;
5477
5478
  }
5478
- const lineData = judgeLineList[target.id];
5479
+ const lineData = judgeLineDataList[judgeLineList.indexOf(target)];
5479
5480
  if (lineData.attachUI) {
5480
- judgeLineList.push({
5481
+ judgeLineDataList.push({
5481
5482
  Group: 0,
5482
5483
  Name: "Auto created for " + uiName,
5483
5484
  Texture: "line.png",
@@ -5485,7 +5486,7 @@ class RPEChartCompiler {
5485
5486
  notes: [],
5486
5487
  bpmfactor: 1,
5487
5488
  eventLayers: [],
5488
- father: target.id,
5489
+ father: judgeLineList.indexOf(target),
5489
5490
  isCover: lineData.isCover,
5490
5491
  numOfNotes: 0,
5491
5492
  anchor: target.anchor,
@@ -5498,7 +5499,7 @@ class RPEChartCompiler {
5498
5499
  return {
5499
5500
  BPMList,
5500
5501
  META,
5501
- judgeLineList,
5502
+ judgeLineList: judgeLineDataList,
5502
5503
  judgeLineGroup: judgeLineGroups,
5503
5504
  multiLineString: "",
5504
5505
  multiScale: 1,
@@ -5506,14 +5507,15 @@ class RPEChartCompiler {
5506
5507
  kpaChartTime: chart2.chartingSeconds
5507
5508
  };
5508
5509
  }
5509
- compileJudgeLine(judgeLine) {
5510
+ compileJudgeLine(judgeLine, lines) {
5510
5511
  const chart2 = this.chart;
5511
5512
  const notes = this.compileNNLists([...judgeLine.nnLists.values()], [...judgeLine.hnLists.values()]);
5513
+ const father = judgeLine.father ? lines.indexOf(judgeLine.father) : -1;
5512
5514
  return {
5513
5515
  notes,
5514
5516
  Group: chart2.judgeLineGroups.indexOf(judgeLine.group),
5515
5517
  Name: judgeLine.name,
5516
- Texture: judgeLine.texture,
5518
+ Texture: RPEChartCompiler.replaceFilename(judgeLine.texture),
5517
5519
  bpmfactor: 1,
5518
5520
  eventLayers: judgeLine.eventLayers.map((layer, index) => ({
5519
5521
  moveXEvents: layer.moveX ? this.dumpEventNodeSequence(layer.moveX) : undefined,
@@ -5528,7 +5530,7 @@ class RPEChartCompiler {
5528
5530
  textEvents: judgeLine.extendedLayer.text ? this.dumpEventNodeSequence(judgeLine.extendedLayer.text) : undefined,
5529
5531
  colorEvents: judgeLine.extendedLayer.color ? this.dumpEventNodeSequence(judgeLine.extendedLayer.color) : undefined
5530
5532
  },
5531
- father: judgeLine.father?.id ?? -1,
5533
+ father,
5532
5534
  isCover: judgeLine.cover ? 1 : 0,
5533
5535
  numOfNotes: notes.length,
5534
5536
  anchor: judgeLine.anchor,
@@ -5802,6 +5804,17 @@ class RPEChartCompiler {
5802
5804
  EventNode.connect(lastStart, newSeq.tail);
5803
5805
  return newSeq;
5804
5806
  }
5807
+ static replaceFilename(filename) {
5808
+ const arr = [];
5809
+ for (const char of filename) {
5810
+ if (char.charCodeAt(0) >= 128) {
5811
+ arr.push(`u(${char.charCodeAt(0).toString(16)})`);
5812
+ } else {
5813
+ arr.push(char);
5814
+ }
5815
+ }
5816
+ return arr.join("");
5817
+ }
5805
5818
  }
5806
5819
  export {
5807
5820
  toTimeString,
package/note.ts CHANGED
@@ -459,7 +459,7 @@ export class NNList {
459
459
 
460
460
  return newNode
461
461
  } else {
462
- return node;
462
+ return node as NoteNode;
463
463
  }
464
464
  }
465
465
  dumpKPA(): NNListDataKPA {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kipphi",
3
3
  "description": "Parse your Phigros Chart(.rpe.json or .kpa.json) into an editor-friendly format.",
4
- "version": "2.1.4-beta.1",
4
+ "version": "2.1.4",
5
5
  "author": "Team Zincs (https://github.com/TeamZincs)",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -65,18 +65,20 @@ export class RPEChartCompiler {
65
65
  }
66
66
  return true; // 有超过两个的节点
67
67
  })
68
+ || line.children.size > 0;
68
69
  } : () => true
69
70
  const judgeLineList = chart.judgeLines
70
- .filter(filter)
71
- .map(line => this.compileJudgeLine(line));
71
+ .filter(filter);
72
+ const judgeLineDataList = judgeLineList
73
+ .map(line => this.compileJudgeLine(line, judgeLineList));
72
74
  const BPMList = chart.timeCalculator.dump();
73
75
  const META: MetaData = {
74
- RPEVersion: 1,
76
+ RPEVersion: 170,
75
77
  background: 'illustration.png',
76
78
  charter: chart.charter,
77
79
  composer: chart.composer,
78
80
  illustration: chart.illustrator,
79
- id: Math.random().toString().slice(2, 10),
81
+ id: Math.random().toString().slice(2, 18),
80
82
  level: chart.level,
81
83
  name: chart.name,
82
84
  offset: chart.offset,
@@ -88,11 +90,11 @@ export class RPEChartCompiler {
88
90
  if (!target) {
89
91
  continue;
90
92
  }
91
- const lineData = judgeLineList[target.id];
93
+ const lineData = judgeLineDataList[judgeLineList.indexOf(target)];
92
94
  // RPEJSON里面一条线只能绑一个UI,KPAJSON可以绑多个
93
95
  // 所以如果绑了多个,自动给它们创建子线
94
96
  if (lineData.attachUI) {
95
- judgeLineList.push({
97
+ judgeLineDataList.push({
96
98
  Group: 0,
97
99
  Name: "Auto created for " + uiName,
98
100
  Texture: "line.png",
@@ -100,7 +102,7 @@ export class RPEChartCompiler {
100
102
  notes: [],
101
103
  bpmfactor: 1.0,
102
104
  eventLayers: [],
103
- father: target.id,
105
+ father: judgeLineList.indexOf(target),
104
106
  isCover: lineData.isCover,
105
107
  numOfNotes: 0,
106
108
  anchor: target.anchor,
@@ -116,7 +118,7 @@ export class RPEChartCompiler {
116
118
  return {
117
119
  BPMList,
118
120
  META,
119
- judgeLineList,
121
+ judgeLineList: judgeLineDataList,
120
122
  judgeLineGroup: judgeLineGroups,
121
123
  multiLineString: '',
122
124
  multiScale: 1.0,
@@ -125,15 +127,17 @@ export class RPEChartCompiler {
125
127
  };
126
128
  }
127
129
 
128
- compileJudgeLine(judgeLine: JudgeLine): JudgeLineDataRPE {
130
+ compileJudgeLine(judgeLine: JudgeLine, lines: JudgeLine[]): JudgeLineDataRPE {
129
131
  const chart = this.chart;
130
132
  const notes = this.compileNNLists([...judgeLine.nnLists.values()], [...judgeLine.hnLists.values()]);
131
133
 
134
+ const father = judgeLine.father ? lines.indexOf(judgeLine.father) : -1;
135
+
132
136
  return {
133
137
  notes: notes,
134
138
  Group: chart.judgeLineGroups.indexOf(judgeLine.group),
135
139
  Name: judgeLine.name,
136
- Texture: judgeLine.texture,
140
+ Texture: RPEChartCompiler.replaceFilename(judgeLine.texture),
137
141
  bpmfactor: 1.0,
138
142
  eventLayers: judgeLine.eventLayers.map((layer, index): EventLayerDataRPE => ({
139
143
  moveXEvents: layer.moveX ? this.dumpEventNodeSequence(layer.moveX) : undefined,
@@ -148,7 +152,7 @@ export class RPEChartCompiler {
148
152
  textEvents: judgeLine.extendedLayer.text ? this.dumpEventNodeSequence(judgeLine.extendedLayer.text) : undefined,
149
153
  colorEvents: judgeLine.extendedLayer.color ? this.dumpEventNodeSequence(judgeLine.extendedLayer.color) : undefined
150
154
  },
151
- father: judgeLine.father?.id ?? -1,
155
+ father: father,
152
156
  isCover: judgeLine.cover ? 1 : 0,
153
157
  numOfNotes: notes.length,
154
158
  anchor: judgeLine.anchor,
@@ -521,6 +525,18 @@ export class RPEChartCompiler {
521
525
  EventNode.connect(lastStart, newSeq.tail)
522
526
  return newSeq;
523
527
  }
528
+
529
+ static replaceFilename(filename: string) {
530
+ const arr = [];
531
+ for (const char of filename) {
532
+ if (char.charCodeAt(0) >= 128) {
533
+ arr.push(`u(${char.charCodeAt(0).toString(16)})`);
534
+ } else {
535
+ arr.push(char);
536
+ }
537
+ }
538
+ return arr.join("");
539
+ }
524
540
  }
525
541
  // 现在是2025年10月18日,杨哲思已经改掉了此项目最史山的代码之一,但是还是一坨
526
542