sonolus-pjsekai-js 1.2.7 → 1.2.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.
- package/README.md +6 -0
- package/dist/EnginePlayData +0 -0
- package/dist/EngineWatchData +0 -0
- package/dist/index.cjs +29 -29
- package/dist/index.d.cts +5 -5
- package/dist/sus/analyze.cjs +27 -25
- package/package.json +7 -11
package/README.md
CHANGED
@@ -166,6 +166,12 @@ Converts USC (Universal Sekai Chart) to Level Data.
|
|
166
166
|
- `usc`: usc chart.
|
167
167
|
- `offset`: offset (default: `0`).
|
168
168
|
|
169
|
+
### `uscToUSC(usc)`
|
170
|
+
|
171
|
+
Converts MMW usc chart to USC (Universal Sekai Chart).
|
172
|
+
|
173
|
+
- `usc`: usc chart.
|
174
|
+
|
169
175
|
### Assets
|
170
176
|
|
171
177
|
The following assets are exposed as package entry points:
|
package/dist/EnginePlayData
CHANGED
Binary file
|
package/dist/EngineWatchData
CHANGED
Binary file
|
package/dist/index.cjs
CHANGED
@@ -22,47 +22,47 @@ Object.defineProperty(exports, "uscToLevelData", { enumerable: true, get: functi
|
|
22
22
|
__exportStar(require("./usc/index.cjs"), exports);
|
23
23
|
var revert_cjs_1 = require("./usc/revert.cjs");
|
24
24
|
Object.defineProperty(exports, "uscToUSC", { enumerable: true, get: function () { return revert_cjs_1.uscToUSC; } });
|
25
|
-
exports.version =
|
25
|
+
exports.version = "1.2.9";
|
26
26
|
exports.databaseEngineItem = {
|
27
|
-
name:
|
27
|
+
name: "prosekaR",
|
28
28
|
version: 13,
|
29
29
|
title: {
|
30
|
-
en:
|
31
|
-
ja:
|
32
|
-
ko:
|
33
|
-
zhs:
|
34
|
-
zht:
|
30
|
+
en: "ProSeka R",
|
31
|
+
ja: "プロセカ R",
|
32
|
+
ko: "프로세카 R",
|
33
|
+
zhs: "世界计划 R",
|
34
|
+
zht: "世界計劃 R",
|
35
35
|
},
|
36
36
|
subtitle: {
|
37
|
-
en:
|
38
|
-
ja:
|
39
|
-
ko:
|
40
|
-
zhs:
|
41
|
-
zht:
|
37
|
+
en: "ProSeka Rush",
|
38
|
+
ja: "プロセカ ラッシュ",
|
39
|
+
ko: "프로세카 러쉬",
|
40
|
+
zhs: "世界计划 匆忙",
|
41
|
+
zht: "世界計劃 匆忙",
|
42
42
|
},
|
43
43
|
author: {
|
44
|
-
en:
|
44
|
+
en: "Hyeon2#7895",
|
45
45
|
},
|
46
46
|
description: {
|
47
47
|
en: [
|
48
|
-
|
48
|
+
"A recreation of Project Sekai: Colorful Stage! engine in Sonolus.",
|
49
49
|
`Version: ${exports.version}`,
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
].join(
|
50
|
+
"",
|
51
|
+
"Forked from the pjsekai engine by Burrito#1000.",
|
52
|
+
"https://github.com/NonSpicyBurrito/sonolus-pjsekai-engine",
|
53
|
+
"",
|
54
|
+
"Github:",
|
55
|
+
"https://github.com/hyeon2006/sonolus-pjsekai-js",
|
56
|
+
].join("\n"),
|
57
57
|
ko: [
|
58
|
-
|
58
|
+
"프로젝트 세카이: 컬러풀 스테이지! 엔진을 Sonolus로 재현했습니다.",
|
59
59
|
`버전: ${exports.version}`,
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
].join(
|
60
|
+
"",
|
61
|
+
"Burrito#1000의 pjsekai 엔진에서 포크되었습니다.",
|
62
|
+
"https://github.com/NonSpicyBurrito/sonolus-pjsekai-engine",
|
63
|
+
"",
|
64
|
+
"깃허브:",
|
65
|
+
"https://github.com/hyeon2006/sonolus-pjsekai-js",
|
66
|
+
].join("\n"),
|
67
67
|
},
|
68
68
|
};
|
package/dist/index.d.cts
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
export { susToUSC } from
|
2
|
-
export { uscToLevelData } from
|
3
|
-
export * from
|
4
|
-
export { uscToUSC } from
|
5
|
-
export declare const version = "1.2.
|
1
|
+
export { susToUSC } from "./sus/convert.cjs";
|
2
|
+
export { uscToLevelData } from "./usc/convert.cjs";
|
3
|
+
export * from "./usc/index.cjs";
|
4
|
+
export { uscToUSC } from "./usc/revert.cjs";
|
5
|
+
export declare const version = "1.2.9";
|
6
6
|
export declare const databaseEngineItem: {
|
7
7
|
readonly name: "prosekaR";
|
8
8
|
readonly version: 13;
|
package/dist/sus/analyze.cjs
CHANGED
@@ -3,13 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.analyze = void 0;
|
4
4
|
const analyze = (sus) => {
|
5
5
|
const { lines, measureChanges, meta } = parse(sus);
|
6
|
-
|
7
|
-
const offset = -+(meta.get('WAVEOFFSET') || '0');
|
6
|
+
const offset = -+(meta.get("WAVEOFFSET") || "0");
|
8
7
|
if (Number.isNaN(offset))
|
9
|
-
throw new Error(
|
8
|
+
throw new Error("Unexpected offset");
|
10
9
|
const ticksPerBeat = getTicksPerBeat(meta);
|
11
10
|
if (!ticksPerBeat)
|
12
|
-
throw new Error(
|
11
|
+
throw new Error("Missing or unexpected ticks per beat");
|
13
12
|
const barLengths = getBarLengths(lines, measureChanges);
|
14
13
|
const toTick = getToTick(barLengths, ticksPerBeat);
|
15
14
|
const bpms = new Map();
|
@@ -20,29 +19,30 @@ const analyze = (sus) => {
|
|
20
19
|
const streams = new Map();
|
21
20
|
for (const [index, line] of lines.entries()) {
|
22
21
|
const [header, data] = line;
|
23
|
-
const measureOffset = measureChanges.find(([changeIndex]) => changeIndex <= index)?.[1] ??
|
22
|
+
const measureOffset = measureChanges.find(([changeIndex]) => changeIndex <= index)?.[1] ??
|
23
|
+
0;
|
24
24
|
// Time Scale Changes
|
25
|
-
if (header.length === 5 && header.startsWith(
|
25
|
+
if (header.length === 5 && header.startsWith("TIL")) {
|
26
26
|
timeScaleChanges.push(...toTimeScaleChanges(line, toTick));
|
27
27
|
continue;
|
28
28
|
}
|
29
29
|
// BPM
|
30
|
-
if (header.length === 5 && header.startsWith(
|
30
|
+
if (header.length === 5 && header.startsWith("BPM")) {
|
31
31
|
bpms.set(header.substring(3), +data);
|
32
32
|
continue;
|
33
33
|
}
|
34
34
|
// BPM Changes
|
35
|
-
if (header.length === 5 && header.endsWith(
|
35
|
+
if (header.length === 5 && header.endsWith("08")) {
|
36
36
|
bpmChanges.push(...toBpmChanges(line, measureOffset, bpms, toTick));
|
37
37
|
continue;
|
38
38
|
}
|
39
39
|
// Tap Notes
|
40
|
-
if (header.length === 5 && header[3] ===
|
40
|
+
if (header.length === 5 && header[3] === "1") {
|
41
41
|
tapNotes.push(...toNotes(line, measureOffset, toTick));
|
42
42
|
continue;
|
43
43
|
}
|
44
44
|
// Streams
|
45
|
-
if (header.length === 6 && (header[3] ===
|
45
|
+
if (header.length === 6 && (header[3] === "3" || header[3] === "9")) {
|
46
46
|
const key = `${header[5]}-${header[3]}`;
|
47
47
|
const stream = streams.get(key);
|
48
48
|
if (stream) {
|
@@ -57,7 +57,7 @@ const analyze = (sus) => {
|
|
57
57
|
continue;
|
58
58
|
}
|
59
59
|
// Directional Notes
|
60
|
-
if (header.length === 5 && header[3] ===
|
60
|
+
if (header.length === 5 && header[3] === "5") {
|
61
61
|
directionalNotes.push(...toNotes(line, measureOffset, toTick));
|
62
62
|
continue;
|
63
63
|
}
|
@@ -79,11 +79,11 @@ const parse = (sus) => {
|
|
79
79
|
const measureChanges = [];
|
80
80
|
const meta = new Map();
|
81
81
|
for (const line of sus
|
82
|
-
.split(
|
82
|
+
.split("\n")
|
83
83
|
.map((line) => line.trim())
|
84
|
-
.filter((line) => line.startsWith(
|
85
|
-
const isLine = line.includes(
|
86
|
-
const index = line.indexOf(isLine ?
|
84
|
+
.filter((line) => line.startsWith("#"))) {
|
85
|
+
const isLine = line.includes(":");
|
86
|
+
const index = line.indexOf(isLine ? ":" : " ");
|
87
87
|
if (index === -1)
|
88
88
|
continue;
|
89
89
|
const left = line.substring(1, index).trim();
|
@@ -91,7 +91,7 @@ const parse = (sus) => {
|
|
91
91
|
if (isLine) {
|
92
92
|
lines.push([left, right]);
|
93
93
|
}
|
94
|
-
else if (left ===
|
94
|
+
else if (left === "MEASUREBS") {
|
95
95
|
measureChanges.unshift([lines.length, +right]);
|
96
96
|
}
|
97
97
|
else {
|
@@ -105,7 +105,7 @@ const parse = (sus) => {
|
|
105
105
|
};
|
106
106
|
};
|
107
107
|
const getTicksPerBeat = (meta) => {
|
108
|
-
const request = meta.get(
|
108
|
+
const request = meta.get("REQUEST");
|
109
109
|
if (!request)
|
110
110
|
return;
|
111
111
|
if (!request.startsWith('"ticks_per_beat ') || !request.endsWith('"'))
|
@@ -118,7 +118,7 @@ const getBarLengths = (lines, measureChanges) => {
|
|
118
118
|
const [header, data] = line;
|
119
119
|
if (header.length !== 5)
|
120
120
|
continue;
|
121
|
-
if (!header.endsWith(
|
121
|
+
if (!header.endsWith("02"))
|
122
122
|
continue;
|
123
123
|
const measure = +header.substring(0, 3) +
|
124
124
|
(measureChanges.find(([changeIndex]) => changeIndex <= index)?.[1] ?? 0);
|
@@ -143,7 +143,7 @@ const getToTick = (barLengths, ticksPerBeat) => {
|
|
143
143
|
return (measure, p, q) => {
|
144
144
|
const bar = bars.find((bar) => measure >= bar.measure);
|
145
145
|
if (!bar)
|
146
|
-
throw new Error(
|
146
|
+
throw new Error("Unexpected missing bar");
|
147
147
|
return (bar.ticks +
|
148
148
|
(measure - bar.measure) * bar.ticksPerMeasure +
|
149
149
|
(p * bar.ticksPerMeasure) / q);
|
@@ -155,20 +155,22 @@ const toBpmChanges = (line, measureOffset, bpms, toTick) => toRaws(line, measure
|
|
155
155
|
}));
|
156
156
|
const toTimeScaleChanges = ([, data], toTick) => {
|
157
157
|
if (!data.startsWith('"') || !data.endsWith('"'))
|
158
|
-
throw new Error(
|
158
|
+
throw new Error("Unexpected time scale changes");
|
159
159
|
return data
|
160
160
|
.slice(1, -1)
|
161
|
-
.split(
|
161
|
+
.split(",")
|
162
162
|
.map((segment) => segment.trim())
|
163
163
|
.filter((segment) => !!segment)
|
164
164
|
.map((segment) => {
|
165
165
|
const [l, rest] = segment.split("'");
|
166
|
-
const [m, r] = rest.split(
|
166
|
+
const [m, r] = rest.split(":");
|
167
167
|
const measure = +l;
|
168
168
|
const tick = +m;
|
169
169
|
const timeScale = +r;
|
170
|
-
if (Number.isNaN(measure) ||
|
171
|
-
|
170
|
+
if (Number.isNaN(measure) ||
|
171
|
+
Number.isNaN(tick) ||
|
172
|
+
Number.isNaN(timeScale))
|
173
|
+
throw new Error("Unexpected time scale change");
|
172
174
|
return {
|
173
175
|
tick: toTick(measure, 0, 1) + tick,
|
174
176
|
timeScale,
|
@@ -210,7 +212,7 @@ const toSlides = (stream) => {
|
|
210
212
|
const toRaws = ([header, data], measureOffset, toTick) => {
|
211
213
|
const measure = +header.substring(0, 3) + measureOffset;
|
212
214
|
return (data.match(/.{2}/g) ?? [])
|
213
|
-
.map((value, i, values) => value !==
|
215
|
+
.map((value, i, values) => value !== "00" && {
|
214
216
|
tick: toTick(measure, i, values.length),
|
215
217
|
value,
|
216
218
|
})
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "sonolus-pjsekai-js",
|
3
|
-
"version": "1.2.
|
3
|
+
"version": "1.2.9",
|
4
4
|
"description": "A recreation of Project Sekai: Colorful Stage! engine in Sonolus",
|
5
5
|
"type": "module",
|
6
6
|
"files": [
|
@@ -20,20 +20,16 @@
|
|
20
20
|
"dev:watch": "sonolus-cli --dev ./watch",
|
21
21
|
"dev:preview": "sonolus-cli --dev ./preview",
|
22
22
|
"dev:tutorial": "sonolus-cli --dev ./tutorial",
|
23
|
-
"format": "
|
24
|
-
"lint": "
|
25
|
-
"lint-fix": "
|
23
|
+
"format": "biome format --write",
|
24
|
+
"lint": "biome lint",
|
25
|
+
"lint-fix": "biome lint --write",
|
26
|
+
"biome": "biome check",
|
26
27
|
"build": "tsc -p ./lib && sonolus-cli --build ./play && sonolus-cli --build ./watch && sonolus-cli --build ./preview && sonolus-cli --build ./tutorial && node ./lib/build.mjs"
|
27
28
|
},
|
28
29
|
"devDependencies": {
|
30
|
+
"@biomejs/biome": "2.0.6",
|
29
31
|
"@sonolus/sonolus.js": "~9.5.6",
|
30
|
-
"
|
31
|
-
"eslint": "^9.27.0",
|
32
|
-
"eslint-config-prettier": "^10.1.5",
|
33
|
-
"prettier": "^3.5.3",
|
34
|
-
"prettier-plugin-organize-imports": "^4.1.0",
|
35
|
-
"typescript": "~5.8.3",
|
36
|
-
"typescript-eslint": "^8.33.0"
|
32
|
+
"typescript": "~5.8.3"
|
37
33
|
},
|
38
34
|
"dependencies": {
|
39
35
|
"@sonolus/core": "~7.13.2"
|